<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Conal Elliott &#187; proof</title>
	<atom:link href="http://conal.net/blog/tag/proof/feed" rel="self" type="application/rss+xml" />
	<link>http://conal.net/blog</link>
	<description>Inspirations &#38; experiments, mainly about denotative/functional programming in Haskell</description>
	<lastBuildDate>Thu, 25 Jul 2019 18:15:11 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=4.1.17</generator>
	<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=conal&amp;popout=1&amp;url=http%3A%2F%2Fconal.net%2Fblog%2F&amp;language=en_US&amp;category=text&amp;title=Conal+Elliott&amp;description=Inspirations+%26amp%3B+experiments%2C+mainly+about+denotative%2Ffunctional+programming+in+Haskell&amp;tags=blog" type="text/html" />
	<item>
		<title>Is program proving viable and useful?</title>
		<link>http://conal.net/blog/posts/is-program-proving-viable-and-useful</link>
		<comments>http://conal.net/blog/posts/is-program-proving-viable-and-useful#comments</comments>
		<pubDate>Sun, 03 Jan 2010 03:21:48 +0000</pubDate>
		<dc:creator><![CDATA[Conal]]></dc:creator>
				<category><![CDATA[Functional programming]]></category>
		<category><![CDATA[creativity]]></category>
		<category><![CDATA[proof]]></category>
		<category><![CDATA[simplicity]]></category>
		<category><![CDATA[specification]]></category>

		<guid isPermaLink="false">http://conal.net/blog/?p=94</guid>
		<description><![CDATA[Is program proving a viable and useful endeavor? Does it create more problems than it solves? Today I participated in a reddit discussion thread. The discussion brought up some issues I care about, and I think others will care also. Although I&#8217;m quoting from another person whose viewpoint may contrast with mine, I mean no [&#8230;]]]></description>
				<content:encoded><![CDATA[<!-- 

Title: Is program proving viable and useful?

Tags: specification, proof, creativity, simplicity

URL: http://conal.net/blog/posts/is-program-proving-viable-and-useful/

-->

<!-- references -->

<!--
**Edits**:

* 2009-02-09: just fiddling around
-->

<!-- without a comment or something here, the last item above becomes a paragraph -->

<p>Is program proving a viable and useful endeavor?
Does it create more problems than it solves?</p>

<p>Today I participated in <a href="http://www.reddit.com/r/programming/comments/akhvr/reflections_on_a_holy_grail_functional_reactive/c0i2gsd">a reddit discussion  thread</a>.
The discussion brought up some issues I care about, and I think others will care also.</p>

<p>Although I&#8217;m quoting from another person whose viewpoint may contrast with mine, I mean no insult or disrespect to him.
I think his views are fairly common, and I appreciate his putting them into writing and stimulating me to put some of mine into writing as well.</p>

<blockquote>
  <p>[&#8230;] you could specify the behavior it should have precisely.
  However in this case (and in most practical cases that aren&#8217;t tricky algorithms actually) the mathematical spec is not much shorter than the implementation.
  So meeting the spec does not help, the spec is just as likely to be wrong/incomplete as the implementation.
  With wrong/incomplete I mean that even if you meet the spec you don&#8217;t attain your goal.</p>
</blockquote>

<p>I like the observation that precise specifications can be as complex and difficult to get correct as precise programs.
And indeed specification complexity is problematic.
Rather than give up on precision, my own interest is in finding simpler and clearer ways to think about things so that specifications can be quite simple.
Thus my focus on simple and precise semantic models.
One example is as given in <em><a href="http://conal.net/papers/push-pull-frp/" title="Paper">Push-pull functional reactive programming</a></em>.
I&#8217;m proud of the simplicity of this specification and of how clearly it shows what parts of the model could use improving.
(The <code>Event</code> type doesn&#8217;t follow the <a href="">type class morphism</a> principle, and indeed has difficulty in practice.)
And since such semantics-based software design methods are still in their infancy, I agree that it&#8217;s usually more practical to abandon preciseness in software development.</p>

<p>For more examples of formally simple specifications, see the papers <em><a href="http://conal.net/blog/posts/denotational-design-with-type-class-morphisms/" title="blog post">Denotational design with type class morphisms</a></em> and <em><a href="http://conal.net/blog/posts/beautiful-differentiation/" title="blog post">Beautiful differentiation</a></em>.</p>

<p>I suspect the crux of the issue here is that <em>combining precision and simplicity is very difficult</em> &#8212; whether for specifications or programs (or for many other other human endeavors).</p>

<blockquote>
  <p><em>Any intelligent fool can make things bigger and more complex &#8230; it takes a touch of genius &#8212; and a lot of courage &#8212; to   move in the opposite direction.</em> &#8211; Albert Einstein</p>
</blockquote>

<p>We had been writing informal/imprecise &#8220;programs&#8221; for a long time before computers were invented, as various kinds of instructions/recipies.
With mechanization of program handling in the 1940s came the requirement of precision.
Since simple precision is difficult (according to my hypothesis), and precision is required, simplicity usually loses out.
So our history of executably-precise programs is populated mostly by complexity.</p>

<blockquote>
  <p><em>I conclude that there are two ways of constructing a software design: One way is to make it so simple that there are   obviously no deficiencies, and the other way is make it so complicated that there are no obvious deficiencies.
  The first   method is far more difficult.</em>  &#8211; C.A.R. Hoare, <a href="http://scifac.ru.ac.za/cspt/hoare.htm">The Emperor&#8217;s Old Clothes, Turing Award lecture,   1980</a></p>
</blockquote>

<p>As much as one assumes that the future is bound to perpetuate the past, one might believe that we will <em>never</em> escape complexity.
In my own creative process, I like to distinguish between the notion of <em>necessarily true</em> and merely <em>historically true</em>.
I understand progress itself to be about this distinction &#8212; the overturning of the historically true that turns out (often surprisingly) not to be necessarily true.</p>

<p>What about <em>specification</em>?
Are precise specifications <em>necessarily</em> complex, or merely <em>historically</em> complex?
(I.e., <em>must</em> we sit by while the future repeats the complexity of the past?)  This question I see as even more unexplored than the same question for programs, because we have not been required to work with formal specifications nearly as much as with formal programs.
Even so, some people have <em>chosen</em> to work on precise specification and so some progress has been made in improving their simplicity, and I&#8217;m optimistic about the future.
Optimistic enough to devote some of my life energy to the search.</p>

<blockquote>
  <p><em>Simplicity is the most difficult thing to secure in this world; it is the last limit of experience and the last effort of genius.</em> &#8211; George Sand</p>
  
  <p><em>Everything is vague to a degree you do not realize till you have tried to make it precise.</em> &#8211; Bertrand Russell</p>
</blockquote>

<p>I expect that future software developers will look back on our era as barbaric, the way we look at some of the medical practices of the past.
Of course, we&#8217;re doing the best we know how, just as past medical practitioners were.</p>

<p>I know people are apt to hear criticism/insult whether present or not, and I hope that these words of mine are not heard as such.
I appreciate both the current practitioners, doing their best with tools at hand, and the pioneer, groping toward the methods of the future.
Personally, I play both roles, and I&#8217;m guessing you do as well, perhaps differing only in balance.
I urge us all to appreciate and respect each other more as we muddle on.</p>
<p><a href="http://conal.net/blog/?flattrss_redirect&amp;id=94&amp;md5=903baaea1bc25d0b20de74f033b03dac"><img src="http://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white.png" srcset="http://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white.png, http://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white@2x.png 2xhttp://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white.png, http://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white@3x.png 3x" alt="Flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://conal.net/blog/posts/is-program-proving-viable-and-useful/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=conal&amp;popout=1&amp;url=http%3A%2F%2Fconal.net%2Fblog%2Fposts%2Fis-program-proving-viable-and-useful&amp;language=en_GB&amp;category=text&amp;title=Is+program+proving+viable+and+useful%3F&amp;description=Is+program+proving+a+viable+and+useful+endeavor%3F+Does+it+create+more+problems+than+it+solves%3F+Today+I+participated+in+a+reddit+discussion+thread.+The+discussion+brought+up+some+issues...&amp;tags=creativity%2Cproof%2Csimplicity%2Cspecification%2Cblog" type="text/html" />
	</item>
		<item>
		<title>Enhancing a Zip</title>
		<link>http://conal.net/blog/posts/enhancing-a-zip</link>
		<comments>http://conal.net/blog/posts/enhancing-a-zip#comments</comments>
		<pubDate>Sun, 16 Nov 2008 01:09:03 +0000</pubDate>
		<dc:creator><![CDATA[Conal]]></dc:creator>
				<category><![CDATA[Functional programming]]></category>
		<category><![CDATA[applicative functor]]></category>
		<category><![CDATA[fold]]></category>
		<category><![CDATA[functor]]></category>
		<category><![CDATA[proof]]></category>
		<category><![CDATA[type class morphism]]></category>
		<category><![CDATA[zip]]></category>

		<guid isPermaLink="false">http://conal.net/blog/?p=61</guid>
		<description><![CDATA[This post is part four of the zip folding series inspired by Max Rabkin&#8217;s Beautiful folding post. I meant to write one little post, but one post turned into four. When I sense that something can be made simpler/clearer, I can&#8217;t leave it be. To review: Part One related Max&#8217;s data representation of left folds [&#8230;]]]></description>
				<content:encoded><![CDATA[<!-- 

Title: Enhancing a Zip

Tags: applicative functor, functor, fold, zip, type class morphism, proof

URL: http://conal.net/blog/posts/enhancing-a-zip/

-->

<!-- references -->

<!-- teaser -->

<p>This post is part four of the zip folding series inspired by Max Rabkin&#8217;s <em><a href="http://squing.blogspot.com/2008/11/beautiful-folding.html" title="blog post by Max Rabkin">Beautiful folding</a></em> post.
I meant to write one little post, but one post turned into four.
When I sense that something can be made simpler/clearer, I can&#8217;t leave it be.</p>

<p>To review:</p>

<ul>
<li><a href="http://conal.net/blog/posts/another-lovely-example-of-type-class-morphisms" title="blog post">Part One</a> related Max&#8217;s data representation of left folds to type class morphisms, a pattern that&#8217;s been steering me lately toward natural (inevitable) design of libraries.</li>
<li><a href="http://conal.net/blog/posts/more-beautiful-fold-zipping" title="blog post">Part Two</a> simplified that representation to help get to the essence of zipping, and in doing so lost the expressiveness necessary to define <code>Functor</code>and <code>Applicative</code> instaces.</li>
<li><a href="http://conal.net/blog/posts/proofs-for-left-fold-zipping/" title="blog post">Part Three</a> proved the suitability of the zipping definitions in <a href="http://conal.net/blog/posts/more-beautiful-fold-zipping" title="blog post">Part Two</a>.</li>
</ul>

<p>This post shows how to restore the <code>Functor</code> and <code>Applicative</code> (very useful composition tools) to folds but does so in a way that leaves the zipping functionality untouched.
This new layer is independent of folding and can be layered onto <em>any zippable type</em>.</p>

<p>You can <a href="http://hackage.haskell.org/cgi-bin/hackage-scripts/package/ZipFold" title="the ZipFold package">get the code</a> described below.</p>

<p><strong>Edits</strong>:</p>

<ul>
<li>2009-02-15: Simplified <code>WithCont</code>, collapsing two type parameters into one.  Added functor comment about <code>cfoldlc'</code>.</li>
</ul>

<!-- without a comment or something here, the last item above becomes a paragraph -->

<p><span id="more-61"></span></p>

<h3>What&#8217;s missing?</h3>

<p>Max&#8217;s fold type packages up the first two arguments of <code>foldl'</code> and adds on an post-fold step, as needed for <code>fmap</code>:</p>

<pre><code>data Fold b c = forall a. F (a -&gt; b -&gt; a) a (a -&gt; c)  -- clever version
</code></pre>

<p>The simpler, less clever version just has the two <code>foldl'</code> arguments, and no <code>forall</code>:</p>

<pre><code>data Fold b a = F (a -&gt; b -&gt; a) a                     -- simple version
</code></pre>

<p>Removing Max&#8217;s post-fold step gets to the essence of fold zipping but loses some useful composability.
In particular, we can no longer define <code>Functor</code> and <code>Applicative</code> instances.</p>

<p>The difference between the clever version and the simple one is a continuation and a <code>forall</code>, which we can write down as follows:</p>

<pre><code>data WithCont z c = forall a. WC (z a) (a -&gt; c)
</code></pre>

<p>The clever version is equivalent to the following:</p>

<pre><code>type FoldC b = WithCont (Fold b)
</code></pre>

<p>Interpreting a <code>FoldC</code> just interprets the <code>Fold</code> and then applies the continuation:</p>

<pre><code>cfoldlc :: FoldC b a -&gt; [b] -&gt; a
cfoldlc (WC f k) = k . cfoldl f
</code></pre>

<p>(In a more general setting, use <code>fmap</code> in place of <code>(.)</code> to give meaning to <code>WithCont</code>.)</p>

<p>Add a copy of <code>WithCont</code>, for reasons explained later, and use it for strict folds.</p>

<pre><code>data WithCont' z c = forall a. WC' (z a) (a -&gt; c)

type FoldC' b = WithCont' (Fold b)

cfoldlc' :: FoldC' b a -&gt; [b] -&gt; a
cfoldlc' (WC' f k) = k . cfoldl' f
</code></pre>

<h3>From <code>Zip</code> to <code>Functor</code> and <code>Applicative</code></h3>

<p>It&#8217;s now a simple matter to recover the lost <code>Functor</code> and <code>Applicative</code> instances, for both non-strict and strict zipping.
The <code>Applicative</code> instances rely on zippability:</p>

<pre><code>instance Functor (WithCont z) where
  fmap g (WC f k) = WC f (g . k)

instance Zip z =&gt; Applicative (WithCont z) where
  pure a = WC undefined (const a)
  WC hf hk &lt;*&gt; WC xf xk =
    WC (hf `zip` xf) ( (a,a') -&gt; (hk a) (xk a'))


instance Functor (WithCont' z) where
  fmap g (WC' f k) = WC' f (g . k)

instance Zip' z =&gt; Applicative (WithCont' z) where
  pure a = WC' undefined (const a)
  WC' hf hk &lt;*&gt; WC' xf xk =
    WC' (hf `zip'` xf) ( (P a a') -&gt; (hk a) (xk a'))
</code></pre>

<p>Now the reason for the duplicate <code>WithCont</code> definition becomes apparent.
Instance selection in Haskell is based entirely on the &#8220;head&#8221; of an instance.
If both <code>Applicative</code> instances used <code>WithCont</code>, the compiler would consider them to overlap.</p>

<h3>Morphism proofs</h3>

<p>It remains to prove that our interpretation functions are <code>Functor</code> and <code>Applicative</code> morphisms.
I&#8217;ll show the non-strict proofs.
The strict morphism proofs go through similarly.</p>

<h4>Functor</h4>

<p>The <code>Functor</code> morphism property for non-strict folding:</p>

<pre><code>cfoldlc (fmap g wc) == fmap g (cfoldlc wc)
</code></pre>

<p>Adding some structure:</p>

<pre><code>cfoldlc (fmap g (WC f k)) == fmap g (cfoldlc (WC f k))
</code></pre>

<p>Proof:</p>

<pre><code>cfoldlc (fmap g (WC f k))

  == {- fmap on WithCont -}

cfoldlc (WC f (g . k))

  == {- cfoldlc def -}

(g . k) . cfoldl f

  == {- associativity of (.)  -}

g . (k . cfoldl f)

  == {- cfoldl def -}

g . cfoldlc (WC f k)

  == {- fmap on functions -}

fmap g (cfoldlc (WC f k))
</code></pre>

<h4>Applicative</h4>

<p><code>Applicative</code> has two methods, so <code>cfoldlc</code> must satisfy two morphism properties.
One for <code>pure</code>:</p>

<pre><code>cfoldlc (pure a) == pure a
</code></pre>

<p>Proof:</p>

<pre><code>cfoldlc (pure a)

  == {- pure on WithCont -}

cfoldlc (WC undefined (const a))

  == {- cfoldlc def -}

const a . cfoldl undefined

  == {- property of const -}

const a

  == {- pure on functions -}

pure a
</code></pre>

<p>And one for <code>(&lt;*&gt;)</code>:</p>

<pre><code>cfoldlc (wch &lt;*&gt; wcx) == cfoldlc wch &lt;*&gt; cfoldlc wcx
</code></pre>

<p>Adding structure:</p>

<pre><code>cfoldlc ((WC hf hk) &lt;*&gt; (WC xf xk)) == cfoldlc (WC hf hk) &lt;*&gt; cfoldlc (WC xf xk)
</code></pre>

<p>Proof:</p>

<pre><code>cfoldlc ((WC hf hk) &lt;*&gt; (WC xf xk))

  == {- (&lt;*&gt;) on WithCont -}

cfoldlc (WC (hf `zip` xf) ( (a,a') -&gt; (hk a) (xk a')))

  == {- cfoldlc def -}

( (a,a') -&gt; (hk a) (xk a')) . cfoldl (hf `zip` xf)

  == {- Zip morphism law for Fold -}

( (a,a') -&gt; (hk a) (xk a')) . (cfoldl hf `zip` cfoldl xf)

  == {- zip def on functions -}

( (a,a') -&gt; (hk a) (xk a')) .  bs -&gt; (cfoldl hf bs, cfoldl xf bs)

  == {- (.) def -}

 bs -&gt; (hk (cfoldl hf bs)) (xk (cfoldl xf bs))

  == {- (&lt;*&gt;) on functions -}

(hk . cfoldl hf bs) &lt;*&gt; (xk . cfoldl xf)

  == {- cfoldlc def, twice -}

cfoldlc (WC hf hk) &lt;*&gt; cfoldlc (WC xf xk)
</code></pre>

<p>That&#8217;s it.</p>

<p>I like that <code>WithCont</code> allows composing the morphism proofs, in addition to the implementations.</p>
<p><a href="http://conal.net/blog/?flattrss_redirect&amp;id=61&amp;md5=5eb0b4e41def72139d912156d5ec8d84"><img src="http://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white.png" srcset="http://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white.png, http://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white@2x.png 2xhttp://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white.png, http://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white@3x.png 3x" alt="Flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://conal.net/blog/posts/enhancing-a-zip/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=conal&amp;popout=1&amp;url=http%3A%2F%2Fconal.net%2Fblog%2Fposts%2Fenhancing-a-zip&amp;language=en_GB&amp;category=text&amp;title=Enhancing+a+Zip&amp;description=This+post+is+part+four+of+the+zip+folding+series+inspired+by+Max+Rabkin%26%238217%3Bs+Beautiful+folding+post.+I+meant+to+write+one+little+post%2C+but+one+post+turned+into+four....&amp;tags=applicative+functor%2Cfold%2Cfunctor%2Cproof%2Ctype+class+morphism%2Czip%2Cblog" type="text/html" />
	</item>
		<item>
		<title>Proofs for left fold zipping</title>
		<link>http://conal.net/blog/posts/proofs-for-left-fold-zipping</link>
		<comments>http://conal.net/blog/posts/proofs-for-left-fold-zipping#comments</comments>
		<pubDate>Sat, 15 Nov 2008 21:30:31 +0000</pubDate>
		<dc:creator><![CDATA[Conal]]></dc:creator>
				<category><![CDATA[Functional programming]]></category>
		<category><![CDATA[fold]]></category>
		<category><![CDATA[proof]]></category>
		<category><![CDATA[zip]]></category>

		<guid isPermaLink="false">http://conal.net/blog/?p=60</guid>
		<description><![CDATA[The post More beautiful fold zipping showed a formulation of left-fold zipping, simplified from the ideas in Max Rabkin&#8217;s Beautiful folding. I claimed that the semantic functions are the inevitable (natural) ones in that they preserve zipping stucture. This post gives the promised proofs. The correctness of fold zipping can be expressed as follows. Is [&#8230;]]]></description>
				<content:encoded><![CDATA[<!-- 

Title: Proofs for left fold zipping

Tags: fold, zip, proof

URL: http://conal.net/blog/posts/proofs-for-left-zip-folding/

-->

<!-- references -->

<!-- teaser -->

<p>The post <em><a href="http://conal.net/blog/posts/more-beautiful-fold-zipping" title="blog post">More beautiful fold zipping</a></em> showed a formulation of left-fold zipping, simplified from the ideas in Max Rabkin&#8217;s <em><a href="http://squing.blogspot.com/2008/11/beautiful-folding.html" title="blog post by Max Rabkin">Beautiful folding</a></em>.  I claimed that the semantic functions are the inevitable (natural) ones in that they preserve zipping stucture.
This post gives the promised proofs.</p>

<!--
**Edits**:

* 2008-02-09: just fiddling around
-->

<!-- without a comment or something here, the last item above becomes a paragraph -->

<p><span id="more-60"></span></p>

<p>The correctness of fold zipping can be expressed as follows.
Is <code>cfoldl</code> a <code>Zip</code> morphism, and is <code>cfoldl'</code> a <code>Zip'</code> morphism?
(See <em><a href="http://conal.net/blog/posts/more-beautiful-fold-zipping" title="blog post">More beautiful fold zipping</a></em> for definitions of these functions and classes, and see <em><a href="http://conal.net/blog/posts/simplifying-semantics-with-type-class-morphisms" title="blog post">Simplifying semantics with type class morphisms</a></em> for the notion of type class morphisms.)</p>

<h3>Non-strict</h3>

<p>The non-strict version is simpler, though less useful.
We want to prove</p>

<pre><code>cfoldl (f `zip` f') == cfoldl f `zip` cfoldl f'
</code></pre>

<p>First, substitute the definition of <code>zip</code> for functions.</p>

<pre><code>instance Zip ((-&gt;) u) where zip = liftA2 (,)
</code></pre>

<p>This definition is a standard one for zipping applicative functors.
Given the <code>Applicative</code> instance for functions, this <code>Zip</code> instance is equivalent to</p>

<pre><code>instance Zip ((-&gt;) u) where r `zip` s =  u -&gt; (r u, s u)
</code></pre>

<p>So the <code>Zip</code> morphism property becomes</p>

<pre><code>cfoldl (f `zip` f') bs == (cfoldl f bs, cfoldl f' bs)
</code></pre>

<p>We&#8217;ll want some structure to our folds as well:</p>

<pre><code>cfoldl (F op e `zip` F op' e') bs
  == (cfoldl (F op e) bs, cfoldl (F op' e') bs)
</code></pre>

<p>Simplify the LHS:</p>

<pre><code>cfoldl (F op e `zip` F op' e') bs

  == {- Fold zip def -}

cfoldl (F op'' (e,e')) bs
  where (a,a') `op''` b = (a `op` b, a' `op'` b)

  == {- cfoldl def -}

foldl op'' (e,e') bs
  where (a,a') `op''` b = (a `op` b, a' `op'` b)
</code></pre>

<p>Then simplify the RHS:</p>

<pre><code>(cfoldl (F op e) bs, cfoldl (F op' e') bs)

  == {- cfoldl def -}

(foldl op e bs, foldl op' e' bs)
</code></pre>

<p>So the morphism law becomes</p>

<pre><code>foldl op'' (e,e') bs == (foldl op e bs, foldl op' e' bs)
  where
    (a,a') `op''` b = (a `op` b, a' `op'` b)
</code></pre>

<p>We&#8217;ll prove this form inductively in the list <code>bs</code>, using the definition of <code>foldl</code>:</p>

<pre><code>foldl :: (a -&gt; b -&gt; a) -&gt; a -&gt; [b] -&gt; a
foldl op a []     = a
foldl op a (b:bs) = foldl op (a `op` b) bs
</code></pre>

<p>First, empty lists.</p>

<pre><code>foldl op'' (e,e') [] where op'' = ...

  == {- foldl def  -}

(e,e')

  == {- foldl def, twice -}

(foldl op e [], foldl op' e' [])
</code></pre>

<p>Next, non-empty lists.</p>

<pre><code>foldl op'' (e,e') (b:bs) where op'' = ...

  == {- foldl def -}

foldl op'' ((e,e') `op''` b) bs where op'' = ...

  == {- op'' definition -}

foldl op'' (e `op` b, e' `op'` b) bs where op'' = ...

  == {- induction hypothesis -}

(foldl op (e `op` b) bs, foldl op' (e' `op'` b) bs)

  == {- foldl def, twice -}

(foldl op e (b:bs), foldl op' e' (b:bs))
</code></pre>

<h3>Strict</h3>

<p>The morphism law:</p>

<pre><code>cfoldl' (f `zip'` f') == cfoldl' f `zip'` cfoldl' f'
</code></pre>

<p>which simplifies to</p>

<pre><code>foldl' op'' (P e e') bs == P (foldl' op e bs) (foldl' op' e' bs)
  where
    P a a' `op''` b = P (a `op` b) (a' `op'` b)
</code></pre>

<p>This property can be proved similarly to the non-strict version.
The new aspect is manipulating the use of <code>seq</code>.</p>

<p>Again, use induction on lists, guided by the fold definition:</p>

<pre><code>foldl' :: (a -&gt; b -&gt; a) -&gt; a -&gt; [b] -&gt; a
foldl' op a []     = a
foldl' op a (b:bs) =
  let a' = a `op` b in a' `seq` foldl' f a' bs
</code></pre>

<p>First, empty lists.</p>

<pre><code>foldl op'' (P e e') [] where op'' = ...

  == {- foldl def  -}

P e e'

  == {- foldl def, twice -}

P (foldl op e []) (foldl op' e' [])
</code></pre>

<p>Next, non-empty lists.
For simplicity, I&#8217;ll inline the <code>let</code> in the definition of <code>foldl'</code> (which affects performance but not meaning):</p>

<pre><code>foldl' op'' (P e e') (b:bs) where op'' = ...

  == {- foldl' def -}

((P e e') `op''` b) `seq`
foldl' op'' ((P e e') `op''` b) bs where op'' = ...

  == {- op'' definition -}

P (e `op` b) (e' `op'` b) `seq`
foldl' op'' (P (e `op` b) (e' `op'` b)) bs

  == {- induction hypothesis -}

P (e `op` b) (e' `op'` b) `seq`
P (foldl' op (e `op` b) bs) (foldl' op' (e' `op` b) bs)

  == {- P strictness -}

P (e `op` b) (e' `op'` b) `seq`
P ((e  `op` b) `seq` foldl' op  (e  `op` b) bs)
  ((e' `op` b) `seq` foldl' op' (e' `op` b) bs)

  == {- foldl' def, twice -}

P (foldl' op e (b:bs)) (foldl' op' e' (b:bs))
</code></pre>

<p>That&#8217;s it.</p>
<p><a href="http://conal.net/blog/?flattrss_redirect&amp;id=60&amp;md5=715461026a2854a157ac9887e1eb8b59"><img src="http://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white.png" srcset="http://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white.png, http://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white@2x.png 2xhttp://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white.png, http://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white@3x.png 3x" alt="Flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://conal.net/blog/posts/proofs-for-left-fold-zipping/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=conal&amp;popout=1&amp;url=http%3A%2F%2Fconal.net%2Fblog%2Fposts%2Fproofs-for-left-fold-zipping&amp;language=en_GB&amp;category=text&amp;title=Proofs+for+left+fold+zipping&amp;description=The+post+More+beautiful+fold+zipping+showed+a+formulation+of+left-fold+zipping%2C+simplified+from+the+ideas+in+Max+Rabkin%26%238217%3Bs+Beautiful+folding.+I+claimed+that+the+semantic+functions+are+the+inevitable...&amp;tags=fold%2Cproof%2Czip%2Cblog" type="text/html" />
	</item>
	</channel>
</rss>
