<?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; zip</title>
	<atom:link href="http://conal.net/blog/tag/zip/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>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>
		<item>
		<title>More beautiful fold zipping</title>
		<link>http://conal.net/blog/posts/more-beautiful-fold-zipping</link>
		<comments>http://conal.net/blog/posts/more-beautiful-fold-zipping#comments</comments>
		<pubDate>Sat, 15 Nov 2008 07:24:21 +0000</pubDate>
		<dc:creator><![CDATA[Conal]]></dc:creator>
				<category><![CDATA[Functional programming]]></category>
		<category><![CDATA[fold]]></category>
		<category><![CDATA[zip]]></category>

		<guid isPermaLink="false">http://conal.net/blog/?p=59</guid>
		<description><![CDATA[My previous post, Another lovely example of type class morphisms, placed some standard structure around Max Rabkin&#8217;s Beautiful folding, using type class morphisms to confirm that the Functor and Applicative instances agreed with their inevitable meanings. In the process of working out the Applicative case, I realized the essence of fold zipping was getting a [&#8230;]]]></description>
				<content:encoded><![CDATA[<!-- 

Title: More beautiful fold zipping

Tags: fold, zip

URL: http://conal.net/blog/posts/more-beautiful-fold-zipping

-->

<!-- references -->

<!-- teaser -->

<p>My previous post, <em><a href="http://conal.net/blog/posts/another-lovely-example-of-type-class-morphisms" title="blog post">Another lovely example of type class morphisms</a></em>, placed some standard structure around 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>, using <a href="http://conal.net/blog/posts/simplifying-semantics-with-type-class-morphisms" title="blog post">type class morphisms</a> to confirm that the <code>Functor</code> and <code>Applicative</code> instances agreed with their inevitable meanings.</p>

<p>In the process of working out the <code>Applicative</code> case, I realized the essence of fold zipping was getting a bit obscured.
This post simplifies Max&#8217;s <code>Fold</code> data type a bit and shows how to zip strict left folds in the simpler setting.
You can <a href="http://hackage.haskell.org/cgi-bin/hackage-scripts/package/ZipFold" title="the ZipFold package">get the code</a> described here.</p>

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

<ul>
<li>2008-11-15: I renamed the <code>Pair</code> and <code>Pair'</code> classes to <code>Zip</code> and <code>Zip'</code>.</li>
</ul>

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

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

<h3>A simpler fold</h3>

<p>The strict left-folding functional is</p>

<pre><code>foldl' :: (a -&gt; b -&gt; a) -&gt; a -&gt; [b] -&gt; a
</code></pre>

<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>A 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>I&#8217;ll use this simpler version for zipping and later enhance it for <code>fmap</code>.</p>

<p>The strict interpretation of <code>Fold</code> simply unpacks and folds:</p>

<pre><code>cfoldl' :: Fold b a -&gt; [b] -&gt; a
cfoldl' (F op e) = foldl' op e
</code></pre>

<p>Zipping is then just a simplification of the <code>(&lt;*&gt;)</code> definition in <a href="http://conal.net/blog/posts/another-lovely-example-of-type-class-morphisms" title="blog post">the previous post</a>.
As before, <code>P</code> is a type and constructor of strict pairs.</p>

<pre><code>data P c c' = P !c !c'

zipF' :: Fold b a -&gt; Fold b a' -&gt; Fold b (P a a')
F op e `zipF'` F op' e' = F op'' (P e e')
 where
   P a a' `op''` b = P (a `op` b) (a' `op'` b)
</code></pre>

<p>We can also define non-strict counterparts:</p>

<pre><code>cfoldl :: Fold b a -&gt; [b] -&gt; a
cfoldl (F op e) = foldl op e

zipF :: Fold b a -&gt; Fold b a' -&gt; Fold b (a,a')
F op e `zipF` F op' e' = F op'' (e,e')
 where
   (a,a') `op''` b = (a `op` b, a' `op'` b)
</code></pre>

<h3>More type classes &#8230;</h3>

<p>A <a href="http://conal.net/blog/posts/simplifying-semantics-with-type-class-morphisms" title="blog post">previous post</a> suggested a criterion for inevitability of interpretation functions like <code>cfoldl</code> and <code>cfoldl'</code>.
Whatever class instances exists for the source type (<code>Fold</code> here), interpretation functions should be
&#8220;type class morphisms&#8221; for those classes, which loosely means that the meaning of a method is the same method on the meaning.</p>

<p>Where&#8217;s the type class for our simplified <code>Fold</code>?
It lacks the magic ingredient Max added to make it a <code>Functor</code> and an <code>Applicative</code>, namely the post-fold step.</p>

<p>However, there&#8217;s <a href="http://hackage.haskell.org/packages/archive/TypeCompose/latest/doc/html/Data-Pair.html" title="module from the TypeCompose package">another class</a> that&#8217;s just the thing:</p>

<pre><code>class Zip f where zip :: f a -&gt; f b -&gt; f (a,b)
</code></pre>

<p>(I&#8217;ve used this class with type representations and user interfaces.)</p>

<p>The <code>Zip</code> class from <code>TypeCompose</code> is almost identical to <a href="http://hackage.haskell.org/packages/archive/category-extras/latest/doc/html/Control-Functor-Zip.html" title="module from the category-extras package">the <code>Zip</code> class</a> in <code>category-extras</code>.
The latter class requires <code>Functor</code>, however, which is too restrictive for the simplified <code>Fold</code> type.</p>

<p>Our <em>non-strict</em> left folds have a <code>Zip</code> instance:</p>

<pre><code>instance Zip (Fold b) where zip = zipF
</code></pre>

<p>For strict folds, define a strict variant on <code>Zip</code>:</p>

<pre><code>class Zip' f where zip' :: f a -&gt; f b -&gt; f (P a b)
</code></pre>

<p>and a <code>Zip'</code> instance for <code>Fold</code>:</p>

<pre><code>instance Zip' (Fold b) where zip' = zipF'
</code></pre>

<h3>&#8230; and more morphisms</h3>

<p>These zipping classes have associated morphism properties.
A function <code>q</code> mapping from one <code>Zip</code> instance to another is a &#8220;<code>Zip</code> morphism&#8221; when</p>

<pre><code>q (f `zip` g) == q f `zip` q g
</code></pre>

<p>for all folds <code>f</code> and <code>g</code>.</p>

<p>Similarly for <code>Zip'</code> morphisms:</p>

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

<p>In other words, <code>q</code> distributes over <code>zip</code> or <code>zip'</code>.</p>

<p>As I&#8217;ll show in another post, the two interpretation functions <code>cfoldl</code> and <code>cfoldl'</code> are <code>Zip</code> and <code>Zip'</code> morphisms, respectively, i.e.,</p>

<pre><code>cfoldl  (f `zip`  g) == cfoldl  f `zip`  cfoldl  g

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

<p>which means that zip folding as defined above works correctly.</p>

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

<p>I like to keep blog posts fairly short, so I&#8217;ll share two more pieces of this story in upcoming blog posts:</p>

<ul>
<li>Regaining the lost <code>Functor</code> and <code>Applicative</code> instances.</li>
<li>The <code>Zip</code> and <code>Zip'</code> morphism proofs for zip folding.</li>
</ul>
<p><a href="http://conal.net/blog/?flattrss_redirect&amp;id=59&amp;md5=f493b4d0c5d54a87e384633fe21bd7aa"><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/more-beautiful-fold-zipping/feed</wfw:commentRss>
		<slash:comments>7</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%2Fmore-beautiful-fold-zipping&amp;language=en_GB&amp;category=text&amp;title=More+beautiful+fold+zipping&amp;description=My+previous+post%2C+Another+lovely+example+of+type+class+morphisms%2C+placed+some+standard+structure+around+Max+Rabkin%26%238217%3Bs+Beautiful+folding%2C+using+type+class+morphisms+to+confirm+that+the+Functor+and+Applicative...&amp;tags=fold%2Czip%2Cblog" type="text/html" />
	</item>
		<item>
		<title>Another lovely example of type class morphisms</title>
		<link>http://conal.net/blog/posts/another-lovely-example-of-type-class-morphisms</link>
		<comments>http://conal.net/blog/posts/another-lovely-example-of-type-class-morphisms#comments</comments>
		<pubDate>Fri, 14 Nov 2008 06:20:06 +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[semantics]]></category>
		<category><![CDATA[type class]]></category>
		<category><![CDATA[type class morphism]]></category>
		<category><![CDATA[zip]]></category>

		<guid isPermaLink="false">http://conal.net/blog/?p=58</guid>
		<description><![CDATA[I read Max Rabkin&#8217;s recent post Beautiful folding with great excitement. He shows how to make combine multiple folds over the same list into a single pass, which can then drastically reduce memory requirements of a lazy functional program. Max&#8217;s trick is giving folds a data representation and a way to combine representations that corresponds [&#8230;]]]></description>
				<content:encoded><![CDATA[<!-- 

Title: Another lovely example of type class morphisms

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

URL: http://conal.net/blog/posts/another-lovely-example-of-type-class-morphisms/

-->

<!-- references -->

<!-- teaser -->

<p>I read Max Rabkin&#8217;s recent post <a href="http://squing.blogspot.com/2008/11/beautiful-folding.html" title="blog post by Max Rabkin">Beautiful folding</a> with great excitement.
He shows how to make combine multiple folds over the same list into a single pass, which can then drastically reduce memory requirements of a lazy functional program.
Max&#8217;s trick is giving folds a data representation and a way to combine representations that corresponds to combining the folds.</p>

<p>Peeking out from behind Max&#8217;s definitions is a lovely pattern I&#8217;ve been noticing more and more over the last couple of years, namely <a href="http://conal.net/blog/posts/simplifying-semantics-with-type-class-morphisms" title="blog post">type class morphisms</a>.</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-58"></span></p>

<h3>Folds as data</h3>

<p>Max gives a data representation of folds and adds on an post-fold step, which makes them composable.</p>

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

<p>The components of a <code>Fold</code> are a (strict left) fold&#8217;s combiner function and initial value, plus a post-fold step.
This interpretation is done by a function <code>cfoldl'</code>, which turns these data folds into function folds:</p>

<pre><code>cfoldl' :: Fold b c -&gt; [b] -&gt; c
cfoldl' (F op e k) = k . foldl' op e
</code></pre>

<p>where <code>foldl'</code> is the standard strict, left-fold functional:</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>

<h3>Standard classes</h3>

<p>As Twan van Laarhoven pointed out in a comment on <a href="http://squing.blogspot.com/2008/11/beautiful-folding.html" title="blog post by Max Rabkin">Max&#8217;s post</a>, <code>Fold b</code> is a functor and an applicative functor, so some of Max&#8217;s <code>Fold</code>-manipulating functions can be replaced by standard vocabulary.</p>

<p>The <code>Functor</code> instance is pretty simple:</p>

<pre><code>instance Functor (Fold b) where
  fmap h (F op e k) = F op e (h . k)
</code></pre>

<p>The <code>Applicative</code> instance is a bit trickier.
For strictness, Max used used a type of strict pairs:</p>

<pre><code>data Pair c c' = P !c !c'
</code></pre>

<p>The instance:</p>

<pre><code>instance Applicative (Fold b) where
  pure a = F (error "no op") (error "no e") (const a)

  F op e k &lt;*&gt; F op' e' k' = F op'' e'' k''
   where
     P a a' `op''` b = P (a `op` b) (a' `op'` b)
     e''             = P e e'
     k'' (P a a')    = (k a) (k' a')
</code></pre>

<p>Given that <code>Fold b</code> is an applicative functor, Max&#8217;s <code>bothWith</code> function is then <code>liftA2</code>.
Max&#8217;s <code>multi-cfoldl'</code> rule then becomes:</p>

<pre><code>forall c f g xs.
   h (cfoldl' f xs) (cfoldl' g xs) == cfoldl' (liftA2 h f g) xs
</code></pre>

<p>thus replacing two passes with one pass.</p>

<h3>Beautiful properties</h3>

<p>Now here&#8217;s the fun part.
Looking at the <code>Applicative</code> instance for <code>((-&gt;) a)</code>, the rule above is equivalent to</p>

<pre><code>forall c f g.
  liftA2 h (cfoldl' f) (cfoldl' g) == cfoldl' (liftA2 h f g)
</code></pre>

<p>Flipped around, this rule says that <code>liftA2</code> distributes over <code>cfoldl'</code>.
Or, &#8220;the meaning of <code>liftA2</code> is <code>liftA2</code>&#8220;.
Neat, huh?</p>

<p>Moreover, this <code>liftA2</code> property is equivalent to the following:</p>

<pre><code>forall f g.
  cfoldl' f &lt;*&gt; cfoldl' g == cfoldl' (f &lt;*&gt; g)
</code></pre>

<p>This form is one of the two <code>Applicative</code> morphism laws (which I usually write in the reverse direction):</p>

<p>For more about these morphisms, see <a href="http://conal.net/blog/posts/simplifying-semantics-with-type-class-morphisms" title="blog post">Simplifying semantics with type class morphisms</a>.
That post suggests that semantic functions in particular ought to be type class morphisms (and if not, then you&#8217;d have an abstraction leak).
And <code>cfoldl'</code> is a semantic function, in that it gives meaning to a <code>Fold</code>.</p>

<p>The other type class morphisms in this case are</p>

<pre><code>cfoldl' (pure a  ) == pure a

cfoldl' (fmap h f) == fmap h (cfoldl' f)
</code></pre>

<p>Given the <code>Functor</code> and <code>Applicative</code> instances of <code>((-&gt;) a)</code>, these two properties are equivalent to</p>

<pre><code>cfoldl' (pure a  ) == const a

cfoldl' (fmap h f) == h . cfoldl' f
</code></pre>

<p>or</p>

<pre><code>cfoldl' (pure a  ) xs == a

cfoldl' (fmap h f) xs == h (cfoldl' f xs)
</code></pre>

<h3>Rewrite rules</h3>

<p>Max pointed out that GHC does not handle his original <code>multi-cfoldl'</code> rule.
The reason is that the head of the LHS (left-hand side) is a variable.
However, the type class morphism laws have constant (known) functions at the head, so I expect they could usefully act as fusion rewrite rules.</p>

<h3>Inevitable instances</h3>

<p>Given the implementations (instances) of <code>Functor</code> and <code>Applicative</code> for <code>Fold</code>, I&#8217;d like to verify that the morphism laws for <code>cfoldl'</code> (above) hold.</p>

<h4>Functor</h4>

<p>Start with <code>fmap</code>.
The morphism law:</p>

<pre><code>cfoldl' (fmap h f) == fmap h (cfoldl' f)
</code></pre>

<p>First, give the <code>Fold</code> argument more structure, so that (without loss of generality) the law becomes</p>

<pre><code>cfoldl' (fmap h (F op e k)) == fmap h (cfoldl' (F op e k))
</code></pre>

<p>The game is to work backward from this law to the definition of <code>fmap</code> for <code>Fold</code>.
I&#8217;ll do so by massaging the RHS (right-hand side) into the form <code>cfoldl' (...)</code>, where &#8220;<code>...</code>&#8221; is the definition <code>fmap h (F op e k)</code>.</p>

<pre><code>fmap h (cfoldl' (F op e k))

  ==  {- inline cfoldl' -}

fmap h (k . foldl' op e)

  ==  {- inline fmap on functions -}

h . (k . foldl' op e)

  ==  {- associativity of (.) -}

(h . k) . foldl' op e

  ==  {- uninline cfoldl' -}

cfoldl' (F op e (h . k))

  ==  {- uninline fmap on Fold  -}

cfoldl' (fmap h (F op e k))
</code></pre>

<p>This proof show why Max had to add the post-fold function <code>k</code> to his <code>Fold</code> type.
If <code>k</code> weren&#8217;t there, we couldn&#8217;t have buried the <code>h</code> in it.</p>

<p>More usefully, this proof suggests how we could have discovered the <code>fmap</code> definition.
For instance, we might have tried with a simpler and more obvious <code>Fold</code> representation:</p>

<pre><code>data FoldS a b = FS (a -&gt; b -&gt; a) a
</code></pre>

<p>Getting into the <code>fmap</code> derivation, we&#8217;d come to</p>

<pre><code>h . foldsl' op e
</code></pre>

<p>and then we&#8217;d be stuck.
But not really, because the awkward extra bit (<code>h .</code>) beckons us to generalize by adding Max&#8217;s post-fold function.</p>

<h4>Applicative</h4>

<p>Next pure:</p>

<pre><code>cfoldl' (pure a) == pure a
</code></pre>

<p>Reason as before, starting with the RHS</p>

<pre><code>pure a

  ==  {- inline pure on functions -}

const a

  ==  {- property of const -}

const a . foldl op e

  ==  {- uninline cfoldl' -}

cfoldl' (F (const a) op e)
</code></pre>

<p>The imaginative step was inventing structure to match the definition of <code>cfoldl'</code>.
This definition is true for <em>any</em> values of <code>op</code> and <code>e</code>, so we can use bottom in the definition:</p>

<pre><code>instance Applicative (Fold b) where
  pure a = F undefined undefined (const a)
</code></pre>

<p>As Twan noticed, the existential (<code>forall</code>) also lets us pick defined values for <code>op</code> and <code>e</code>.
He chose <code>(_ _ -&gt; ())</code> and <code>()</code>.</p>

<p>The derivation of <code>(&lt;*&gt;)</code> is trickier and is the heart of the problem of fusing folds to reduce multiple traversals to a single one.
Why the heart?  Because <code>(&lt;*&gt;)</code> is all about <em>combining</em> two things into one.</p>

<h4>Intermission</h4>

<p>I&#8217;m taking a break here.
While fiddling with a proof of the <code>(&lt;*&gt;)</code> morphism law, I realized a simpler way to structure these folds, which will be the topic of an upcoming post.</p>
<p><a href="http://conal.net/blog/?flattrss_redirect&amp;id=58&amp;md5=654d33555237a7a03d4b82df83d84d6f"><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/another-lovely-example-of-type-class-morphisms/feed</wfw:commentRss>
		<slash:comments>2</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%2Fanother-lovely-example-of-type-class-morphisms&amp;language=en_GB&amp;category=text&amp;title=Another+lovely+example+of+type+class+morphisms&amp;description=I+read+Max+Rabkin%26%238217%3Bs+recent+post+Beautiful+folding+with+great+excitement.+He+shows+how+to+make+combine+multiple+folds+over+the+same+list+into+a+single+pass%2C+which+can+then...&amp;tags=applicative+functor%2Cfold%2Cfunctor%2Csemantics%2Ctype+class%2Ctype+class+morphism%2Czip%2Cblog" type="text/html" />
	</item>
	</channel>
</rss>
