<?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; functor</title>
	<atom:link href="http://conal.net/blog/tag/functor/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>A third view on trees</title>
		<link>http://conal.net/blog/posts/a-third-view-on-trees</link>
		<comments>http://conal.net/blog/posts/a-third-view-on-trees#comments</comments>
		<pubDate>Sat, 04 Jun 2011 02:46:20 +0000</pubDate>
		<dc:creator><![CDATA[Conal]]></dc:creator>
				<category><![CDATA[Functional programming]]></category>
		<category><![CDATA[functor]]></category>

		<guid isPermaLink="false">http://conal.net/blog/?p=460</guid>
		<description><![CDATA[A few recent posts have played with trees from two perspectives. The more commonly used I call &#34;top-down&#34;, because the top-level structure is most immediately apparent. A top-down binary tree is either a leaf or a pair of such trees, and that pair can be accessed without wading through intervening structure. Much less commonly used [&#8230;]]]></description>
				<content:encoded><![CDATA[<!-- teaser -->

<p>A few recent posts have played with trees from two perspectives. The more commonly used I call &quot;top-down&quot;, because the top-level structure is most immediately apparent. A top-down binary tree is either a leaf or a pair of such trees, and that pair can be accessed without wading through intervening structure. Much less commonly used are &quot;bottom-up&quot; trees. A bottom-up binary tree is either a leaf or a single such tree of pairs. In the non-leaf case, the pair structure of the tree elements is accessible by operations like mapping, folding, or scanning. The difference is between a pair of trees and a tree of pairs.</p>

<p>As an alternative to the top-down and bottom-up views on trees, I now want to examine a third view, which is a hybrid of the two. Instead of pairs of trees or trees of pairs, this hybrid view is of trees of trees, and more specifically of bottom-up trees of top-down trees. As we&#8217;ll see, these hybrid trees emerge naturally from the top-down and bottom-up views. A later post will show how this third view lends itself to an <em>in-place</em> (destructive) scan algorithm, suitable for execution on modern GPUs.</p>

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

<ul>
<li>2011-06-04: &quot;Suppose we have a bottom-up tree of top-down trees, i.e., <code>t ∷ TB (TT a)</code>. Was backwards. (Thanks to Noah Easterly.)</li>
<li>2011-06-04: Notation: &quot;<code>f ➶ n</code>&quot; and &quot;<code>f ➴ n</code>&quot;.</li>
</ul>

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

<p>The post <a href="http://conal.net/blog/posts/parallel-tree-scanning-by-composition/" title="blog post"><em>Parallel tree scanning by composition</em></a> defines &quot;top-down&quot; and a &quot;bottom-up&quot; binary trees as follows (modulo type and constructor names):</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">data</span> <span class="dt">TT</span> a <span class="fu">=</span> <span class="kw">LT</span> a <span class="fu">|</span> <span class="dt">BT</span> { unBT <span class="ot">&#8759;</span> <span class="dt">Pair</span> (<span class="dt">TT</span> a) } <span class="kw">deriving</span> <span class="kw">Functor</span><br /><br /><span class="kw">data</span> <span class="dt">TB</span> a <span class="fu">=</span> <span class="dt">LB</span> a <span class="fu">|</span> <span class="dt">BB</span> { unBB <span class="ot">&#8759;</span> <span class="dt">TB</span> (<span class="dt">Pair</span> a) } <span class="kw">deriving</span> <span class="kw">Functor</span></code></pre>

<p>So, while a non-leaf <code>TT</code> (top-down tree) has a pair at the top (outside), a non-leaf <code>TB</code> (bottom-up tree) has pairs at the bottom (inside).</p>

<p>Combining these two observations leads to an interesting possibility. Suppose we have a bottom-up tree of top-down trees, i.e., <code>t ∷ TB (TT a)</code>. If <code>t</code> is not a leaf, then <code>t ≡ BB tt</code> where <code>tt</code> is a bottom-up tree whose leaves are pairs of top-down trees, i.e., <code>tt ∷ TB (Pair (TT a))</code>. Each of those leaves of type <code>Pair (TT a)</code> can be converted to type <code>TT a</code> (single tree), simply by applying the <code>BT</code> constructor. Moreover, this transformation is invertible. For convenience, define a type alias for hybrid trees:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">type</span> <span class="dt">TH</span> a <span class="fu">=</span> <span class="dt">TB</span> (<span class="dt">TT</span> a)</code></pre>

<p>Then the two conversions:</p>

<pre class="sourceCode"><code class="sourceCode haskell">upT   <span class="ot">&#8759;</span> <span class="dt">TH</span> a <span class="ot">&#8594;</span> <span class="dt">TH</span> a<br />upT   <span class="fu">=</span> <span class="fu">fmap</span> <span class="dt">BT</span> &#8728; unBB<br /><br />downT <span class="ot">&#8759;</span> <span class="dt">TH</span> a <span class="ot">&#8594;</span> <span class="dt">TH</span> a<br />downT <span class="fu">=</span> <span class="dt">BB</span> &#8728; <span class="fu">fmap</span> unBT</code></pre>

<div class=exercise>

<p><em>Exercise:</em> Prove <code>upT</code> and <code>downT</code> are inverses where defined.</p>
<p>Answer:</p>

<div class=toggle>

<pre class="sourceCode"><code class="sourceCode haskell">  upT &#8728; downT<br />&#8801; <span class="fu">fmap</span> <span class="dt">BT</span> &#8728; unBB &#8728; <span class="dt">BB</span> &#8728; <span class="fu">fmap</span> unBT<br />&#8801; <span class="fu">fmap</span> <span class="dt">BT</span> &#8728; <span class="fu">fmap</span> unBT<br />&#8801; <span class="fu">fmap</span> (<span class="dt">BT</span> &#8728; unBT)<br />&#8801; <span class="fu">fmap</span> <span class="fu">id</span><br />&#8801; <span class="fu">id</span><br /><br />  downT &#8728; upT<br />&#8801; <span class="dt">BB</span> &#8728; <span class="fu">fmap</span> unBT &#8728; <span class="fu">fmap</span> <span class="dt">BT</span> &#8728; unBB<br />&#8801; <span class="dt">BB</span> &#8728; <span class="fu">fmap</span> (unBT &#8728; <span class="dt">BT</span>) &#8728; unBB<br />&#8801; <span class="dt">BB</span> &#8728; <span class="fu">fmap</span> <span class="fu">id</span> &#8728; unBB<br />&#8801; <span class="dt">BB</span> &#8728; <span class="fu">id</span> &#8728; unBB<br />&#8801; <span class="dt">BB</span> &#8728; unBB<br />&#8801; <span class="fu">id</span></code></pre>

</div>


</div>

<p>Consider a perfect binary leaf tree of depth <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>n</mi></mrow></math>, i.e., an <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>n</mi></mrow></math>-deep binary tree with each level full and data only at the leaves (where a leaf is depth <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mn>0</mn></mrow></math> tree.) We can view such a tree as top-down, or bottom-up, or as a hybrid.</p>

<p>Each of these three views is really <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow></math> views:</p>

<ul>
<li>Top-down: a depth <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>n</mi></mrow></math> tree, or a pair of depth <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>n</mi><mo>-</mo><mn>1</mn></mrow></math> trees, or a pair of pairs of depth <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>n</mi><mo>-</mo><mn>2</mn></mrow></math> trees, etc.</li>
<li>Bottom-up: a depth <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>n</mi></mrow></math> tree, or a depth <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>n</mi><mo>-</mo><mn>1</mn></mrow></math> tree of pairs, or a depth <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>n</mi><mo>-</mo><mn>2</mn></mrow></math> tree of pairs of pairs, etc.</li>
<li>Hybrid: a depth <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>n</mi></mrow></math> tree of depth <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mn>0</mn></mrow></math> trees, or a depth <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>n</mi><mo>-</mo><mn>1</mn></mrow></math> tree of depth <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mn>1</mn></mrow></math> trees, or, &#8230;, or a depth <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mn>0</mn></mrow></math> tree of depth <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>n</mi></mrow></math> trees.</li>
</ul>

<p>In the hybrid case, counting from <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mn>0</mn></mrow></math> to <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>n</mi></mrow></math>, the <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msup><mi>k</mi><mrow><mi>t</mi><mi>h</mi></mrow></msup></mrow></math> such view is a depth <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>n</mi><mo>-</mo><mi>k</mi></mrow></math> bottom-up tree whose elements (leaf values) are depth <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>k</mi></mrow></math> top-down trees. When <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>k</mi><mo>=</mo><mi>n</mi></mrow></math>, we have a bottom-up tree whose leaves are all single-leaf trees, and when <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>k</mi><mo>=</mo><mn>0</mn></mrow></math>, we have a single-leaf bottom-up tree containing a top-down tree. Imagine a horizontal line at depth <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>k</mi></mrow></math>, dividing the bottom-up outer structure from the top-down inner structure. The <code>downT</code> function moves the dividing line downward, and the <code>upT</code> function moves the line upward. Both functions are partial.</p>

<h3 id="generalizing">Generalizing</h3>

<p>The role of <code>Pair</code> in the tree types above is simple and regular. We can abstract out this particular type constructor, generalizing to an arbitrary functor. I&#8217;ll call this generalization &quot;functor trees&quot;. Again, there are top-down and bottom-up versions:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">data</span> <span class="dt">FT</span> f a <span class="fu">=</span> <span class="dt">FLT</span> a <span class="fu">|</span> <span class="dt">FBT</span> { unFBT <span class="ot">&#8759;</span> f (<span class="dt">FT</span> f a) } <span class="kw">deriving</span> <span class="kw">Functor</span><br /><br /><span class="kw">data</span> <span class="dt">FB</span> f a <span class="fu">=</span> <span class="dt">FLB</span> a <span class="fu">|</span> <span class="dt">FBB</span> { unFBB <span class="ot">&#8759;</span> <span class="dt">FB</span> f (f a) } <span class="kw">deriving</span> <span class="kw">Functor</span></code></pre>

<p>And a hybrid version, with generalized versions of <code>upT</code> and <code>downT</code>:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">type</span> <span class="dt">FH</span> f a <span class="fu">=</span> <span class="dt">FB</span> f (<span class="dt">FT</span> f a)<br /><br />upH   <span class="ot">&#8759;</span> <span class="kw">Functor</span> f <span class="ot">&#8658;</span> <span class="dt">FH</span> f a <span class="ot">&#8594;</span> <span class="dt">FH</span> f a<br />upH   <span class="fu">=</span> <span class="fu">fmap</span> <span class="dt">FBT</span> &#8728; unFBB<br /><br />downH <span class="ot">&#8759;</span> <span class="kw">Functor</span> f <span class="ot">&#8658;</span> <span class="dt">FH</span> f a <span class="ot">&#8594;</span> <span class="dt">FH</span> f a<br />downH <span class="fu">=</span> <span class="dt">FBB</span> &#8728; <span class="fu">fmap</span> unFBT</code></pre>

<p>These definitions specialize to the ones (for binary trees) by substituting <code>Pair</code> for the parameter <code>f</code>.</p>

<h3 id="depth-typing">Depth-typing</h3>

<p>The upward and downward view-changing functions above are partial, as they can fail at extreme tree views (at depth <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mn>0</mn></mrow></math> or <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>n</mi></mrow></math>). We could make this partiality explicit by changing the result type to <code>Maybe (TH a)</code> for binary hybrid trees and to <code>Maybe (FH f a)</code> for the functor generalization. Alternatively, make the tree sizes <em>explicit</em> in the types, as in a few recent posts, including <a href="http://conal.net/blog/posts/a-trie-for-length-typed-vectors/" title="blog post"><em>A trie for length-typed vectors</em></a>. (In those posts, I used the terms &quot;right-folded&quot; and &quot;left-folded&quot; in place of &quot;top-down&quot; and &quot;bottom-up&quot;, reflecting the right- or left-folding of functor composition. The &quot;folded&quot; terms led to some confusion, especially in the context of data type folds and scans.) In the depth-typed versions, &quot;leaves&quot; are zero-ary compositions, and &quot;branches&quot; are <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mo stretchy="false">(</mo><mi>m</mi><mo>+</mo><mn>1</mn><mo stretchy="false">)</mo></mrow></math>-ary compositions for some <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>m</mi></mrow></math>.</p>

<p>Top-down:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">data</span> (&#10164;) <span class="ot">&#8759;</span> (<span class="fu">*</span> <span class="ot">&#8594;</span> <span class="fu">*</span>) <span class="ot">&#8594;</span> <span class="fu">*</span> <span class="ot">&#8594;</span> (<span class="fu">*</span> <span class="ot">&#8594;</span> <span class="fu">*</span>) <span class="kw">where</span><br />  <span class="dt">ZeroT</span> <span class="ot">&#8759;</span> a <span class="ot">&#8594;</span> (f &#10164; <span class="dt">Z</span>) a<br />  <span class="dt">SuccT</span> <span class="ot">&#8759;</span> <span class="dt">IsNat</span> n <span class="ot">&#8658;</span> f ((f &#10164; n) a) <span class="ot">&#8594;</span> (f &#10164; <span class="dt">S</span> n) a<br /><br />unZeroT <span class="ot">&#8759;</span> (f &#10164; <span class="dt">Z</span>) a <span class="ot">&#8594;</span> a<br />unZeroT (<span class="dt">ZeroT</span> a) <span class="fu">=</span> a<br /><br />unSuccT <span class="ot">&#8759;</span> (f &#10164; <span class="dt">S</span> n) a <span class="ot">&#8594;</span> f ((f &#10164; n) a)<br />unSuccT (<span class="dt">SuccT</span> fsa) <span class="fu">=</span> fsa<br /><br /><span class="kw">instance</span> <span class="kw">Functor</span> f <span class="ot">&#8658;</span> <span class="kw">Functor</span> (f &#10164; n) <span class="kw">where</span><br />  <span class="fu">fmap</span> h (<span class="dt">ZeroT</span> a)  <span class="fu">=</span> <span class="dt">ZeroT</span> (h a)<br />  <span class="fu">fmap</span> h (<span class="dt">SuccT</span> fs) <span class="fu">=</span> <span class="dt">SuccT</span> ((fmap&#8728;fmap) h fs)</code></pre>

<p>Bottom-up:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">data</span> (&#10166;) <span class="ot">&#8759;</span> (<span class="fu">*</span> <span class="ot">&#8594;</span> <span class="fu">*</span>) <span class="ot">&#8594;</span> <span class="fu">*</span> <span class="ot">&#8594;</span> (<span class="fu">*</span> <span class="ot">&#8594;</span> <span class="fu">*</span>) <span class="kw">where</span><br />  <span class="dt">ZeroB</span> <span class="ot">&#8759;</span> a <span class="ot">&#8594;</span> (f &#10166; <span class="dt">Z</span>) a<br />  <span class="dt">SuccB</span> <span class="ot">&#8759;</span> <span class="dt">IsNat</span> n <span class="ot">&#8658;</span> (f &#10166; n) (f a) <span class="ot">&#8594;</span> (f &#10166; <span class="dt">S</span> n) a<br /><br />unZeroB <span class="ot">&#8759;</span> (f &#10166; <span class="dt">Z</span>) a <span class="ot">&#8594;</span> a<br />unZeroB (<span class="dt">ZeroB</span> a) <span class="fu">=</span> a<br /><br />unSuccB <span class="ot">&#8759;</span> (f &#10166; <span class="dt">S</span> n) a <span class="ot">&#8594;</span> (f &#10166; n) (f a)<br />unSuccB (<span class="dt">SuccB</span> fsa) <span class="fu">=</span> fsa<br /><br /><span class="kw">instance</span> <span class="kw">Functor</span> f <span class="ot">&#8658;</span> <span class="kw">Functor</span> (f &#10166; n) <span class="kw">where</span><br />  <span class="fu">fmap</span> h (<span class="dt">ZeroB</span> a)  <span class="fu">=</span> <span class="dt">ZeroB</span> (h a)<br />  <span class="fu">fmap</span> h (<span class="dt">SuccB</span> fs) <span class="fu">=</span> <span class="dt">SuccB</span> ((fmap&#8728;fmap) h fs)</code></pre>

<p>Hybrid:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">type</span> <span class="dt">H</span> p q f a <span class="fu">=</span> (f &#10166; p) ((f &#10164; q) a)</code></pre>

<p>Upward and downward shift become total functions, and their types explicitly describe how the line shifts between <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mo stretchy="false">(</mo><mi>p</mi><mo>+</mo><mn>1</mn><mo stretchy="false">)</mo><mo>/</mo><mi>q</mi></mrow></math> and <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>p</mi><mo>/</mo><mo stretchy="false">(</mo><mi>q</mi><mo>+</mo><mn>1</mn><mo stretchy="false">)</mo></mrow></math>:</p>

<pre class="sourceCode"><code class="sourceCode haskell">up   <span class="ot">&#8759;</span> (<span class="kw">Functor</span> f, <span class="dt">IsNat</span> q) <span class="ot">&#8658;</span> <span class="dt">H</span> (<span class="dt">S</span> p) q f a <span class="ot">&#8594;</span> <span class="dt">H</span> p (<span class="dt">S</span> q) f a<br />up   <span class="fu">=</span> <span class="fu">fmap</span> <span class="dt">SuccT</span> &#8728; unSuccB<br /><br />down <span class="ot">&#8759;</span> (<span class="kw">Functor</span> f, <span class="dt">IsNat</span> p) <span class="ot">&#8658;</span> <span class="dt">H</span> p (<span class="dt">S</span> q) f a <span class="ot">&#8594;</span> <span class="dt">H</span> (<span class="dt">S</span> p) q f a<br />down <span class="fu">=</span> <span class="dt">SuccB</span> &#8728; <span class="fu">fmap</span> unSuccT</code></pre>

<h3 id="so-what">So what?</h3>

<p>Why care about the multitude of views on trees?</p>

<ul>
<li>It&#8217;s pretty.</li>
<li>A future post will show how these hybrid trees enable an elegant formulation of parallel scanning that lends itself to an in-place, GPU-friendly implementation.</li>
</ul>
<p><a href="http://conal.net/blog/?flattrss_redirect&amp;id=460&amp;md5=3a9aceb3d722783b8e463cbfc78be6e4"><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/a-third-view-on-trees/feed</wfw:commentRss>
		<slash:comments>0</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%2Fa-third-view-on-trees&amp;language=en_GB&amp;category=text&amp;title=A+third+view+on+trees&amp;description=A+few+recent+posts+have+played+with+trees+from+two+perspectives.+The+more+commonly+used+I+call+%26quot%3Btop-down%26quot%3B%2C+because+the+top-level+structure+is+most+immediately+apparent.+A+top-down+binary+tree...&amp;tags=functor%2Cblog" type="text/html" />
	</item>
		<item>
		<title>Parallel tree scanning by composition</title>
		<link>http://conal.net/blog/posts/parallel-tree-scanning-by-composition</link>
		<comments>http://conal.net/blog/posts/parallel-tree-scanning-by-composition#comments</comments>
		<pubDate>Tue, 24 May 2011 20:31:23 +0000</pubDate>
		<dc:creator><![CDATA[Conal]]></dc:creator>
				<category><![CDATA[Functional programming]]></category>
		<category><![CDATA[functor]]></category>
		<category><![CDATA[program derivation]]></category>
		<category><![CDATA[scan]]></category>

		<guid isPermaLink="false">http://conal.net/blog/?p=429</guid>
		<description><![CDATA[My last few blog posts have been on the theme of scans, and particularly on parallel scans. In Composable parallel scanning, I tackled parallel scanning in a very general setting. There are five simple building blocks out of which a vast assortment of data structures can be built, namely constant (no value), identity (one value), [&#8230;]]]></description>
				<content:encoded><![CDATA[<!-- teaser -->

<p>My last few blog posts have been on the theme of <em>scans</em>, and particularly on <em>parallel</em> scans. In <a href="http://conal.net/blog/posts/composable-parallel-scanning/" title="blog post"><em>Composable parallel scanning</em></a>, I tackled parallel scanning in a very general setting. There are five simple building blocks out of which a vast assortment of data structures can be built, namely constant (no value), identity (one value), sum, product, and composition. The post defined parallel prefix and suffix scan for each of these five &quot;functor combinators&quot;, in terms of the same scan operation on each of the component functors. Every functor built out of this basic set thus has a parallel scan. Functors defined more conventionally can be given scan implementations simply by converting to a composition of the basic set, scanning, and then back to the original functor. Moreover, I expect this implementation could be generated automatically, similarly to GHC&#8217;s <code>DerivingFunctor</code> extension.</p>

<p>Now I&#8217;d like to show two examples of parallel scan composition in terms of binary trees, namely the top-down and bottom-up variants of perfect binary leaf trees used in previous posts. (In previous posts, I used the terms &quot;right-folded&quot; and &quot;left-folded&quot; instead of &quot;top-down&quot; and &quot;bottom-up&quot;.) The resulting two algorithms are expressed nearly identically, but have differ significantly in the work performed. The top-down version does <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mo>&#920;</mo><mo stretchy="false">(</mo><mi>n</mi><mspace width="0.167em"></mspace><mi>log</mi><mspace width="0.167em"></mspace><mi>n</mi><mo stretchy="false">)</mo></mrow></math> work, while the bottom-up version does only <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mo>&#920;</mo><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow></math>, and thus the latter algorithm is work-efficient, while the former is not. Moreover, with a <em>very</em> simple optimization, the bottom-up tree algorithm corresponds closely to Guy Blelloch&#8217;s parallel prefix scan for arrays, given in <a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.53.5739" title="Paper by Guy Blelloch"><em>Programming parallel algorithms</em></a>. I&#8217;m delighted with this result, as I had been wondering how to think about Guy&#8217;s algorithm.</p>

<p><strong>Edit:</strong></p>

<ul>
<li>2011-05-31: Added <code>Scan</code> and <code>Applicative</code> instances for <code>T2</code> and <code>T4</code>.</li>
</ul>

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

<h3 id="scanning-via-functor-combinators">Scanning via functor combinators</h3>

<p>In <a href="http://conal.net/blog/posts/composable-parallel-scanning/" title="blog post"><em>Composable parallel scanning</em></a>, we saw the <code>Scan</code> class:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">class</span> <span class="dt">Scan</span> f <span class="kw">where</span><br />  prefixScan, suffixScan <span class="ot">&#8759;</span> <span class="dt">Monoid</span> m <span class="ot">&#8658;</span> f m <span class="ot">&#8594;</span> (m, f m)</code></pre>

<p>Given a structure of values, the prefix and suffix scan methods generate the overall <code>fold</code> (of type <code>m</code>), plus a structure of the same type as the input. (In contrast, the usual Haskell <code>scanl</code> and <code>scanr</code> functions on lists yield a single list with one more element than the source list. I changed the interface for generality and composability.) The <a href="http://conal.net/blog/posts/composable-parallel-scanning/" title="blog post">post</a> gave instances for the basic set of five functor combinators.</p>

<p>Most functors are not defined via the basic combinators, but as mentioned above, we can scan by conversion to and from the basic set. For convenience, encapsulate this conversion in a type class:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">class</span> <span class="dt">EncodeF</span> f <span class="kw">where</span><br />  <span class="kw">type</span> <span class="dt">Enc</span> f <span class="ot">&#8759;</span> <span class="fu">*</span> <span class="ot">&#8594;</span> <span class="fu">*</span><br />  encode <span class="ot">&#8759;</span> f a <span class="ot">&#8594;</span> <span class="dt">Enc</span> f a<br />  decode <span class="ot">&#8759;</span> <span class="dt">Enc</span> f a <span class="ot">&#8594;</span> f a</code></pre>

<p>and define scan functions via <code>EncodeF</code>:</p>

<pre class="sourceCode"><code class="sourceCode haskell">prefixScanEnc, suffixScanEnc <span class="ot">&#8759;</span><br />  (<span class="dt">EncodeF</span> f, <span class="dt">Scan</span> (<span class="dt">Enc</span> f), <span class="dt">Monoid</span> m) <span class="ot">&#8658;</span> f m <span class="ot">&#8594;</span> (m, f m)<br />prefixScanEnc <span class="fu">=</span> second decode &#8728; prefixScan &#8728; encode<br />suffixScanEnc <span class="fu">=</span> second decode &#8728; suffixScan &#8728; encode</code></pre>

<h4 id="lists">Lists</h4>

<p>As a first example, consider</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">instance</span> <span class="dt">EncodeF</span> [] <span class="kw">where</span><br />  <span class="kw">type</span> <span class="dt">Enc</span> [] <span class="fu">=</span> <span class="dt">Const</span> () <span class="fu">+</span> <span class="dt">Id</span> &#215; []<br />  encode [] <span class="fu">=</span> <span class="dt">InL</span> (<span class="dt">Const</span> ())<br />  encode (a <span class="fu">:</span> <span class="kw">as</span>) <span class="fu">=</span> <span class="dt">InR</span> (<span class="dt">Id</span> a &#215; <span class="kw">as</span>)<br />  decode (<span class="dt">InL</span> (<span class="dt">Const</span> ())) <span class="fu">=</span> []<br />  decode (<span class="dt">InR</span> (<span class="dt">Id</span> a &#215; <span class="kw">as</span>)) <span class="fu">=</span> a <span class="fu">:</span> <span class="kw">as</span></code></pre>

<p>And declare a boilerplate <code>Scan</code> instance via <code>EncodeF</code>:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">instance</span> <span class="dt">Scan</span> [] <span class="kw">where</span><br />  prefixScan <span class="fu">=</span> prefixScanEnc<br />  suffixScan <span class="fu">=</span> suffixScanEnc</code></pre>

<p>I haven&#8217;t checked the details, but I think with this instance, suffix scanning has okay performance, while prefix scan does quadratic work. The reason is the in the <code>Scan</code> instance for products, the two components are scanned independently (in parallel), and then the whole second component is adjusted for <code>prefixScan</code>, while the whole first component is adjusted for <code>suffixScan</code>. In the case of lists, the first component is the list head, and second component is the list tail.</p>

<p>For your reading convenience, here&#8217;s that <code>Scan</code> instance again:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">instance</span> (<span class="dt">Scan</span> f, <span class="dt">Scan</span> g, <span class="kw">Functor</span> f, <span class="kw">Functor</span> g) <span class="ot">&#8658;</span> <span class="dt">Scan</span> (f &#215; g) <span class="kw">where</span><br />  prefixScan (fa &#215; ga) <span class="fu">=</span> (af &#8853; ag, fa' &#215; ((af &#8853;) <span class="fu">&lt;$&gt;</span> ga'))<br />   <span class="kw">where</span> (af,fa') <span class="fu">=</span> prefixScan fa<br />         (ag,ga') <span class="fu">=</span> prefixScan ga<br /><br />  suffixScan (fa &#215; ga) <span class="fu">=</span> (af &#8853; ag, ((&#8853; ag) <span class="fu">&lt;$&gt;</span> fa') &#215; ga')<br />   <span class="kw">where</span> (af,fa') <span class="fu">=</span> suffixScan fa<br />         (ag,ga') <span class="fu">=</span> suffixScan ga</code></pre>

<p>The lop-sidedness of the list type thus interferes with parallelization, and makes the parallel scans perform much worse than cumulative sequential scans.</p>

<p>Let&#8217;s next look at a more balanced type.</p>

<h3 id="binary-trees">Binary Trees</h3>

<p>We&#8217;ll get better parallel performance by organizing our data so that we can cheaply partition it into roughly equal pieces. Tree types allows such partitioning.</p>

<h4 id="top-down-trees">Top-down trees</h4>

<p>We&#8217;ll try a few variations, starting with a simple binary tree.</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">data</span> <span class="dt">T1</span> a <span class="fu">=</span> <span class="dt">L1</span> a <span class="fu">|</span> <span class="dt">B1</span> (<span class="dt">T1</span> a) (<span class="dt">T1</span> a) <span class="kw">deriving</span> <span class="kw">Functor</span></code></pre>

<p>Encoding and decoding is straightforward:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">instance</span> <span class="dt">EncodeF</span> <span class="dt">T1</span> <span class="kw">where</span><br />  <span class="kw">type</span> <span class="dt">Enc</span> <span class="dt">T1</span> <span class="fu">=</span> <span class="dt">Id</span> <span class="fu">+</span> <span class="dt">T1</span> &#215; <span class="dt">T1</span><br />  encode (<span class="dt">L1</span> a)   <span class="fu">=</span> <span class="dt">InL</span> (<span class="dt">Id</span> a)<br />  encode (<span class="dt">B1</span> s t) <span class="fu">=</span> <span class="dt">InR</span> (s &#215; t)<br />  decode (<span class="dt">InL</span> (<span class="dt">Id</span> a))  <span class="fu">=</span> <span class="dt">L1</span> a<br />  decode (<span class="dt">InR</span> (s &#215; t)) <span class="fu">=</span> <span class="dt">B1</span> s t<br /><br /><span class="kw">instance</span> <span class="dt">Scan</span> <span class="dt">T1</span> <span class="kw">where</span><br />  prefixScan <span class="fu">=</span> prefixScanEnc<br />  suffixScan <span class="fu">=</span> suffixScanEnc</code></pre>

<p>Note that these definitions could be generated automatically from the data type definition.</p>

<p>For <em>balanced trees</em>, prefix and suffix scan divide the problem in half at each step, solve each half, and do linear work to patch up one of the two halves. Letting <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>n</mi></mrow></math> be the number of elements, and <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>W</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow></math> the work, we have the recurrence <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>W</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo><mo>=</mo><mn>2</mn><mspace width="0.167em"></mspace><mi>W</mi><mo stretchy="false">(</mo><mi>n</mi><mo>/</mo><mn>2</mn><mo stretchy="false">)</mo><mo>+</mo><mi>c</mi><mspace width="0.167em"></mspace><mi>n</mi></mrow></math> for some constant factor <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>c</mi></mrow></math>. By the <a href="http://en.wikipedia.org/wiki/Master_theorem" title="Wikipedia entry">Master theorem</a>, therefore, the work done is <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mo>&#920;</mo><mo stretchy="false">(</mo><mi>n</mi><mspace width="0.167em"></mspace><mi>log</mi><mspace width="0.167em"></mspace><mi>n</mi><mo stretchy="false">)</mo></mrow></math>. (Use case 2, with <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>a</mi><mo>=</mo><mi>b</mi><mo>=</mo><mn>2</mn></mrow></math>, <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>f</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo><mo>=</mo><mi>c</mi><mspace width="0.167em"></mspace><mi>n</mi></mrow></math>, and <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>k</mi><mo>=</mo><mn>0</mn></mrow></math>.)</p>

<p>Again assuming a <em>balanced</em> tree, the computation dependencies have logarithmic depth, so the ideal parallel running time (assuming sufficient processors) is <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mo>&#920;</mo><mo stretchy="false">(</mo><mi>log</mi><mi>n</mi><mo stretchy="false">)</mo></mrow></math>. Thus we have an algorithm that is depth-efficient (modulo constant factors) but work-inefficient.</p>

<h4 id="composition">Composition</h4>

<p>A binary tree as defined above is either a leaf or a pair of binary trees. We can make this pair-ness more explicit with a reformulation:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">data</span> <span class="dt">T2</span> a <span class="fu">=</span> <span class="dt">L2</span> a <span class="fu">|</span> <span class="dt">B2</span> (<span class="dt">Pair</span> (<span class="dt">T2</span> a)) <span class="kw">deriving</span> <span class="kw">Functor</span></code></pre>

<p>where <code>Pair</code>, as in <a href="http://conal.net/blog/posts/composable-parallel-scanning/" title="blog post"><em>Composable parallel scanning</em></a>, is defined as</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">data</span> <span class="dt">Pair</span> a <span class="fu">=</span> a <span class="fu">:#</span> a <span class="kw">deriving</span> <span class="kw">Functor</span></code></pre>

<p>or even</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">type</span> <span class="dt">Pair</span> <span class="fu">=</span> <span class="dt">Id</span> &#215; <span class="dt">Id</span></code></pre>

<p>For encoding and decoding, we could use the same representation as with <code>T1</code>, but let&#8217;s instead use a more natural one for the definition of <code>T2</code>:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">instance</span> <span class="dt">EncodeF</span> <span class="dt">T2</span> <span class="kw">where</span><br />  <span class="kw">type</span> <span class="dt">Enc</span> <span class="dt">T2</span> <span class="fu">=</span> <span class="dt">Id</span> <span class="fu">+</span> <span class="dt">Pair</span> &#8728; <span class="dt">T2</span><br />  encode (<span class="dt">L2</span> a)  <span class="fu">=</span> <span class="dt">InL</span> (<span class="dt">Id</span> a)<br />  encode (<span class="dt">B2</span> st) <span class="fu">=</span> <span class="dt">InR</span> (<span class="dt">O</span> st)<br />  decode (<span class="dt">InL</span> (<span class="dt">Id</span> a)) <span class="fu">=</span> <span class="dt">L2</span> a<br />  decode (<span class="dt">InR</span> (<span class="dt">O</span> st)) <span class="fu">=</span> <span class="dt">B2</span> st</code></pre>

<p>Boilerplate scanning:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">instance</span> <span class="dt">Scan</span> <span class="dt">T2</span> <span class="kw">where</span><br />  prefixScan <span class="fu">=</span> prefixScanEnc<br />  suffixScan <span class="fu">=</span> suffixScanEnc</code></pre>

<p>for which we&#8217;ll need an applicative instance:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">instance</span> <span class="dt">Applicative</span> <span class="dt">T2</span> <span class="kw">where</span><br />  pure <span class="fu">=</span> <span class="dt">L2</span><br />  <span class="dt">L2</span> f <span class="fu">&lt;*&gt;</span> <span class="dt">L2</span> x <span class="fu">=</span> <span class="dt">L2</span> (f x)<br />  <span class="dt">B2</span> (fs <span class="fu">:#</span> gs) <span class="fu">&lt;*&gt;</span> <span class="dt">B2</span> (xs <span class="fu">:#</span> ys) <span class="fu">=</span> <span class="dt">B2</span> ((fs <span class="fu">&lt;*&gt;</span> xs) <span class="fu">:#</span> (gs <span class="fu">&lt;*&gt;</span> ys))<br />  _ <span class="fu">&lt;*&gt;</span> _ <span class="fu">=</span> <span class="fu">error</span> <span class="st">&quot;T2 (&lt;*&gt;): structure mismatch&quot;</span></code></pre>

<p>The <code>O</code> constructor is for functor composition.</p>

<p>With a small change to the tree type, we can make the composition of <code>Pair</code> and <code>T</code> more explicit:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">data</span> <span class="dt">T3</span> a <span class="fu">=</span> <span class="dt">L3</span> a <span class="fu">|</span> <span class="dt">B3</span> ((<span class="dt">Pair</span> &#8728; <span class="dt">T3</span>) a) <span class="kw">deriving</span> <span class="kw">Functor</span></code></pre>

<p>Then the conversion becomes even simpler, since there&#8217;s no need to add or remove <code>O</code> wrappers:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">instance</span> <span class="dt">EncodeF</span> <span class="dt">T3</span> <span class="kw">where</span><br />  <span class="kw">type</span> <span class="dt">Enc</span> <span class="dt">T3</span> <span class="fu">=</span> <span class="dt">Id</span> <span class="fu">+</span> <span class="dt">Pair</span> &#8728; <span class="dt">T3</span><br />  encode (<span class="dt">L3</span> a)  <span class="fu">=</span> <span class="dt">InL</span> (<span class="dt">Id</span> a)<br />  encode (<span class="dt">B3</span> st) <span class="fu">=</span> <span class="dt">InR</span> st<br />  decode (<span class="dt">InL</span> (<span class="dt">Id</span> a)) <span class="fu">=</span> <span class="dt">L3</span> a<br />  decode (<span class="dt">InR</span> st)     <span class="fu">=</span> <span class="dt">B3</span> st</code></pre>

<h4 id="bottom-up-trees">Bottom-up trees</h4>

<p>In the formulations above, a non-leaf tree consists of a pair of trees. I&#8217;ll call these trees &quot;top-down&quot;, since visible pair structure begins at the top.</p>

<p>With a very small change, we can instead use a tree of pairs:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">data</span> <span class="dt">T4</span> a <span class="fu">=</span> <span class="dt">L4</span> a <span class="fu">|</span> <span class="dt">B4</span> (<span class="dt">T4</span> (<span class="dt">Pair</span> a)) <span class="kw">deriving</span> <span class="kw">Functor</span></code></pre>

<p>Again an applicative instance allows a standard <code>Scan</code> instance:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">instance</span> <span class="dt">Scan</span> <span class="dt">T4</span> <span class="kw">where</span><br />  prefixScan <span class="fu">=</span> prefixScanEnc<br />  suffixScan <span class="fu">=</span> suffixScanEnc<br /><br /><span class="kw">instance</span> <span class="dt">Applicative</span> <span class="dt">T4</span> <span class="kw">where</span><br />  pure <span class="fu">=</span> <span class="dt">L4</span><br />  <span class="dt">L4</span> f   <span class="fu">&lt;*&gt;</span> <span class="dt">L4</span> x   <span class="fu">=</span> <span class="dt">L4</span> (f x)<br />  <span class="dt">B4</span> fgs <span class="fu">&lt;*&gt;</span> <span class="dt">B4</span> xys <span class="fu">=</span> <span class="dt">B4</span> (liftA2 h fgs xys)<br />   <span class="kw">where</span> h (f <span class="fu">:#</span> g) (x <span class="fu">:#</span> y) <span class="fu">=</span> f x <span class="fu">:#</span> g y<br />  _ <span class="fu">&lt;*&gt;</span> _ <span class="fu">=</span> <span class="fu">error</span> <span class="st">&quot;T4 (&lt;*&gt;): structure mismatch&quot;</span></code></pre>

<p>or a more explicitly composed form:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">data</span> <span class="dt">T5</span> a <span class="fu">=</span> <span class="dt">L5</span> a <span class="fu">|</span> <span class="dt">B5</span> ((<span class="dt">T5</span> &#8728; <span class="dt">Pair</span>) a) <span class="kw">deriving</span> <span class="kw">Functor</span></code></pre>

<p>I&#8217;ll call these new variations &quot;bottom-up&quot; trees, since visible pair structure begins at the bottom. After stripping off the branch constructor, <code>B4</code>, we can get at the pair-valued leaves by means of <code>fmap</code>, <code>fold</code>, or <code>traverse</code> (or variations). For <code>B5</code>, we&#8217;d also have to strip off the <code>O</code> wrapper (functor composition).</p>

<p>Encoding is nearly the same as with top-down trees. For instance,</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">instance</span> <span class="dt">EncodeF</span> <span class="dt">T4</span> <span class="kw">where</span><br />  <span class="kw">type</span> <span class="dt">Enc</span> <span class="dt">T4</span> <span class="fu">=</span> <span class="dt">Id</span> <span class="fu">+</span> <span class="dt">T4</span> &#8728; <span class="dt">Pair</span><br />  encode (<span class="dt">L4</span> a) <span class="fu">=</span> <span class="dt">InL</span> (<span class="dt">Id</span> a)<br />  encode (<span class="dt">B4</span> t) <span class="fu">=</span> <span class="dt">InR</span> (<span class="dt">O</span> t)<br />  decode (<span class="dt">InL</span> (<span class="dt">Id</span> a)) <span class="fu">=</span> <span class="dt">L4</span> a<br />  decode (<span class="dt">InR</span> (<span class="dt">O</span> t))  <span class="fu">=</span> <span class="dt">B4</span> t</code></pre>

<h3 id="scanning-pairs">Scanning pairs</h3>

<p>We&#8217;ll need to scan on the <code>Pair</code> functor. If we use the definition of <code>Pair</code> above in terms of <code>Id</code> and <code>(×)</code>, then we&#8217;ll get scanning for free. For <em>using</em> <code>Pair</code>, I find the explicit data type definition above more convenient. We can then derive a <code>Scan</code> instance by conversion. Start with a standard specification:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">data</span> <span class="dt">Pair</span> a <span class="fu">=</span> a <span class="fu">:#</span> a <span class="kw">deriving</span> <span class="kw">Functor</span></code></pre>

<p>And encode &amp; decode explicitly:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">instance</span> <span class="dt">EncodeF</span> <span class="dt">Pair</span> <span class="kw">where</span><br />  <span class="kw">type</span> <span class="dt">Enc</span> <span class="dt">Pair</span> <span class="fu">=</span> <span class="dt">Id</span> &#215; <span class="dt">Id</span><br />  encode (a <span class="fu">:#</span> b) <span class="fu">=</span> <span class="dt">Id</span> a &#215; <span class="dt">Id</span> b<br />  decode (<span class="dt">Id</span> a &#215; <span class="dt">Id</span> b) <span class="fu">=</span> a <span class="fu">:#</span> b</code></pre>

<p>Then use our boilerplate <code>Scan</code> instance for <code>EncodeF</code> instances:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">instance</span> <span class="dt">Scan</span> <span class="dt">Pair</span> <span class="kw">where</span><br />  prefixScan <span class="fu">=</span> prefixScanEnc<br />  suffixScan <span class="fu">=</span> suffixScanEnc</code></pre>

<p>We&#8217;ve seen the <code>Scan</code> instance for <code>(×)</code> above. The instance for <code>Id</code> is very simple:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">newtype</span> <span class="dt">Id</span> a <span class="fu">=</span> <span class="dt">Id</span> a<br /><br /><span class="kw">instance</span> <span class="dt">Scan</span> <span class="dt">Id</span> <span class="kw">where</span><br />  prefixScan (<span class="dt">Id</span> m) <span class="fu">=</span> (m, <span class="dt">Id</span> &#8709;)<br />  suffixScan        <span class="fu">=</span> prefixScan</code></pre>

<p>Given these definitions, we can calculate a more streamlined <code>Scan</code> instance for <code>Pair</code>:</p>

<pre class="sourceCode"><code class="sourceCode haskell">  prefixScan (a <span class="fu">:#</span> b)<br />&#8801;  <span class="co">{- specification -}</span><br />  prefixScanEnc (a <span class="fu">:#</span> b)<br />&#8801;  <span class="co">{- prefixScanEnc definition -}</span><br />  (second decode &#8728; prefixScan &#8728; encode) (a <span class="fu">:#</span> b)<br />&#8801;  <span class="co">{- (&#8728;) -}</span><br />  second decode (prefixScan (encode (a <span class="fu">:#</span> b)))<br />&#8801;  <span class="co">{- encode definition for Pair -}</span><br />  second decode (prefixScan (<span class="dt">Id</span> a &#215; <span class="dt">Id</span> b))<br />&#8801;  <span class="co">{- prefixScan definition for f &#215; g -}</span><br />  second decode<br />    (af &#8853; ag, fa' &#215; ((af &#8853;) <span class="fu">&lt;$&gt;</span> ga'))<br />     <span class="kw">where</span> (af,fa') <span class="fu">=</span> prefixScan (<span class="dt">Id</span> a)<br />           (ag,ga') <span class="fu">=</span> prefixScan (<span class="dt">Id</span> b)<br />&#8801;  <span class="co">{- Definition of second on functions -}</span><br />  (af &#8853; ag, decode (fa' &#215; ((af &#8853;) <span class="fu">&lt;$&gt;</span> ga')))<br />   <span class="kw">where</span> (af,fa') <span class="fu">=</span> prefixScan (<span class="dt">Id</span> a)<br />         (ag,ga') <span class="fu">=</span> prefixScan (<span class="dt">Id</span> b)<br />&#8801;  <span class="co">{- prefixScan definition for Id -}</span><br />  (af &#8853; ag, decode (fa' &#215; ((af &#8853;) <span class="fu">&lt;$&gt;</span> ga')))<br />   <span class="kw">where</span> (af,fa') <span class="fu">=</span> (a, <span class="dt">Id</span> &#8709;)<br />         (ag,ga') <span class="fu">=</span> (b, <span class="dt">Id</span> &#8709;)<br />&#8801;  <span class="co">{- substitution -}</span><br />  (a &#8853; b, decode (<span class="dt">Id</span> &#8709; &#215; ((a &#8853;) <span class="fu">&lt;$&gt;</span> <span class="dt">Id</span> &#8709;)))<br />&#8801;  <span class="co">{- fmap/(&lt;$&gt;) for Id -}</span><br />  (a &#8853; b, decode (<span class="dt">Id</span> &#8709; &#215; <span class="dt">Id</span> (a &#8853; &#8709;)))<br />&#8801;  <span class="co">{- Monoid law -}</span><br />  (a &#8853; b, decode (<span class="dt">Id</span> &#8709; &#215; <span class="dt">Id</span> a))<br />&#8801;  <span class="co">{- decode definition on Pair -}</span><br />  (a &#8853; b, (&#8709; <span class="fu">:#</span> a))</code></pre>

<p>Whew! And similarly for <code>suffixScan</code>.</p>

<p>Now let&#8217;s recall the <code>Scan</code> instance for <code>Pair</code> given in <a href="http://conal.net/blog/posts/composable-parallel-scanning/" title="blog post"><em>Composable parallel scanning</em></a>:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">instance</span> <span class="dt">Scan</span> <span class="dt">Pair</span> <span class="kw">where</span><br />  prefixScan (a <span class="fu">:#</span> b) <span class="fu">=</span> (a &#8853; b, (&#8709; <span class="fu">:#</span> a))<br />  suffixScan (a <span class="fu">:#</span> b) <span class="fu">=</span> (a &#8853; b, (b <span class="fu">:#</span> &#8709;))</code></pre>

<p>Hurray! The derivation led us to the same definition. A &quot;sufficiently smart&quot; compiler could do this derivation automatically.</p>

<p>With this warm-up derivation, let&#8217;s now turn to trees.</p>

<h3 id="scanning-trees">Scanning trees</h3>

<p>Given the tree encodings above, how does scan work? We&#8217;ll have to consult <code>Scan</code> instances for some of the functor combinators. The product instance is repeated above. We&#8217;ll also want the instances for sum and composition. Omitting the <code>suffixScan</code> definitions for brevity:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">data</span> (f <span class="fu">+</span> g) a <span class="fu">=</span> <span class="dt">InL</span> (f a) <span class="fu">|</span> <span class="dt">InR</span> (g a)<br /><br /><span class="kw">instance</span> (<span class="dt">Scan</span> f, <span class="dt">Scan</span> g) <span class="ot">&#8658;</span> <span class="dt">Scan</span> (f <span class="fu">+</span> g) <span class="kw">where</span><br />  prefixScan (<span class="dt">InL</span> fa) <span class="fu">=</span> second <span class="dt">InL</span> (prefixScan fa)<br />  prefixScan (<span class="dt">InR</span> ga) <span class="fu">=</span> second <span class="dt">InR</span> (prefixScan ga)<br /><br /><span class="kw">newtype</span> (g &#8728; f) a <span class="fu">=</span> <span class="dt">O</span> (g (f a))<br /><br /><span class="kw">instance</span> (<span class="dt">Scan</span> g, <span class="dt">Scan</span> f, <span class="kw">Functor</span> f, <span class="dt">Applicative</span> g) <span class="ot">&#8658;</span> <span class="dt">Scan</span> (g &#8728; f) <span class="kw">where</span><br />  prefixScan <span class="fu">=</span> second (<span class="dt">O</span> &#8728; <span class="fu">fmap</span> adjustL &#8728; <span class="fu">zip</span>)<br />             &#8728; assocR<br />             &#8728; first prefixScan<br />             &#8728; <span class="fu">unzip</span><br />             &#8728; <span class="fu">fmap</span> prefixScan<br />             &#8728; unO</code></pre>

<p>This last definition uses a few utility functions:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="fu">zip</span> <span class="ot">&#8759;</span> <span class="dt">Applicative</span> g <span class="ot">&#8658;</span> (g a, g b) <span class="ot">&#8594;</span> g (a,b)<br /><span class="fu">zip</span> <span class="fu">=</span> <span class="fu">uncurry</span> (liftA2 (,))<br /><br /><span class="fu">unzip</span> <span class="ot">&#8759;</span> <span class="kw">Functor</span> g <span class="ot">&#8658;</span> g (a,b) <span class="ot">&#8594;</span> (g a, g b)<br /><span class="fu">unzip</span> <span class="fu">=</span> <span class="fu">fmap</span> <span class="fu">fst</span> <span class="fu">&amp;&amp;&amp;</span> <span class="fu">fmap</span> <span class="fu">snd</span><br /><br />assocR <span class="ot">&#8759;</span> ((a,b),c) <span class="ot">&#8594;</span> (a,(b,c))<br />assocR   ((a,b),c) <span class="fu">=</span>  (a,(b,c))<br /><br />adjustL <span class="ot">&#8759;</span> (<span class="kw">Functor</span> f, <span class="dt">Monoid</span> m) <span class="ot">&#8658;</span> (m, f m) <span class="ot">&#8594;</span> f m<br />adjustL (m, ms) <span class="fu">=</span> (m &#8853;) <span class="fu">&lt;$&gt;</span> ms</code></pre>

<p>Let&#8217;s consider how the <code>Scan (g ∘ f)</code> instance plays out for top-down vs bottom-up trees, given the functor-composition encodings above. The critical definitions:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">type</span> <span class="dt">Enc</span> <span class="dt">T2</span> <span class="fu">=</span> <span class="dt">Id</span> <span class="fu">+</span> <span class="dt">Pair</span> &#8728; <span class="dt">T2</span><br /><br /><span class="kw">type</span> <span class="dt">Enc</span> <span class="dt">T4</span> <span class="fu">=</span> <span class="dt">Id</span> <span class="fu">+</span> <span class="dt">T4</span> &#8728; <span class="dt">Pair</span></code></pre>

<p>Focusing on the branch case, we have <code>Pair ∘ T2</code> vs <code>T4 ∘ Pair</code>, so we&#8217;ll use the <code>Scan (g ∘ f)</code> instance either way. Let&#8217;s consider the work implied by that instance. There are two calls to <code>prefixScan</code>, plus a linear amount of other work. The meanings of those two calls differ, however:</p>

<ul>
<li>For top-down trees (<code>T2</code>), the recursive tree scans are in <code>fmap prefixScan</code>, mapping over the pair of trees. The <code>first prefixScan</code> is a pair scan and so does constant work. Since there are two recursive calls, each working on a tree of half size (assuming balance), plus linear other work, the total work <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mo>&#920;</mo><mo stretchy="false">(</mo><mi>n</mi><mspace width="0.167em"></mspace><mi>log</mi><mspace width="0.167em"></mspace><mi>n</mi><mo stretchy="false">)</mo></mrow></math>, as explained above.</li>
<li>For bottom-up trees (<code>T4</code>), there is only one recursive recursive tree scan, which appears in <code>first prefixScan</code>. The <code>prefixScan</code> in <code>fmap prefixScan</code> is pair scan and so does constant work but is mapped over the half-sized tree (of pairs), and so does linear work altogether. Since there only one recursive tree scan, at half size, plus linear other work, the total work is then proportional to <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>n</mi><mo>+</mo><mi>n</mi><mo>/</mo><mn>2</mn><mo>+</mo><mi>n</mi><mo>/</mo><mn>4</mn><mo>+</mo><mo>&#8230;</mo><mo>&#8776;</mo><mn>2</mn><mspace width="0.167em"></mspace><mi>n</mi><mo>=</mo><mo>&#920;</mo><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow></math>. So we have a work-efficient algorithm!</li>
</ul>

<h3 id="looking-deeper">Looking deeper</h3>

<p>In addition to the simple analysis above of scanning over top-down and over bottom-up, let&#8217;s look in detail at what transpires and how each case can be optimized. This section may well have more detail than you&#8217;re interested in. If so, feel free to skip ahead.</p>

<h4 id="top-down">Top-down</h4>

<p>Beginning as with <code>Pair</code>,</p>

<pre class="sourceCode"><code class="sourceCode haskell">  prefixScan t<br />&#8801;  <span class="co">{- specification -}</span><br />  prefixScanEnc t<br />&#8801;  <span class="co">{- prefixScanEnc definition -}</span><br />  (second decode &#8728; prefixScan &#8728; encode) t<br />&#8801;  <span class="co">{- (&#8728;) -}</span><br />  second decode (prefixScan (encode t))</code></pre>

<p>Take <code>T2</code>, with <code>T3</code> being quite similar. Now split into two cases for the two constructors of <code>T2</code>. First leaf:</p>

<pre class="sourceCode"><code class="sourceCode haskell">  prefixScan (<span class="dt">L2</span> m)<br />&#8801;  <span class="co">{- as above -}</span><br />  second decode (prefixScan (encode (<span class="dt">L2</span> m)))<br />&#8801;  <span class="co">{- encode for L2 -}</span><br />  second decode (prefixScan (<span class="dt">InL</span> (<span class="dt">Id</span> m)))<br />&#8801;  <span class="co">{- prefixScan for functor sum -}</span><br />  second decode (second <span class="dt">InL</span> (prefixScan (<span class="dt">Id</span> m)))<br />&#8801;  <span class="co">{- prefixScan for Id -}</span><br />  second decode (second <span class="dt">InL</span> (m, <span class="dt">Id</span> &#8709;))<br />&#8801;  <span class="co">{- second for functions -}</span><br />  second decode (m, <span class="dt">InL</span> (<span class="dt">Id</span> &#8709;))<br />&#8801;  <span class="co">{- second for functions -}</span><br />  (m, decode (<span class="dt">InL</span> (<span class="dt">Id</span> &#8709;)))<br />&#8801;  <span class="co">{- decode for L2 -}</span><br />  (m, <span class="dt">L2</span> &#8709;)</code></pre>

<p>Then branch:</p>

<pre class="sourceCode"><code class="sourceCode haskell">  prefixScan (<span class="dt">B2</span> (s <span class="fu">:#</span> t))<br />&#8801;  <span class="co">{- as above -}</span><br />  second decode (prefixScan (encode (<span class="dt">B2</span> (s <span class="fu">:#</span> t))))<br />&#8801;  <span class="co">{- encode for L2 -}</span><br />  second decode (prefixScan (<span class="dt">InR</span> (<span class="dt">O</span> (s <span class="fu">:#</span> t))))<br />&#8801;  <span class="co">{- prefixScan for (+) -}</span><br />  second decode (second <span class="dt">InR</span> (prefixScan (<span class="dt">O</span> (s <span class="fu">:#</span> t))))<br />&#8801;  <span class="co">{- property of second -}</span><br />  second (decode &#8728; <span class="dt">InR</span>) (prefixScan (<span class="dt">O</span> (s <span class="fu">:#</span> t)))</code></pre>

<p>Focus on the <code>prefixScan</code> application:</p>

<pre class="sourceCode"><code class="sourceCode haskell">  prefixScan (<span class="dt">O</span> (s <span class="fu">:#</span> t)) <span class="fu">=</span><br />&#8801;  <span class="co">{- prefixScan for (&#8728;) -}</span><br /> ( second (<span class="dt">O</span> &#8728; <span class="fu">fmap</span> adjustL &#8728; <span class="fu">zip</span>) &#8728; assocR &#8728; first prefixScan<br /> &#8728; <span class="fu">unzip</span> &#8728; <span class="fu">fmap</span> prefixScan &#8728; unO ) (<span class="dt">O</span> (s <span class="fu">:#</span> t))<br />&#8801;  <span class="co">{- unO/O -}</span><br />  ( second (<span class="dt">O</span> &#8728; <span class="fu">fmap</span> adjustL &#8728; <span class="fu">zip</span>) &#8728; assocR &#8728; first prefixScan<br />  &#8728; <span class="fu">unzip</span> &#8728; <span class="fu">fmap</span> prefixScan ) (s <span class="fu">:#</span> t)<br />&#8801;  <span class="co">{- fmap on Pair -}</span><br />  (second (<span class="dt">O</span> &#8728; <span class="fu">fmap</span> adjustL &#8728; <span class="fu">zip</span>) &#8728; assocR &#8728; first prefixScan &#8728; <span class="fu">unzip</span>)<br />    (prefixScan s <span class="fu">:#</span> prefixScan t)<br />&#8801;  <span class="co">{- expand prefixScan -}</span><br />  (second (<span class="dt">O</span> &#8728; <span class="fu">fmap</span> adjustL &#8728; <span class="fu">zip</span>) &#8728; assocR &#8728; first prefixScan &#8728; <span class="fu">unzip</span>)<br />    ((ms,s') <span class="fu">:#</span> (mt,t'))<br />      <span class="kw">where</span> (ms,s') <span class="fu">=</span> prefixScan s<br />            (mt,t') <span class="fu">=</span> prefixScan t<br />&#8801;  <span class="co">{- unzip -}</span><br />  (second (<span class="dt">O</span> &#8728; <span class="fu">fmap</span> adjustL &#8728; <span class="fu">zip</span>) &#8728; assocR &#8728; first prefixScan)<br />    ((ms <span class="fu">:#</span> mt), (s' <span class="fu">:#</span> t')) <span class="kw">where</span> &#8943;<br />&#8801;  <span class="co">{- first -}</span><br />  (second (<span class="dt">O</span> &#8728; <span class="fu">fmap</span> adjustL &#8728; <span class="fu">zip</span>) &#8728; assocR)<br />    (prefixScan (ms <span class="fu">:#</span> mt), (s' <span class="fu">:#</span> t')) <span class="kw">where</span> &#8943;<br />&#8801;  <span class="co">{- prefixScan for Pair -}</span><br />  (second (<span class="dt">O</span> &#8728; <span class="fu">fmap</span> adjustL &#8728; <span class="fu">zip</span>) &#8728; assocR)<br />    ((ms &#8853; mt, (&#8709; <span class="fu">:#</span> ms)), (s' <span class="fu">:#</span> t')) <span class="kw">where</span> &#8943;<br />&#8801;  <span class="co">{- assocR -}</span><br />  (second (<span class="dt">O</span> &#8728; <span class="fu">fmap</span> adjustL &#8728; <span class="fu">zip</span>))<br />    (ms &#8853; mt, ((&#8709; <span class="fu">:#</span> ms), (s' <span class="fu">:#</span> t'))) <span class="kw">where</span> &#8943;<br />&#8801;  <span class="co">{- second -}</span><br />  ( ms &#8853; mt<br />  , (<span class="dt">O</span> &#8728; <span class="fu">fmap</span> adjustL &#8728; <span class="fu">zip</span>) ((&#8709; <span class="fu">:#</span> ms), (s' <span class="fu">:#</span> t')) ) <span class="kw">where</span> &#8943;<br />&#8801;  <span class="co">{- zip -}</span><br />  ( ms &#8853; mt<br />  , (<span class="dt">O</span> &#8728; <span class="fu">fmap</span> adjustL) ((&#8709;,s') <span class="fu">:#</span> (ms,t')) )  <span class="kw">where</span> &#8943;<br />&#8801;  <span class="co">{- fmap for Pair -}</span><br />  ( ms &#8853; mt<br />  , <span class="dt">O</span> (adjustL (&#8709;,s') <span class="fu">:#</span> adjustL (ms,t')) )  <span class="kw">where</span> &#8943;<br />&#8801;  <span class="co">{- adjustL -}</span><br />  ( ms &#8853; mt<br />  , <span class="dt">O</span> (((&#8709; &#8853;) <span class="fu">&lt;$&gt;</span> s') <span class="fu">:#</span> ((ms &#8853;) <span class="fu">&lt;$&gt;</span> t')) )  <span class="kw">where</span> &#8943;<br />&#8801;  <span class="co">{- Monoid law (left identity) -}</span><br />  ( ms &#8853; mt<br />  , <span class="dt">O</span> ((<span class="fu">id</span> <span class="fu">&lt;$&gt;</span> s') <span class="fu">:#</span> ((ms &#8853;) <span class="fu">&lt;$&gt;</span> t')) )  <span class="kw">where</span> &#8943;<br />&#8801;  <span class="co">{- Functor law (fmap id) -}</span><br />  ( ms &#8853; mt<br />  , <span class="dt">O</span> (s' <span class="fu">:#</span> ((ms &#8853;) <span class="fu">&lt;$&gt;</span> t')) )<br />      <span class="kw">where</span> (ms,s') <span class="fu">=</span> prefixScan s<br />            (mt,t') <span class="fu">=</span> prefixScan t</code></pre>

<p>Continuing from above,</p>

<pre class="sourceCode"><code class="sourceCode haskell">  prefixScan (<span class="dt">B2</span> (s <span class="fu">:#</span> t))<br />&#8801;  <span class="co">{- see above -}</span><br />  second (decode &#8728; <span class="dt">InR</span>) (prefixScan (<span class="dt">O</span> (s <span class="fu">:#</span> t)))<br />&#8801;  <span class="co">{- prefixScan focus from above -}</span><br />  second (decode &#8728; <span class="dt">InR</span>)<br />    ( ms &#8853; mt<br />    , <span class="dt">O</span> (s' <span class="fu">:#</span> ((ms &#8853;) <span class="fu">&lt;$&gt;</span> t')) )<br />        <span class="kw">where</span> (ms,s') <span class="fu">=</span> prefixScan s<br />              (mt,t') <span class="fu">=</span> prefixScan t<br />&#8801;  <span class="co">{- definition of second on functions -}</span><br />    (ms &#8853; mt, (decode &#8728; <span class="dt">InR</span>) (<span class="dt">O</span> (s' <span class="fu">:#</span> ((ms &#8853;) <span class="fu">&lt;$&gt;</span> t')))) <span class="kw">where</span> &#8943;<br />&#8801;  <span class="co">{- (&#8728;) -}</span><br />    (ms &#8853; mt, decode (<span class="dt">InR</span> (<span class="dt">O</span> (s' <span class="fu">:#</span> ((ms &#8853;) <span class="fu">&lt;$&gt;</span> t'))))) <span class="kw">where</span> &#8943;<br />&#8801;  <span class="co">{- decode for B2 -}</span><br />    (ms &#8853; mt, <span class="dt">B2</span> (s' <span class="fu">:#</span> ((ms &#8853;) <span class="fu">&lt;$&gt;</span> t'))) <span class="kw">where</span> &#8943;</code></pre>

<p>This final form is as in <a href="http://conal.net/blog/posts/deriving-parallel-tree-scans/" title="blog post"><em>Deriving parallel tree scans</em></a>, changed for the new scan interface. The derivation saved some work in wrapping &amp; unwrapping and method invocation, plus one of the two adjustment passes over the sub-trees. As explained above, this algorithm performs <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mo>&#920;</mo><mo stretchy="false">(</mo><mi>n</mi><mspace width="0.167em"></mspace><mi>log</mi><mspace width="0.167em"></mspace><mi>n</mi><mo stretchy="false">)</mo></mrow></math> work.</p>

<p>I&#8217;ll leave <code>suffixScan</code> for you to do yourself.</p>

<h4 id="bottom-up">Bottom-up</h4>

<p>What happens if we switch from top-down to bottom-up binary trees? I&#8217;ll use <code>T4</code> (though <code>T5</code> would work as well):</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">data</span> <span class="dt">T4</span> a <span class="fu">=</span> <span class="dt">L4</span> a <span class="fu">|</span> <span class="dt">B4</span> (<span class="dt">T4</span> (<span class="dt">Pair</span> a))</code></pre>

<p>The leaf case is just as with <code>T2</code> above, so let&#8217;s get right to branches.</p>

<pre class="sourceCode"><code class="sourceCode haskell">  prefixScan (<span class="dt">B4</span> t)<br />&#8801;  <span class="co">{- as above -}</span><br />  second decode (prefixScan (encode (<span class="dt">B4</span> t)))<br />&#8801;  <span class="co">{- encode for L2 -}</span><br />  second decode (prefixScan (<span class="dt">InR</span> (<span class="dt">O</span> t)))<br />&#8801;  <span class="co">{- prefixScan for (+) -}</span><br />  second decode (second <span class="dt">InR</span> (prefixScan (<span class="dt">O</span> t)))<br />&#8801;  <span class="co">{- property of second -}</span><br />  second (decode &#8728; <span class="dt">InR</span>) (prefixScan (<span class="dt">O</span> t))</code></pre>

<p>As before, now focus on the <code>prefixScan</code> call.</p>

<pre class="sourceCode"><code class="sourceCode haskell">  prefixScan (<span class="dt">O</span> t) <span class="fu">=</span><br />&#8801;  <span class="co">{- prefixScan for (&#8728;) -}</span><br /> ( second (<span class="dt">O</span> &#8728; <span class="fu">fmap</span> adjustL &#8728; <span class="fu">zip</span>) &#8728; assocR &#8728; first prefixScan<br /> &#8728; <span class="fu">unzip</span> &#8728; <span class="fu">fmap</span> prefixScan &#8728; unO ) (<span class="dt">O</span> t)<br />&#8801;  <span class="co">{- unO/O -}</span><br />  ( second (<span class="dt">O</span> &#8728; <span class="fu">fmap</span> adjustL &#8728; <span class="fu">zip</span>) &#8728; assocR &#8728; first prefixScan<br />  &#8728; <span class="fu">unzip</span> &#8728; <span class="fu">fmap</span> prefixScan ) t<br />&#8801;  <span class="co">{- prefixScan on Pair (derived above) -}</span><br />  (second (<span class="dt">O</span> &#8728; <span class="fu">fmap</span> adjustL &#8728; <span class="fu">zip</span>) &#8728; assocR &#8728; first prefixScan &#8728; <span class="fu">unzip</span>)<br />    <span class="fu">fmap</span> (&#955; (a <span class="fu">:#</span> b) <span class="ot">&#8594;</span> (a &#8853; b, (&#8709; <span class="fu">:#</span> a))) t<br />&#8801;  <span class="co">{- unzip/fmap -}</span><br />  (second (<span class="dt">O</span> &#8728; <span class="fu">fmap</span> adjustL &#8728; <span class="fu">zip</span>) &#8728; assocR &#8728; first prefixScan)<br />    ( <span class="fu">fmap</span> (&#955; (a <span class="fu">:#</span> b) <span class="ot">&#8594;</span> (a &#8853; b)) t<br />    , <span class="fu">fmap</span> (&#955; (a <span class="fu">:#</span> b) <span class="ot">&#8594;</span> (&#8709; <span class="fu">:#</span> a))   t )<br />&#8801;  <span class="co">{- first on functions -}</span><br />  (second (<span class="dt">O</span> &#8728; <span class="fu">fmap</span> adjustL &#8728; <span class="fu">zip</span>) &#8728; assocR)<br />    ( prefixScan (<span class="fu">fmap</span> (&#955; (a <span class="fu">:#</span> b) <span class="ot">&#8594;</span> (a &#8853; b)) t)<br />    , <span class="fu">fmap</span> (&#955; (a <span class="fu">:#</span> b) <span class="ot">&#8594;</span> (&#8709; <span class="fu">:#</span> a))   t )<br />&#8801;  <span class="co">{- expand prefixScan -}</span><br />  (second (<span class="dt">O</span> &#8728; <span class="fu">fmap</span> adjustL &#8728; <span class="fu">zip</span>) &#8728; assocR)<br />    ((mp,p'), <span class="fu">fmap</span> (&#955; (a <span class="fu">:#</span> b) <span class="ot">&#8594;</span> (&#8709; <span class="fu">:#</span> a)) t)<br />   <span class="kw">where</span> (mp,p') <span class="fu">=</span> prefixScan (<span class="fu">fmap</span> (&#955; (a <span class="fu">:#</span> b) <span class="ot">&#8594;</span> (a &#8853; b)) t)<br />&#8801;  <span class="co">{- assocR -}</span><br />  (second (<span class="dt">O</span> &#8728; <span class="fu">fmap</span> adjustL &#8728; <span class="fu">zip</span>))<br />    (mp, (p', <span class="fu">fmap</span> (&#955; (a <span class="fu">:#</span> b) <span class="ot">&#8594;</span> (&#8709; <span class="fu">:#</span> a)) t))<br />   <span class="kw">where</span> &#8943;<br />&#8801;  <span class="co">{- second on functions -}</span><br />  (mp, (<span class="dt">O</span> &#8728; <span class="fu">fmap</span> adjustL &#8728; <span class="fu">zip</span>) (p', <span class="fu">fmap</span> (&#955; (a <span class="fu">:#</span> b) <span class="ot">&#8594;</span> (&#8709; <span class="fu">:#</span> a)) t))<br />    <span class="kw">where</span> &#8943;<br />&#8801;  <span class="co">{- fmap/zip/fmap -}</span><br />  (mp, <span class="dt">O</span> (liftA2 tweak p' t))<br />    <span class="kw">where</span> tweak s (a <span class="fu">:#</span> _) <span class="fu">=</span> adjustL (s, (&#8709; <span class="fu">:#</span> a))<br />          (mp,p') <span class="fu">=</span> prefixScan (<span class="fu">fmap</span> (&#955; (a <span class="fu">:#</span> b) <span class="ot">&#8594;</span> (a &#8853; b)) t)<br />&#8801;  <span class="co">{- adjustL, then simplify -}</span><br />  (mp, <span class="dt">O</span> (liftA2 tweak p' t))<br />    <span class="kw">where</span> tweak s (a <span class="fu">:#</span> _) <span class="fu">=</span> (s <span class="fu">:#</span> s &#8853; a)<br />          (mp,p') <span class="fu">=</span> prefixScan (<span class="fu">fmap</span> (&#955; (a <span class="fu">:#</span> b) <span class="ot">&#8594;</span> (a &#8853; b)) t)</code></pre>

<p>Now re-introduce the context of <code>prefixScan (O t)</code>:</p>

<pre class="sourceCode"><code class="sourceCode haskell">  prefixScan (<span class="dt">B4</span> t)<br />&#8801;  <span class="co">{- see above -}</span><br />  second (decode &#8728; <span class="dt">InR</span>) (prefixScan (<span class="dt">O</span> t))<br />&#8801;  <span class="co">{- see above -}</span><br />  second (decode &#8728; <span class="dt">InR</span>)<br />    (mp, <span class="dt">O</span> (liftA2 tweak p' t))<br />      <span class="kw">where</span> &#8943;<br />&#8801;  <span class="co">{- decode for T4 -}</span><br />  (mp, <span class="dt">B4</span> (liftA2 tweak p' t))<br />    <span class="kw">where</span> p <span class="fu">=</span> <span class="fu">fmap</span> (&#955; (e <span class="fu">:#</span> o) <span class="ot">&#8594;</span> (e &#8853; o)) t<br />          (mp,p') <span class="fu">=</span> prefixScan p<br />          tweak s (e <span class="fu">:#</span> _) <span class="fu">=</span> (s <span class="fu">:#</span> s &#8853; e)</code></pre>

<p>Notice how much this bottom-up tree scan algorithm differs from the top-down algorithm derived above. In particular, there&#8217;s only one recursive tree scan (on a half-sized tree) instead of two, plus linear additional work, for a total of <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mo>&#920;</mo><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow></math> work.</p>

<h3 id="guy-blellochs-parallel-scan-algorithm">Guy Blelloch&#8217;s parallel scan algorithm</h3>

<p>In <a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.53.5739" title="Paper by Guy Blelloch"><em>Programming parallel algorithms</em></a>, Guy Blelloch gives the following algorithm for parallel prefix scan, expressed in the parallel functional language NESL:</p>

<pre class="sourceCode"><code class="sourceCode haskell">function scan(a) <span class="fu">=</span><br /><span class="kw">if</span> <span class="fu">#</span>a &#8801; <span class="dv">1</span> <span class="kw">then</span> [<span class="dv">0</span>]<br /><span class="kw">else</span><br />  <span class="kw">let</span> es <span class="fu">=</span> even_elts(a);<br />      os <span class="fu">=</span> odd_elts(a);<br />      ss <span class="fu">=</span> scan({e<span class="fu">+</span>o<span class="fu">:</span> e <span class="kw">in</span> es; o <span class="kw">in</span> os})<br />  <span class="kw">in</span> interleave(ss,{s<span class="fu">+</span>e<span class="fu">:</span> s <span class="kw">in</span> ss; e <span class="kw">in</span> es})</code></pre>

<p>This algorithm is nearly identical to the <code>T4</code> scan algorithm above. I was very glad to find this route to Guy&#8217;s algorithm, which had been fairly mysterious to me. I mean, I could believe that the algorithm worked, but I had no idea how I might have discovered it myself. With the functor composition approach to scanning, I now see how Guy&#8217;s algorithm emerges as well as how it generalizes to other data structures.</p>

<h3 id="nested-data-types-and-parallelism">Nested data types and parallelism</h3>

<p>Most of the recursive algebraic data types that appear in Haskell programs are <em>regular</em>, meaning that the recursive instances are instantiated with the same type parameter as the containing type. For instance, a top-down tree of elements of type <code>a</code> is either a leaf or has two trees whose elements have that same type <code>a</code>. In contrast, in a bottom-up tree, the (single) recursively contained tree is over elements of type <code>(a,a)</code>. Such non-regular data types are called &quot;nested&quot;. The two tree scan algorithms above suggest to me that nested data types are particularly useful for efficient parallel algorithms.</p>
<p><a href="http://conal.net/blog/?flattrss_redirect&amp;id=429&amp;md5=a05805e935f7c2c3d368a59c3a7c2adb"><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/parallel-tree-scanning-by-composition/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%2Fparallel-tree-scanning-by-composition&amp;language=en_GB&amp;category=text&amp;title=Parallel+tree+scanning+by+composition&amp;description=My+last+few+blog+posts+have+been+on+the+theme+of+scans%2C+and+particularly+on+parallel+scans.+In+Composable+parallel+scanning%2C+I+tackled+parallel+scanning+in+a+very+general+setting....&amp;tags=functor%2Cprogram+derivation%2Cscan%2Cblog" type="text/html" />
	</item>
		<item>
		<title>Composable parallel scanning</title>
		<link>http://conal.net/blog/posts/composable-parallel-scanning</link>
		<comments>http://conal.net/blog/posts/composable-parallel-scanning#comments</comments>
		<pubDate>Tue, 01 Mar 2011 22:33:36 +0000</pubDate>
		<dc:creator><![CDATA[Conal]]></dc:creator>
				<category><![CDATA[Functional programming]]></category>
		<category><![CDATA[functor]]></category>
		<category><![CDATA[scan]]></category>

		<guid isPermaLink="false">http://conal.net/blog/?p=411</guid>
		<description><![CDATA[The post Deriving list scans gave a simple specification of the list-scanning functions scanl and scanr, and then transformed those specifications into the standard optimized implementations. Next, the post Deriving parallel tree scans adapted the specifications and derivations to a type of binary trees. The resulting implementations are parallel-friendly, but not work-efficient, in that they [&#8230;]]]></description>
				<content:encoded><![CDATA[<!-- teaser -->

<p>The post <a href="http://conal.net/blog/posts/deriving-list-scans/" title="blog post"><em>Deriving list scans</em></a> gave a simple specification of the list-scanning functions <a href="http://hackage.haskell.org/packages/archive/base/latest/doc/html/Data-List.html#v:scanl"><code>scanl</code></a> and <a href="http://hackage.haskell.org/packages/archive/base/latest/doc/html/Data-List.html#v:scanr"><code>scanr</code></a>, and then transformed those specifications into the standard optimized implementations. Next, the post <a href="http://conal.net/blog/posts/deriving-parallel-tree-scans/" title="blog post"><em>Deriving parallel tree scans</em></a> adapted the specifications and derivations to a type of binary trees. The resulting implementations are parallel-friendly, but not work-efficient, in that they perform <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>n</mi><mspace width="0.167em"></mspace><mi>log</mi><mspace width="0.167em"></mspace><mi>n</mi></mrow></math> work vs linear work as in the best-known sequential algorithm.</p>

<p>Besides the work-inefficiency, I don&#8217;t know how to extend the critical <code>initTs</code> and <code>tailTs</code> functions (analogs of <code>inits</code> and <code>tails</code> on lists) to depth-typed, perfectly balanced trees, of the sort I played with in <a href="http://conal.net/blog/posts/a-trie-for-length-typed-vectors/" title="blog post"><em>A trie for length-typed vectors</em></a> and <a href="http://conal.net/blog/posts/from-tries-to-trees/" title="blog post"><em>From tries to trees</em></a>. The difficulty I encounter is that the functions <code>initTs</code> and <code>tailTs</code> make unbalanced trees out of balanced ones, so I don&#8217;t know how to adapt the specifications when types prevent the existence of unbalanced trees.</p>

<p>This new post explores an approach to generalized scanning via type classes. After defining the classes and giving a simple example, I&#8217;ll give a simple &amp; general framework based on composing functor combinators.</p>

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

<ul>
<li>2011-03-02: Fixed typo. &quot;constant functor is easiest&quot; (instead of &quot;identity functor&quot;). Thanks, frguybob.</li>
<li>2011-03-05: Removed final unfinished sentence.</li>
<li>2011-07-28: Replace &quot;<code>assocL</code>&quot; with &quot;<code>assocR</code>&quot; in <code>prefixScan</code> derivation for <code>g ∘ f</code>.</li>
</ul>

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

<h3 id="generalizing-list-scans">Generalizing list scans</h3>

<p>The left and right scan functions on lists have an awkward feature. The output list has one more element than the input list, corresponding to the fact that the number of prefixes (<a href="http://hackage.haskell.org/packages/archive/base/latest/doc/html/Data-List.html#v:inits"><code>inits</code></a>) of a list is one more than the number of elements, and similarly for suffixes (<a href="http://hackage.haskell.org/packages/archive/base/latest/doc/html/Data-List.html#v:tails"><code>tails</code></a>).</p>

<p>While it&#8217;s easy to extend a list by adding one more element, it&#8217;s not easy with other functors. In <a href="http://conal.net/blog/posts/deriving-parallel-tree-scans/" title="blog post"><em>Deriving parallel tree scans</em></a>, I simply removed the <code>∅</code> element from the scan. In this post, I&#8217;ll instead change the interface to produce an output of exactly the same shape, plus one extra element. The extra element will equal a <code>fold</code> over the complete input. If you recall, we had to search for that complete fold in an input subtree in order to adjust the other subtree. (See <code>headT</code> and <code>lastT</code> and their generalizations in <a href="http://conal.net/blog/posts/deriving-parallel-tree-scans/" title="blog post"><em>Deriving parallel tree scans</em></a>.) Separating out this value eliminates the search.</p>

<p>Define a class with methods for prefix and suffix scan:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">class</span> <span class="dt">Scan</span> f <span class="kw">where</span><br />  prefixScan, suffixScan <span class="ot">&#8759;</span> <span class="dt">Monoid</span> m <span class="ot">&#8658;</span> f m <span class="ot">&#8594;</span> (m, f m)</code></pre>

<p>Prefix scans (<code>prefixScan</code>) accumulate moving left-to-right, while suffix scans (<code>suffixScan</code>) accumulate moving right-to-left.</p>

<h4 id="a-simple-example-pairs">A simple example: pairs</h4>

<p>To get a first sense of generalized scans, let&#8217;s use see how to scan over a pair functor.</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">data</span> <span class="dt">Pair</span> a <span class="fu">=</span> a <span class="fu">:#</span> a <span class="kw">deriving</span> (<span class="kw">Eq</span>,<span class="kw">Ord</span>,<span class="kw">Show</span>)</code></pre>

<p>With GHC&#8217;s <code>DeriveFunctor</code> option, we could also derive a <code>Functor</code> instance, but for clarity, define it explicitly:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">instance</span> <span class="kw">Functor</span> <span class="dt">Pair</span> <span class="kw">where</span><br />  <span class="fu">fmap</span> f (a <span class="fu">:#</span> b) <span class="fu">=</span> (f a <span class="fu">:#</span> f b)</code></pre>

<p>The scans:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">instance</span> <span class="dt">Scan</span> <span class="dt">Pair</span> <span class="kw">where</span><br />  prefixScan (a <span class="fu">:#</span> b) <span class="fu">=</span> (a &#8853; b, (&#8709; <span class="fu">:#</span> a))<br />  suffixScan (a <span class="fu">:#</span> b) <span class="fu">=</span> (a &#8853; b, (b <span class="fu">:#</span> &#8709;))</code></pre>

<p>As you can see, if we eliminated the <code>∅</code> elements, we could shift to the left or right and forgo the extra result.</p>

<p>Naturally, there is also a <code>Fold</code> instance, and the scans produce the fold results as well sub-folds:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">instance</span> <span class="dt">Foldable</span> <span class="dt">Pair</span> <span class="kw">where</span><br />  fold (a <span class="fu">:#</span> b) <span class="fu">=</span> a &#8853; b</code></pre>

<p>The <code>Pair</code> functor also has unsurprising instances for <code>Applicative</code> and <code>Traversable</code>.</p>

<div class=toggle>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">instance</span> <span class="dt">Applicative</span> <span class="dt">Pair</span> <span class="kw">where</span><br />  pure a <span class="fu">=</span> a <span class="fu">:#</span> a<br />  (f <span class="fu">:#</span> g) <span class="fu">&lt;*&gt;</span> (x <span class="fu">:#</span> y) <span class="fu">=</span> (f x <span class="fu">:#</span> g y)<br /><br /><span class="kw">instance</span> <span class="dt">Traversable</span> <span class="dt">Pair</span> <span class="kw">where</span><br />  sequenceA (fa <span class="fu">:#</span> fb) <span class="fu">=</span> (<span class="fu">:#</span>) <span class="fu">&lt;$&gt;</span> fa <span class="fu">&lt;*&gt;</span> fb</code></pre>

</div>

<p>We don&#8217;t really have to figure out how to define scans for every functor separately. We can instead look at how functors are are composed out of their essential building blocks.</p>

<h3 id="scans-for-functor-combinators">Scans for functor combinators</h3>

<p>To see how to scan over a broad range of functors, let&#8217;s look at each of the functor combinators, e.g., as in <a href="http://conal.net/blog/posts/elegant-memoization-with-higher-order-types/" title="blog post"><em>Elegant memoization with higher-order types</em></a>.</p>

<h4 id="constant">Constant</h4>

<p>The constant functor is easiest.</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">newtype</span> <span class="dt">Const</span> x a <span class="fu">=</span> <span class="dt">Const</span> x</code></pre>

<p>There are no values to accumulate, so the final result (fold) is <code>∅</code>.</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">instance</span> <span class="dt">Scan</span> (<span class="dt">Const</span> x) <span class="kw">where</span><br />  prefixScan (<span class="dt">Const</span> x) <span class="fu">=</span> (&#8709;, <span class="dt">Const</span> x)<br />  suffixScan           <span class="fu">=</span> prefixScan</code></pre>

<h4 id="identity">Identity</h4>

<p>The identity functor is nearly as easy.</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">newtype</span> <span class="dt">Id</span> a <span class="fu">=</span> <span class="dt">Id</span> a</code></pre>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">instance</span> <span class="dt">Scan</span> <span class="dt">Id</span> <span class="kw">where</span><br />  prefixScan (<span class="dt">Id</span> m) <span class="fu">=</span> (m, <span class="dt">Id</span> &#8709;)<br />  suffixScan        <span class="fu">=</span> prefixScan</code></pre>

<h4 id="sum">Sum</h4>

<p>Scanning in a sum is just scanning in a summand:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">data</span> (f <span class="fu">+</span> g) a <span class="fu">=</span> <span class="dt">InL</span> (f a) <span class="fu">|</span> <span class="dt">InR</span> (g a)</code></pre>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">instance</span> (<span class="dt">Scan</span> f, <span class="dt">Scan</span> g) <span class="ot">&#8658;</span> <span class="dt">Scan</span> (f <span class="fu">+</span> g) <span class="kw">where</span><br />  prefixScan (<span class="dt">InL</span> fa) <span class="fu">=</span> second <span class="dt">InL</span> (prefixScan fa)<br />  prefixScan (<span class="dt">InR</span> ga) <span class="fu">=</span> second <span class="dt">InR</span> (prefixScan ga)<br /><br />  suffixScan (<span class="dt">InL</span> fa) <span class="fu">=</span> second <span class="dt">InL</span> (suffixScan fa)<br />  suffixScan (<span class="dt">InR</span> ga) <span class="fu">=</span> second <span class="dt">InR</span> (suffixScan ga)</code></pre>

<p>These definitions correspond to simple &quot;commutative diagram&quot; properties, e.g.,</p>

<pre class="sourceCode"><code class="sourceCode haskell">prefixScan &#8728; <span class="dt">InL</span> &#8801; second <span class="dt">InL</span> &#8728; prefixScan</code></pre>

<h4 id="product">Product</h4>

<p>Product scannning is a little trickier.</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">data</span> (f &#215; g) a <span class="fu">=</span> f a &#215; g a</code></pre>

<p>Scan each of the two parts separately, and then combine the final (<code>fold</code>) part of one result with each of the non-final elements of the other.</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">instance</span> (<span class="dt">Scan</span> f, <span class="dt">Scan</span> g, <span class="kw">Functor</span> f, <span class="kw">Functor</span> g) <span class="ot">&#8658;</span> <span class="dt">Scan</span> (f &#215; g) <span class="kw">where</span><br />  prefixScan (fa &#215; ga) <span class="fu">=</span> (af &#8853; ag, fa' &#215; ((af &#8853;) <span class="fu">&lt;$&gt;</span> ga'))<br />   <span class="kw">where</span> (af,fa') <span class="fu">=</span> prefixScan fa<br />         (ag,ga') <span class="fu">=</span> prefixScan ga<br /><br />  suffixScan (fa &#215; ga) <span class="fu">=</span> (af &#8853; ag, ((&#8853; ag) <span class="fu">&lt;$&gt;</span> fa') &#215; ga')<br />   <span class="kw">where</span> (af,fa') <span class="fu">=</span> suffixScan fa<br />         (ag,ga') <span class="fu">=</span> suffixScan ga</code></pre>

<h4 id="composition">Composition</h4>

<p>Finally, composition is the trickiest.</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">newtype</span> (g &#8728; f) a <span class="fu">=</span> <span class="dt">O</span> (g (f a))</code></pre>

<p>The target signatures:</p>

<pre class="sourceCode"><code class="sourceCode haskell">  prefixScan, suffixScan <span class="ot">&#8759;</span> <span class="dt">Monoid</span> m <span class="ot">&#8658;</span> (g &#8728; f) m <span class="ot">&#8594;</span> (m, (g &#8728; f) m)</code></pre>

<p>To find the prefix and suffix scan definitions, fiddle with types beginning at the domain type for <code>prefixScan</code> or <code>suffixScan</code> and arriving at the range type.</p>

<p>Some helpers:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="fu">zip</span> <span class="ot">&#8759;</span> <span class="dt">Applicative</span> g <span class="ot">&#8658;</span> (g a, g b) <span class="ot">&#8594;</span> g (a,b)<br /><span class="fu">zip</span> <span class="fu">=</span> <span class="fu">uncurry</span> (liftA2 (,))<br /><br /><span class="fu">unzip</span> <span class="ot">&#8759;</span> <span class="kw">Functor</span> g <span class="ot">&#8658;</span> g (a,b) <span class="ot">&#8594;</span> (g a, g b)<br /><span class="fu">unzip</span> <span class="fu">=</span> <span class="fu">fmap</span> <span class="fu">fst</span> <span class="fu">&amp;&amp;&amp;</span> <span class="fu">fmap</span> <span class="fu">snd</span></code></pre>

<pre class="sourceCode"><code class="sourceCode haskell">assocR <span class="ot">&#8759;</span> ((a,b),c) <span class="ot">&#8594;</span> (a,(b,c))<br />assocR   ((a,b),c) <span class="fu">=</span>  (a,(b,c))</code></pre>

<pre class="sourceCode"><code class="sourceCode haskell">adjustL <span class="ot">&#8759;</span> (<span class="kw">Functor</span> f, <span class="dt">Monoid</span> m) <span class="ot">&#8658;</span> (m, f m) <span class="ot">&#8594;</span> f m<br />adjustL (m, ms) <span class="fu">=</span> (m &#8853;) <span class="fu">&lt;$&gt;</span> ms<br /><br />adjustR <span class="ot">&#8759;</span> (<span class="kw">Functor</span> f, <span class="dt">Monoid</span> m) <span class="ot">&#8658;</span> (m, f m) <span class="ot">&#8594;</span> f m<br />adjustR (m, ms) <span class="fu">=</span> (&#8853; m) <span class="fu">&lt;$&gt;</span> ms</code></pre>

<p>First <code>prefixScan</code>:</p>

<pre class="sourceCode"><code class="sourceCode haskell">gofm                     <span class="ot">&#8759;</span> (g &#8728; f) m<br />unO                   <span class="ch">''</span> <span class="ot">&#8759;</span> g (f m)<br /><span class="fu">fmap</span> prefixScan       <span class="ch">''</span> <span class="ot">&#8759;</span> g (m, f m)<br /><span class="fu">unzip</span>                 <span class="ch">''</span> <span class="ot">&#8759;</span> (g m, g (f m))<br />first prefixScan      <span class="ch">''</span> <span class="ot">&#8759;</span> ((m, g m), g (f m))<br />assocR                <span class="ch">''</span> <span class="ot">&#8759;</span> (m, (g m, g (f m)))<br />second <span class="fu">zip</span>            <span class="ch">''</span> <span class="ot">&#8759;</span> (m, g (m, f m))<br />second (<span class="fu">fmap</span> adjustL) <span class="ch">''</span> <span class="ot">&#8759;</span> (m, g (f m))<br />second <span class="dt">O</span>              <span class="ch">''</span> <span class="ot">&#8759;</span> (m, (g &#8728; f) m)</code></pre>

<p>Then <code>suffixScan</code>:</p>

<pre class="sourceCode"><code class="sourceCode haskell">gofm                     <span class="ot">&#8759;</span> (g &#8728; f) m<br />unO                   <span class="ch">''</span> <span class="ot">&#8759;</span> g (f m)<br /><span class="fu">fmap</span> suffixScan       <span class="ch">''</span> <span class="ot">&#8759;</span> g (m, f m)<br /><span class="fu">unzip</span>                 <span class="ch">''</span> <span class="ot">&#8759;</span> (g m, g (f m))<br />first suffixScan      <span class="ch">''</span> <span class="ot">&#8759;</span> ((m, g m), g (f m))<br />assocR                <span class="ch">''</span> <span class="ot">&#8759;</span> (m, (g m, g (f m)))<br />second <span class="fu">zip</span>            <span class="ch">''</span> <span class="ot">&#8759;</span> (m, (g (m, f m)))<br />second (<span class="fu">fmap</span> adjustR) <span class="ch">''</span> <span class="ot">&#8759;</span> (m, (g (f m)))<br />second <span class="dt">O</span>              <span class="ch">''</span> <span class="ot">&#8759;</span> (m, ((g &#8728; f) m))</code></pre>

<p>Putting together the pieces and simplifying just a bit leads to the method definitions:</p>

<pre class="sourceCode"><code class="sourceCode haskell"><span class="kw">instance</span> (<span class="dt">Scan</span> g, <span class="dt">Scan</span> f, <span class="kw">Functor</span> f, <span class="dt">Applicative</span> g) <span class="ot">&#8658;</span> <span class="dt">Scan</span> (g &#8728; f) <span class="kw">where</span><br />  prefixScan <span class="fu">=</span> second (<span class="dt">O</span> &#8728; <span class="fu">fmap</span> adjustL &#8728; <span class="fu">zip</span>)<br />             &#8728; assocR<br />             &#8728; first prefixScan<br />             &#8728; <span class="fu">unzip</span><br />             &#8728; <span class="fu">fmap</span> prefixScan<br />             &#8728; unO<br /><br />  suffixScan <span class="fu">=</span> second (<span class="dt">O</span> &#8728; <span class="fu">fmap</span> adjustR &#8728; <span class="fu">zip</span>)<br />             &#8728; assocR<br />             &#8728; first suffixScan<br />             &#8728; <span class="fu">unzip</span><br />             &#8728; <span class="fu">fmap</span> suffixScan<br />             &#8728; unO</code></pre>

<h3 id="whats-coming-up">What&#8217;s coming up?</h3>

<ul>
<li>What might not easy to spot at this point is that the <code>prefixScan</code> and <code>suffixScan</code> methods given in this post do essentially the same job as in <a href="http://conal.net/blog/posts/deriving-parallel-tree-scans/" title="blog post"><em>Deriving parallel tree scans</em></a>, when the binary tree type is deconstructed into functor combinators. A future post will show this connection.</li>
<li>Switch from standard (right-folded) trees to left-folded trees (in the sense of <a href="http://conal.net/blog/posts/a-trie-for-length-typed-vectors/" title="blog post"><em>A trie for length-typed vectors</em></a> and <a href="http://conal.net/blog/posts/from-tries-to-trees/" title="blog post"><em>From tries to trees</em></a>), which reduces the running time from <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mo>&#920;</mo><mspace width="0.167em"></mspace><mo stretchy="false">(</mo><mi>n</mi><mspace width="0.167em"></mspace><mi>log</mi><mspace width="0.167em"></mspace><mi>n</mi><mo stretchy="false">)</mo></mrow></math> to <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mo>&#920;</mo><mspace width="0.167em"></mspace><mi>n</mi></mrow></math>.</li>
<li>Scanning in place, i.e., destructively replacing the values in the input structure rather than allocating a new structure.</li>
</ul>
<p><a href="http://conal.net/blog/?flattrss_redirect&amp;id=411&amp;md5=9870e39e2e5552b7c42709138945e306"><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/composable-parallel-scanning/feed</wfw:commentRss>
		<slash:comments>5</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%2Fcomposable-parallel-scanning&amp;language=en_GB&amp;category=text&amp;title=Composable+parallel+scanning&amp;description=The+post+Deriving+list+scans+gave+a+simple+specification+of+the+list-scanning+functions+scanl+and+scanr%2C+and+then+transformed+those+specifications+into+the+standard+optimized+implementations.+Next%2C+the+post+Deriving...&amp;tags=functor%2Cscan%2Cblog" type="text/html" />
	</item>
		<item>
		<title>Fixing lists</title>
		<link>http://conal.net/blog/posts/fixing-lists</link>
		<comments>http://conal.net/blog/posts/fixing-lists#comments</comments>
		<pubDate>Sun, 30 Jan 2011 18:14:30 +0000</pubDate>
		<dc:creator><![CDATA[Conal]]></dc:creator>
				<category><![CDATA[Functional programming]]></category>
		<category><![CDATA[applicative functor]]></category>
		<category><![CDATA[functor]]></category>
		<category><![CDATA[number]]></category>
		<category><![CDATA[trie]]></category>
		<category><![CDATA[vector]]></category>

		<guid isPermaLink="false">http://conal.net/blog/?p=284</guid>
		<description><![CDATA[In the post Memoizing polymorphic functions via unmemoization, I toyed with the idea of lists as tries. I don&#8217;t think [a] is a trie, simply because [a] is a sum type (being either nil or a cons), while tries are built out of the identity, product, and composition functors. In contrast, Stream is a trie, [&#8230;]]]></description>
				<content:encoded><![CDATA[<!-- teaser -->

<p
>In the post <a href="http://conal.net/blog/posts/memoizing-polymorphic-functions-via-unmemoization/" title="blog post"
  ><em
    >Memoizing polymorphic functions via unmemoization</em
    ></a
  >, I toyed with the idea of lists as tries. I don&#8217;t think <code
  >[a]</code
  > is a trie, simply because <code
  >[a]</code
  > is a <em
  >sum</em
  > type (being either nil or a cons), while tries are built out of the identity, product, and composition functors. In contrast, <code
  >Stream</code
  > <em
  >is</em
  > a trie, being built solely with the identity and product functors. Moreover, <code
  >Stream</code
  > is not just any old trie, it is the trie that corresponds to Peano (unary natural) numbers, i.e., <code
  >Stream a &#8773; N &#8594; a</code
  >, where</p
>

<pre class="sourceCode haskell"
><code
  ><span class="kw"
    >data</span
    > <span class="dt"
    >N</span
    > <span class="fu"
    >=</span
    > <span class="dt"
    >Zero</span
    > <span class="fu"
    >|</span
    > <span class="dt"
    >Succ</span
    > <span class="dt"
    >N</span
    ><br
     /><br
     /><span class="kw"
    >data</span
    > <span class="dt"
    >Stream</span
    > a <span class="fu"
    >=</span
    > <span class="dt"
    >Cons</span
    > a (<span class="dt"
    >Stream</span
    > a)<br
     /></code
  ></pre
>

<p
>If we didn't already know the <code
  >Stream</code
  > type, we would derive it systematically from <code
  >N</code
  >, using standard isomorphisms.</p
>

<p
><code
  >Stream</code
  > is a trie (over unary numbers), thanks to it having no choice points, i.e., no sums in its construction. However, streams are infinite-only, which is not always what we want. In contrast, lists can be finite, but are not a trie in any sense I understand. In this post, I look at how to <em
  >fix</em
  > lists, so they can be finite and yet be a trie, thanks to having no choice points (sums)?</p
>

<p
>You can find the code for this post and the <a href="http://conal.net/blog/posts/type-bounded-numbers/" title="blog post"
  >previous one</a
  > in a <a href="https://github.com/conal/numbers-vectors-trees/" title="github repository"
  >code repository</a
  >.</p
>

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

<ul
><li
  >2011-01-30: Added spoilers warning.</li
  ><li
  >2011-01-30: Pointer to <a href="https://github.com/conal/numbers-vectors-trees/" title="github repository"
    >code repository</a
    >.</li
  ></ul
>

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

<div id="fixing-lists"
><h3
  >Fixing lists</h3
  ><p
  >Is there a type of finite lists without choice points (sums)? Yes. There are lots of them. One for each length. Instead of having a single type of lists, have an infinite family of types of <span class="math"
    ><em
      >n</em
      ></span
    >-element lists, one type for each <span class="math"
    ><em
      >n</em
      ></span
    >.</p
  ><p
  >In other words, to fix the problem with lists (trie-unfriendliness), split up the usual list type into subtypes (so to speak), each of which has a fixed length.</p
  ><p
  >I realize I'm changing the question to a simpler one. I hope you'll forgive me and hang in to see where this ride goes.</p
  ><p
  >As a first try, we might use tuples as our fixed-length lists:</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >type</span
      > <span class="dt"
      >L0</span
      > a <span class="fu"
      >=</span
      > ()<br
       /><span class="kw"
      >type</span
      > <span class="dt"
      >L1</span
      > a <span class="fu"
      >=</span
      > (a)<br
       /><span class="kw"
      >type</span
      > <span class="dt"
      >L2</span
      > a <span class="fu"
      >=</span
      > (a,a)<br
       /><span class="kw"
      >type</span
      > <span class="dt"
      >L3</span
      > a <span class="fu"
      >=</span
      > (a,a,a)<br
       />&#8943;<br
       /></code
    ></pre
  ><p
  >However, we can only write down finitely many such types, and I don't know how we could write any definitions that are polymorphic over <em
    >length</em
    >.</p
  ><p
  >What can &quot;polymorphic over length&quot; mean in a setting like Haskell, where polymorphism is over <em
    >types</em
    > rather than <em
    >values</em
    >. Can we express numbers (for lengths, etc) as types? Yes, as in the previous post, <a href="http://conal.net/blog/posts/type-bounded-numbers/" title="blog post"
    ><em
      >Type-bounded numbers</em
      ></a
    >, using a common encoding:</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >data</span
      > <span class="dt"
      >Z</span
      >    <span class="co"
      >-- zero</span
      ><br
       /><span class="kw"
      >data</span
      > <span class="dt"
      >S</span
      > n  <span class="co"
      >-- successor</span
      ><br
       /></code
    ></pre
  ><p
  >Given these type-level numbers, we can define a data type <code
    >Vec n a</code
    >, containing only vectors (fixed lists) of length <code
    >n</code
    > and elements of type <code
    >a</code
    >. Such vectors can be built up as either the zero-length vector, or by adding an element to an vector of length <span class="math"
    ><em
      >n</em
      ></span
    > to get a vector of length <span class="math"
    ><em
      >n</em
      > + 1</span
    >. I don't know how to define this type as a regular algebraic data type, but it's easy as a <em
    >generalized</em
    > algebraic data type (<a href="http://en.wikibooks.org/wiki/Haskell/GADT" title="Haskell Wikibook page"
    >GADT</a
    >):</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >infixr</span
      > <span class="dv"
      >5</span
      > <span class="fu"
      >:&lt;</span
      ><br
       /><br
       /><span class="kw"
      >data</span
      > <span class="dt"
      >Vec</span
      > <span class="dv"
      >&#8759;</span
      > <span class="fu"
      >*</span
      > &#8594; <span class="fu"
      >*</span
      > &#8594; <span class="fu"
      >*</span
      > <span class="kw"
      >where</span
      ><br
       />  <span class="dt"
      >ZVec</span
      > <span class="dv"
      >&#8759;</span
      >                <span class="dt"
      >Vec</span
      > <span class="dt"
      >Z</span
      >     a<br
       />  (<span class="fu"
      >:&lt;</span
      >) <span class="dv"
      >&#8759;</span
      > a &#8594; <span class="dt"
      >Vec</span
      > n a &#8594; <span class="dt"
      >Vec</span
      > (<span class="dt"
      >S</span
      > n) a<br
       /></code
    ></pre
  ><p
  >For example,</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="fu"
      >*</span
      ><span class="dt"
      >Vec</span
      ><span class="fu"
      >&gt;</span
      > <span class="fu"
      >:</span
      >ty <span class="ch"
      >'z'</span
      > <span class="fu"
      >:&lt;</span
      > <span class="ch"
      >'o'</span
      > <span class="fu"
      >:&lt;</span
      > <span class="ch"
      >'m'</span
      > <span class="fu"
      >:&lt;</span
      > <span class="ch"
      >'g'</span
      > <span class="fu"
      >:&lt;</span
      > <span class="dt"
      >ZVec</span
      ><br
       /><span class="ch"
      >'z'</span
      > <span class="fu"
      >:&lt;</span
      > <span class="ch"
      >'o'</span
      > <span class="fu"
      >:&lt;</span
      > <span class="ch"
      >'m'</span
      > <span class="fu"
      >:&lt;</span
      > <span class="ch"
      >'g'</span
      > <span class="fu"
      >:&lt;</span
      > <span class="dt"
      >ZVec</span
      > <span class="dv"
      >&#8759;</span
      > <span class="dt"
      >Vec</span
      > (<span class="dt"
      >S</span
      > (<span class="dt"
      >S</span
      > (<span class="dt"
      >S</span
      > (<span class="dt"
      >S</span
      > <span class="dt"
      >Z</span
      >)))) <span class="dt"
      >Char</span
      ><br
       /></code
    ></pre
  ><p
  >As desired, <code
    >Vec</code
    > is length-typed, covers all (finite) lengths, and allows definition of length-polymorphic functions. For instance, it's easy to map functions over vectors:</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >instance</span
      > <span class="kw"
      >Functor</span
      > (<span class="dt"
      >Vec</span
      > n) <span class="kw"
      >where</span
      ><br
       />  <span class="fu"
      >fmap</span
      > _ <span class="dt"
      >ZVec</span
      >     <span class="fu"
      >=</span
      > <span class="dt"
      >ZVec</span
      ><br
       />  <span class="fu"
      >fmap</span
      > f (a <span class="fu"
      >:&lt;</span
      > u) <span class="fu"
      >=</span
      > f a <span class="fu"
      >:&lt;</span
      > <span class="fu"
      >fmap</span
      > f u<br
       /></code
    ></pre
  ><p
  >The type of <code
    >fmap</code
    > here is <code
    >(a &#8594; b) &#8594; Vec n a &#8594; Vec n b</code
    >.</p
  ><p
  >Folding over vectors is also straightforward:</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >instance</span
      > <span class="dt"
      >Foldable</span
      > (<span class="dt"
      >Vec</span
      > n) <span class="kw"
      >where</span
      ><br
       />  <span class="fu"
      >foldr</span
      > _ b <span class="dt"
      >ZVec</span
      >      <span class="fu"
      >=</span
      > b<br
       />  <span class="fu"
      >foldr</span
      > h b (a <span class="fu"
      >:&lt;</span
      > as) <span class="fu"
      >=</span
      > a <span class="ot"
      >`h`</span
      > <span class="fu"
      >foldr</span
      > h b as<br
       /></code
    ></pre
  ><p
  >Is <code
    >Vec n</code
    > an applicative functor as well?</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >instance</span
      > <span class="dt"
      >Applicative</span
      > (<span class="dt"
      >Vec</span
      > n) <span class="kw"
      >where</span
      ><br
       />  &#8943;<br
       /></code
    ></pre
  ><p
  >We would need</p
  ><pre class="sourceCode haskell"
  ><code
    >pure <span class="dv"
      >&#8759;</span
      > a &#8594; <span class="dt"
      >Vec</span
      > n a<br
       />(&#8859;)  <span class="dv"
      >&#8759;</span
      > <span class="dt"
      >Vec</span
      > n (a &#8594; b) &#8594; <span class="dt"
      >Vec</span
      > n a &#8594; <span class="dt"
      >Vec</span
      > n b<br
       /></code
    ></pre
  ><p
  >The <code
    >(&#8859;)</code
    > method can be defined similarly to <code
    >fmap</code
    >:</p
  ><pre class="sourceCode haskell"
  ><code
    >  <span class="dt"
      >ZVec</span
      >      &#8859; <span class="dt"
      >ZVec</span
      >      <span class="fu"
      >=</span
      > <span class="dt"
      >ZVec</span
      ><br
       />  (f <span class="fu"
      >:&lt;</span
      > fs) &#8859; (x <span class="fu"
      >:&lt;</span
      > xs) <span class="fu"
      >=</span
      > f x <span class="fu"
      >:&lt;</span
      > (fs &#8859; xs)<br
       /></code
    ></pre
  ><p
  >Unlike <code
    >fmap</code
    > and <code
    >(&#8859;)</code
    >, <code
    >pure</code
    > doesn't have a vector structure to crawl over. It must create just the right structure anyway. You might enjoy thinking about how to solve this puzzle, which I'll tackle in my next post. (Warning: spoilers in the comments below.)</p
  ></div
>
<p><a href="http://conal.net/blog/?flattrss_redirect&amp;id=284&amp;md5=8a876a1ca74b5e365684d743df52c81c"><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/fixing-lists/feed</wfw:commentRss>
		<slash:comments>10</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%2Ffixing-lists&amp;language=en_GB&amp;category=text&amp;title=Fixing+lists&amp;description=In+the+post+Memoizing+polymorphic+functions+via+unmemoization%2C+I+toyed+with+the+idea+of+lists+as+tries.+I+don%26%238217%3Bt+think+%5Ba%5D+is+a+trie%2C+simply+because+%5Ba%5D+is+a+sum...&amp;tags=applicative+functor%2Cfunctor%2Cnumber%2Ctrie%2Cvector%2Cblog" type="text/html" />
	</item>
		<item>
		<title>Fixing broken isomorphisms &#8212; details for non-strict memoization, part 2</title>
		<link>http://conal.net/blog/posts/fixing-broken-isomorphisms-details-for-non-strict-memoization-part-2</link>
		<comments>http://conal.net/blog/posts/fixing-broken-isomorphisms-details-for-non-strict-memoization-part-2#comments</comments>
		<pubDate>Wed, 22 Sep 2010 23:02:26 +0000</pubDate>
		<dc:creator><![CDATA[Conal]]></dc:creator>
				<category><![CDATA[Functional programming]]></category>
		<category><![CDATA[functor]]></category>
		<category><![CDATA[memoization]]></category>
		<category><![CDATA[trie]]></category>
		<category><![CDATA[unamb]]></category>

		<guid isPermaLink="false">http://conal.net/blog/?p=198</guid>
		<description><![CDATA[The post Details for non-strict memoization, part 1 works out a systematic way of doing non-strict memoization, i.e., correct memoization of non-strict (and more broadly, non-hyper-strict) functions. As I mentioned at the end, there was an awkward aspect, which is that the purported &#8220;isomorphisms&#8221; used for regular types are not quite isomorphisms. For instance, functions [&#8230;]]]></description>
				<content:encoded><![CDATA[<!-- 

Title: Fixing broken isomorphisms - details for non-strict memoization, part 2

Tags: memoization, functor, trie, unamb

URL: http://conal.net/blog/posts/fixing-broken-isomorphisms-details-for-non-strict-memoization-part-2/

-->

<!-- references -->

<!-- teaser -->

<!--
**Edits**:

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

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

<p>The post <em><a href="http://conal.net/blog/posts/details-for-nonstrict-memoization-part-1/" title="blog post">Details for non-strict memoization, part 1</a></em> works out a systematic way of doing <em>non-strict</em> memoization, i.e., correct memoization of non-strict (and more broadly, non-hyper-strict) functions.
As I mentioned at the end, there was an awkward aspect, which is that the purported &#8220;isomorphisms&#8221; used for regular types are not quite isomorphisms.</p>

<p>For instance, functions from triples are memoized by converting to and from nested pairs:</p>

<pre><code>untriple ∷ (a,b,c) -&gt; ((a,b),c)
untriple (a,b,c) = ((a,b),c)

triple ∷ ((a,b),c) -&gt; (a,b,c)
triple ((a,b),c) = (a,b,c)
</code></pre>

<p>Then <code>untriple</code> and <code>triple</code> form an embedding/projection pair, i.e.,</p>

<pre><code>triple ∘ untriple ≡ id
untriple ∘ triple ⊑ id
</code></pre>

<p>The reason for the inequality is that the nested-pair form permits <code>(⊥,c)</code>, which does not correspond to any triple.</p>

<pre><code>untriple (triple (⊥,c)) ≡ untriple ⊥ ≡ ⊥
</code></pre>

<p>Can we patch this problem by simply using an irrefutable (lazy) pattern in the definition of <code>triple</code>, i.e., <code>triple (~(a,b),c) = (a,b,c)</code>?
Let&#8217;s try:</p>

<pre><code>untriple (triple (⊥,c)) ≡ untriple (⊥,⊥,c) ≡ ((⊥,⊥),c)
</code></pre>

<p>So isomorphism fails and so does even the embedding/projection property.</p>

<p>Similarly, to deal with regular algebraic data types, I used a class that describes regular data types as repeated applications of a single, associated <em>pattern functor</em> (following <em><a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.142.4778" title="Paper by Thomas Noort, Alexey Rodriguez, Stefan Holdermans, Johan Jeuring, Bastiaan Heeren">A Lightweight Approach to Datatype-Generic Rewriting</a></em>):</p>

<pre><code>class Functor (PF t) ⇒ Regular t where
  type PF t ∷ * → *
  unwrap ∷ t → PF t t
  wrap   ∷ PF t t → t
</code></pre>

<p>Here <code>unwrap</code> converts a value into its pattern functor form, and <code>wrap</code> converts back.
For example, here is the <code>Regular</code> instance I had used for lists:</p>

<pre><code>instance Regular [a] where
  type PF [a] = Const () :+: Const a :*: Id

  unwrap []     = InL (Const ())
  unwrap (a:as) = InR (Const a :*: Id as)

  wrap (InL (Const ()))          = []
  wrap (InR (Const a :*: Id as)) = a:as
</code></pre>

<p>Again, we have an embedding/projection pair, rather than a genuine isomorphism:</p>

<pre><code>wrap ∘ unwrap ≡ id
unwrap ∘ wrap ⊑ id
</code></pre>

<p>The inequality comes from ⊥ values occurring in <code>PF [a] [a]</code> at type <code>Const () [a]</code>, <code>()</code>,  <code>(Const a :*: Id) [a]</code>, <code>Const a [a]</code>, or <code>Id [a]</code>.</p>

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

<h3>Why care?</h3>

<p>What harm results from the lack of genuine isomorphism?
For hyper-strict functions, as usually handled (correctly) in memoization, I don&#8217;t think there is any harm.
For correct memoization of non-hyper-strict functions, however, the superfluous points of undefinedness lead to larger memo tries and wasted effort.
For instance, a function from triples goes through some massaging on the way to being memoized:</p>

<pre><code>λ (a,b,c) → ⋯
⇓
λ ((a,b),c) → ⋯
⇓
λ (a,b) → λ c → ⋯
</code></pre>

<p>For hyper-strict memoization, the next step transforms to <code>λ a → λ b → λ c → ⋯</code>.
For non-strict memoization, however, we first stash away the value of the function applied to <code>⊥ ∷ (a,b)</code>, which will always be ⊥ in this context.</p>

<h3>Strict products and sums</h3>

<p>To eliminate the definedness discrepancy and regain isomorphism, we might make all non-strictness explicit via unlifted product &amp; sums, and explicit lifting.</p>

<pre><code>-- | Add a bottom to a type
data Lift a = Lift { unLift ∷ a } deriving Functor

infixl 6 :+:!
infixl 7 :*:!

-- | Strict pair
data a :*! b = !a :*! !b

-- | Strict sum
data a :+! b = Left' !a | Right' !b
</code></pre>

<p>Note that the <code>Id</code> and <code>Const a</code> functors used in canonical representations are already strict, as they&#8217;re defined via <code>newtype</code>.</p>

<p>With these new tools, we can decompose isomorphically.
For instance,</p>

<pre><code>(a,b,c) ≅ Lift a :*! Lift b :*! Lift c
</code></pre>

<p>with the isomorphism given by</p>

<pre><code>untriple' ∷ (a,b,c) -&gt; Lift a :*! Lift b :*! Lift c
untriple' (a,b,c) = Lift a :*! Lift b :*! Lift c

triple' ∷ Lift a :*! Lift b :*! Lift c -&gt; (a,b,c)
triple' (Lift a :*! Lift b :*! Lift c) = (a,b,c)
</code></pre>

<p>For regular types, we&#8217;ll also want variations as functor combinators:</p>

<pre><code>-- | Strict product functor
data (f :*:! g) a = !(f a) :*:! !(g a) deriving Functor

-- | Strict sum functor
data (f :+:! g) a = InL' !(f a) | InR' !(g a) deriving Functor
</code></pre>

<p>Then change the <code>Regular</code> instance on lists to the following:</p>

<pre><code>instance Regular [a] where
  type PF [a] = Const () :+:! Const (Lift a) :*:! Lift

  unwrap []     = InL' (Const ())
  unwrap (a:as) = InR' (Const (Lift a) :*:! Lift as)

  wrap (InL' (Const ()))                    = []
  wrap (InR' (Const (Lift a) :*:! Lift as)) = a:as
</code></pre>

<p>I suppose it would be fairly straightforward to derive such instances for algebraic data types automatically via Template Haskell.</p>

<h3>Tries for non-strict memoization</h3>

<p>As in <em><a href="http://conal.net/blog/posts/details-for-nonstrict-memoization-part-1/" title="blog post">part 1</a></em>, represent a non-strict memo trie for a function <code>f ∷ k -&gt; v</code> as a value for <code>f ⊥</code> and a <em>strict</em> (but not hyper-strict) memo trie for <code>f</code>:</p>

<pre><code>type k :→: v = Trie v (k :→ v)
</code></pre>

<p>For non-strict sum domains, the strict memo trie was a pair of non-strict tries:</p>

<pre><code>instance (HasTrie a, HasTrie b) ⇒ HasTrie (Either a b) where
  type STrie (Either a b) = Trie a :*: Trie b
  sTrie   f           = trie (f ∘ Left) :*: trie (f ∘ Right)
  sUntrie (ta :*: tb) = untrie ta `either` untrie tb
</code></pre>

<p>For non-strict product, the strict trie was a composition of non-strict tries:</p>

<pre><code>instance (HasTrie a, HasTrie b) =&gt; HasTrie (a , b) where
  type STrie (a , b) = Trie a :. Trie b
  sTrie   f = O (fmap trie (trie (curry f)))
  sUntrie (O tt) = uncurry (untrie (fmap untrie tt))
</code></pre>

<p>What about <em>strict</em> sum and product domains?
Since strict sums &amp; products cannot contain ⊥ as their immediate components, we can omit the values corresponding to ⊥ for those components.
That is, we can use pairs and compositions of <em>strict</em> tries instead.</p>

<pre><code>instance (HasTrie a, HasTrie b) =&gt; HasTrie (a :+! b) where
  type STrie (a :+! b) = STrie a :*: STrie b
  sTrie   f           = sTrie (f . Left') :*: sTrie (f . Right')
  sUntrie (ta :*: tb) = sUntrie ta `either'` sUntrie tb

instance (HasTrie a, HasTrie b) =&gt; HasTrie (a :*! b) where
  type STrie (a :*! b) = STrie a :. STrie b
  sTrie   f      = O (fmap sTrie (sTrie (curry' f)))
  sUntrie (O tt) = uncurry' (sUntrie (fmap sUntrie tt))
</code></pre>

<p>I&#8217;ve also substituted versions of <code>curry</code> and <code>uncurry</code> for strict products and <code>either</code> for strict sums:</p>

<pre><code>curry' ∷ (a :*! b -&gt; c) -&gt; (a -&gt; b -&gt; c)
curry' f a b = f (a :*! b)

uncurry' ∷ (a -&gt; b -&gt; c) -&gt; ((a :*! b) -&gt; c)
uncurry' f (a :*! b) = f a b

either' ∷ (a -&gt; c) -&gt; (b -&gt; c) -&gt; (a :+! b -&gt; c)
either' f _ (Left'  a) = f a
either' _ g (Right' b) = g b
</code></pre>

<p>We&#8217;ll also need to handle the lifting functor.
The type <code>Lift a</code> has an additional bottom.
A strict function or trie over <code>Lift a</code> is only strict in the lower (outer) one.
So a strict trie over <code>Lift a</code> is simply a non-strict trie over <code>a</code>.</p>

<pre><code>instance HasTrie a =&gt; HasTrie (Lift a) where
  type STrie (Lift a) = Trie a
  sTrie   f = trie (f . Lift)
  sUntrie t = untrie t . unLift
</code></pre>

<p>Notice that this instance puts back exactly what was lost from memo tries when going from non-strict products and sums to strict products and sums.
The reason for this relationship is explained in the following simple isomorphisms:</p>

<pre><code>(a,b)      ≅ Lift a :*! Lift b
Either a b ≅ Lift a :+! Lift b
</code></pre>

<p>Then isomorphisms can then be used to implement memoize over non-strict products and sums via memoization over strict products and sums.</p>

<h2>Higher-order memoization</h2>

<p>The post <em><a href="http://conal.net/blog/posts/memoizing-higher-order-functions/" title="blog post">Memoizing higher-order functions</a></em> suggested a simple way to memoize functions over function-valued domains by using (as always) type isomorphisms.
The isomorphism used is between functions and memo tries.</p>

<p>I gave one example in that post</p>

<pre><code>ft1 ∷ (Bool → a) → [a]
ft1 f = [f False, f True]
</code></pre>

<p>In retrospect, this example was a lousy choice, as it hides an important problem.
The <code>Bool</code> type is <em>finite</em>, and so the corresponding trie type has only finitely large elements.
For that reason, higher-order memoization can get away with the usual hyper-strict memoization.</p>

<p>If instead, we try memoizing a function of type <code>(a → b) → c</code>, where the type <code>a</code> has infinitely many <code>elements</code> (e.g., <code>Integer</code> or <code>[Bool]</code>), then we&#8217;ll have to memoize over the domain <code>a :→: b</code> (memo tries from <code>a</code> to <code>b</code>), which includes infinite elements.
In that case, hyper-strict memoization blows up, so we&#8217;ll want to use non-strict memoization instead.</p>

<p>As mentioned above, the type of non-strict tries contains a value and a strict trie:</p>

<pre><code>type k :→: v = Trie v (k :→ v)
</code></pre>

<p>I thought I&#8217;d memoize by mapping to &amp; from the isomorphic pair type <code>(v, k :→ v)</code>.
However, now I&#8217;m not satisfied with this mapping.
A non-strict trie from <code>k</code> to <code>v</code> is not just <em>any</em> such pair of <code>v</code> and <code>k :→ v</code>.
Monotonicity requires that the single <code>v</code> value (for ⊥) be a lower bound (information-wise) of every <code>v</code> in the trie.
Ignoring this constraint would lead to a trie in which most of the entries do not correspond to any non-strict memo trie.</p>

<p><em>Puzzle:</em> Can this constraint be captured as a <em>static</em> type in modern Haskell&#8217;s (GHC&#8217;s) type system (i.e., without resorting to general dependent typing)?
I don&#8217;t know the answer.</p>

<h2>Memoizing abstract types</h2>

<p>This problem is more wide-spread still.
Whenever there are constraints on a representation beyond what is expressed directly and statically in the representation type, we will have this same sort of isomorphism puzzle.
Can we capture the constraint as a Haskell type?
When we cannot, what do we do?</p>

<p>If we didn&#8217;t care about efficiency, I think we could ignore the issue, and everything else in this blog post, and accept making memo tries that are much larger than necessary.
Although laziness will keep from filling in range values for unaccessed domain values, I worry that there will be quite a lot time and space wasted navigating past large portions of unusable trie structure.</p>
<p><a href="http://conal.net/blog/?flattrss_redirect&amp;id=198&amp;md5=c2a469f4293d7f7d52b9fe50951c2f43"><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/fixing-broken-isomorphisms-details-for-non-strict-memoization-part-2/feed</wfw:commentRss>
		<slash:comments>0</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%2Ffixing-broken-isomorphisms-details-for-non-strict-memoization-part-2&amp;language=en_GB&amp;category=text&amp;title=Fixing+broken+isomorphisms+%26%238212%3B+details+for+non-strict+memoization%2C+part+2&amp;description=The+post+Details+for+non-strict+memoization%2C+part+1+works+out+a+systematic+way+of+doing+non-strict+memoization%2C+i.e.%2C+correct+memoization+of+non-strict+%28and+more+broadly%2C+non-hyper-strict%29+functions.+As+I+mentioned...&amp;tags=functor%2Cmemoization%2Ctrie%2Cunamb%2Cblog" type="text/html" />
	</item>
		<item>
		<title>Another angle on zippers</title>
		<link>http://conal.net/blog/posts/another-angle-on-zippers</link>
		<comments>http://conal.net/blog/posts/another-angle-on-zippers#comments</comments>
		<pubDate>Thu, 29 Jul 2010 17:06:10 +0000</pubDate>
		<dc:creator><![CDATA[Conal]]></dc:creator>
				<category><![CDATA[Functional programming]]></category>
		<category><![CDATA[derivative]]></category>
		<category><![CDATA[functor]]></category>
		<category><![CDATA[zipper]]></category>

		<guid isPermaLink="false">http://conal.net/blog/?p=154</guid>
		<description><![CDATA[The zipper is an efficient and elegant data structure for purely functional editing of tree-like data structures, first published by Gérard Huet. Zippers maintain a location of focus in a tree and support navigation operations (up, down, left, right) and editing (replace current focus). The original zipper type and operations are customized for a single [&#8230;]]]></description>
				<content:encoded><![CDATA[<!-- 

Title: Another angle on zippers

Tags: derivative, functor, zipper

URL: http://conal.net/blog/posts/another-angle-on-zippers/

-->

<!-- references -->

<!-- teaser -->

<p>The zipper is an efficient and elegant data structure for purely functional editing of tree-like data structures, <a href="http://www.st.cs.uni-saarland.de/edu/seminare/2005/advanced-fp/docs/huet-zipper.pdf" title="paper by Gérard Huet">first published by Gérard Huet</a>.
Zippers maintain a location of focus in a tree and support navigation operations (up, down, left, right) and editing (replace current focus).</p>

<p>The original zipper type and operations are customized for a single type, but it&#8217;s not hard to see how to adapt to other tree-like types, and hence to regular data types.
There have been many follow-up papers to <em><a href="http://www.st.cs.uni-saarland.de/edu/seminare/2005/advanced-fp/docs/huet-zipper.pdf" title="paper by Gérard Huet">The Zipper</a></em>, including a polytypic version in the paper <em><a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.1.6342" title="paper by Ralf Hinze, Johan Jeuring, and Andres Löh">Type-indexed data types</a></em>.</p>

<p>All of the zipper adaptations and generalizations I&#8217;ve seen so far maintain the original navigation interface.
In this post, I propose an alternative interface that appears to significantly simplify matters.
There are only two navigation functions instead of four, and each of the two is specified and implemented via a fairly simple one-liner.</p>

<p>I haven&#8217;t used this new zipper formulation in an application yet, so I do not know whether some usefulness has been lost in simplifying the interface.</p>

<p>The code in this blog post is taken from the Haskell library <a href="http://hackage.haskell.org/package/functor-combo" title="Hackage entry: functor-combo">functor-combo</a> and completes the <code>Holey</code> type class introduced in <em><a href="http://conal.net/blog/posts/differentiation-of-higher-order-types/" title="blog post">Differentiation of higher-order types</a></em>.</p>

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

<ul>
<li>2010-07-29: Removed some stray <code>Just</code> applications in <code>up</code> definitions.  (Thanks, illissius.)</li>
<li>2010-07-29: Augmented my complicated definition of <code>tweak2</code> with a much simpler version from Sjoerd Visscher.</li>
<li>2010-07-29: Replaced <code>fmap (first (:ds'))</code> with <code>(fmap.first) (:ds')</code> in <code>down</code> definitions.  (Thanks, Sjoerd.)</li>
</ul>

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

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

<h3>Extraction</h3>

<p>The post <em><a href="http://conal.net/blog/posts/differentiation-of-higher-order-types/" title="blog post">Differentiation of higher-order types</a></em> gave part of a type class for one-hole contexts (functor derivatives) and the filling of those contexts:</p>

<pre><code>class Functor f ⇒ Holey f where
  type Der f :: * → *
  fillC :: Der f a → a → f a
</code></pre>

<p>The arguments of <code>fillC</code> correspond roughly to the components of what Gérard Huet called a &#8220;location&#8221;, namely context and something to fill the context:</p>

<pre><code>type Loc f a = (Der f a, a)
</code></pre>

<p>So an alternative hole-filling interface is</p>

<pre><code>fill :: Holey f ⇒ Loc f a → f a
fill = uncurry fillC
</code></pre>

<p>Now consider a reverse operation, a kind of <em>extraction</em>:</p>

<pre><code>guess1 :: f a → Loc f a
</code></pre>

<p>There&#8217;s an awkward problem here.
What if <code>f a</code> has more than one possible hole, or has no hole at all?
If more than one, then which do we pick?
Perhaps the left-most.
If none, then we might want to have a failure representation, e.g.,</p>

<pre><code>guess2 :: f a → Maybe (Loc f a)
</code></pre>

<p>To handle the more-than-one possibility, we could add another method for traversing the various extractions, like the <code>go_right</code> operation in <em><a href="http://www.st.cs.uni-saarland.de/edu/seminare/2005/advanced-fp/docs/huet-zipper.pdf" title="paper by Gérard Huet">The Zipper</a></em>, section 2.2.
I don&#8217;t know what changes we&#8217;d have to make to the <code>Loc</code> type.</p>

<p>We could instead use a list of possible extractions.</p>

<pre><code>guess3 :: f a → [Loc f a]
</code></pre>

<p>Why a <em>list</em>?
I guess because it&#8217;s in our habitual functional toolbox, and it covers any number of alternative extracted locations.
On the other hand, our toolbox is growing, and sometimes list isn&#8217;t the best functor for the job.
For instance, we might use a finger tree, which has better performance for some sequence operations.</p>

<p>Or we could a functor closer at hand, namely <code>f</code> itself.</p>

<pre><code>class Functor f ⇒ Holey f where
  type Der f :: * → *
  fillC   :: Der f a → a → f a
  extract :: f a → f (Loc f a)
</code></pre>

<p>For instance, when <code>f ≡ []</code>, <code>extract</code> returns a list of extractions; and when <code>f ≡ Id :*: Id</code>, <code>extract</code> returns a pair of extractions.</p>

<h3>How to extract</h3>

<p>A constant functor has void derivative.
Extraction yields another constant structure, with the same data but a different type:</p>

<pre><code>instance Holey (Const x) where
  type Der (Const x) = Void
  fillC = voidF
  extract (Const x) = Const x
</code></pre>

<p>The identity functor has exactly one opportunity for a hole, leaving no information behind:</p>

<pre><code>instance Holey Id where
  type Der Id = Unit
  fillC (Const ()) = Id
  extract (Id a) = Id (Const (), a)
</code></pre>

<p>The definitions of <code>Der</code> and <code>fillC</code> above and below are lifted directly from <em><a href="http://conal.net/blog/posts/differentiation-of-higher-order-types/" title="blog post">Differentiation of higher-order types</a></em>.</p>

<p>For sums, there are two cases: <code>InL fa, InR ga :: (f :+: g) a</code>.
Starting with the first case:</p>

<pre><code>InL fa :: (f :+: g) a

fa :: f a

extract fa :: f (Loc f a)

           :: f (Der f a, a)

(fmap.first) InL (extract fa) :: f ((Der f :+: Der g) a, a)

                              :: f ((Der (f :+: g) a), a)
</code></pre>

<p>See <em><a href="http://conal.net/blog/posts/semantic-editor-combinators/" title="blog post">Semantic editor combinators</a></em> for an explanation of <code>(fmap.first)</code> friends.
Continuing, apply the definition of <code>Der</code> on sums:</p>

<pre><code>InL ((fmap.first) InL (extract fa)) :: (f :+: g) ((Der (f :+: g) a), a)

                                    :: (f :+: g) (Loc (f :+: g) a)
</code></pre>

<p>The two steps that introduce <code>g</code> are motivated by the required type of <code>extract</code>.
Similarly, for the second case:</p>

<pre><code>InR ((fmap.first) InR (extract ga)) :: (f :+: g) (Loc (f :+: g) a)
</code></pre>

<p>So,</p>

<pre><code>instance (Holey f, Holey g) ⇒ Holey (f :+: g) where
  type Der (f :+: g) = Der f :+: Der g
  fillC (InL df) = InL ∘ fillC df
  fillC (InR df) = InR ∘ fillC df
  extract (InL fa) = InL ((fmap.first) InL (extract fa))
  extract (InR ga) = InR ((fmap.first) InR (extract ga))
</code></pre>

<p>For products, recall the derivative type:</p>

<pre><code>  type Der (f :*: g) = Der f :*: g  :+:  f :*: Der g
</code></pre>

<p>To extract from a product, we extract from either component and then pair with the other component.
The form of an argument to <code>extract</code> is</p>

<pre><code>fa :*: ga :: (f :*: g) a
</code></pre>

<p>Again, start with the left part:</p>

<pre><code>fa :: f a

extract fa :: f (Loc f a)
           :: f (Der f a, a)

(fmap.first) (:*: ga) (extract fa) :: f ((Der f :*: g) a, a)

(fmap.first) (InL ∘ (:*: ga)) (extract fa)
  :: f (((Der f :*: g) :+: (f :*: Der g)) a, a)

  :: f ((Der (f :*: g)) a, a)
</code></pre>

<p>Similarly, for the second component,</p>

<pre><code>(fmap.first) (InR ∘ (fa :*:)) (extract ga)
  :: g ((Der (f :*: g)) a, a)
</code></pre>

<p>Combining the two extraction routes:</p>

<pre><code>(fmap.first) (InL ∘ (:*: ga)) (extract fa) :*:
(fmap.first) (InR ∘ (fa :*:)) (extract ga)
  :: (f :*: g) (Der (f :*: g) a, a)
</code></pre>

<p>So,</p>

<pre><code>instance (Holey f, Holey g) ⇒ Holey (f :*: g) where
  type Der (f :*: g) = Der f :*: g  :+:  f :*: Der g
  fillC (InL (dfa :*:  ga)) = (:*: ga) ∘ fillC dfa
  fillC (InR ( fa :*: dga)) = (fa :*:) ∘ fillC dga
  extract (fa :*: ga) = 
    (fmap.first) (InL ∘ (:*: ga)) (extract fa) :*:
    (fmap.first) (InR ∘ (fa :*:)) (extract ga)
</code></pre>

<p>Finally, the chain rule, for functor composition:</p>

<pre><code>type Der (g :. f) = Der g :. f  :*:  Der f
</code></pre>

<p>A value of type <code>(g :. f) a</code> has form <code>O gfa</code>, where <code>gfa :: g (f a)</code>.
To extract:</p>

<ul>
<li>form all <code>g</code>-extractions, yielding values of type <code>fa :: f a</code> and their contexts of type <code>Der g (f a)</code>;</li>
<li>form all <code>f</code>-extractions of each such <code>fa</code>, yielding values of type <code>a</code> and their contexts of type <code>Der f a</code>; and</li>
<li>reassemble these pieces into the shape determined by <code>Der (g :. f)</code>.</li>
</ul>

<p>Let&#8217;s go:</p>

<pre><code>gfa :: g (f a)

extract gfa :: g (Loc g (f a))

            :: g (Der g (f a), f a)

fmap (second extract) (extract gfa)
  :: g (Der g (f a), f (Loc f a))
</code></pre>

<p>Continuing, the following lemmas come in handy.</p>

<pre><code>tweak2 :: Functor f ⇒
          (dg (f a), f (df a, a)) → f (((dg :. f) :*: df) a, a)
tweak2 = (fmap.first) chainRule ∘ tweak1

tweak1 :: Functor f ⇒
          (dg (fa), f (dfa, a)) → f ((dg (fa), dfa), a)
tweak1 = fmap lassoc ∘ squishP

squishP :: Functor f ⇒ (a, f b) → f (a,b)
squishP (a,fb) = fmap (a,) fb

chainRule :: (dg (f a), df a) → ((dg :. f) :*: df) a
chainRule (dgfa, dfa) = O dgfa :*: dfa

lassoc :: (p,(q,r)) → ((p,q),r)
lassoc    (p,(q,r)) =  ((p,q),r)
</code></pre>

<p><em>Edit:</em> Sjoerd Visscher found a much simpler form to replace the previous group of definitions:</p>

<pre><code>tweak2 (dgfa, fl) = (fmap.first) (O dgfa :*:) fl
</code></pre>

<p>More specifically,</p>

<pre><code>tweak2 :: Functor f =&gt; (Der g (f a), f (Loc f a))
                    -&gt; f (((Der g :. f) :*: Der f) a, a)
       :: Functor f =&gt; (Der g (f a), f (Loc f a))
                    -&gt; f (Der (g :. f) a, a)
       :: Functor f =&gt; (Der g (f a), f (Loc f a))
                    -&gt; f (Loc (g :. f) a)
</code></pre>

<p>This lemma gives just what we need to tweak the inner extraction:</p>

<pre><code>fmap (tweak2 ∘ second extract) (extract gfa) :: g (f (Loc (g :. f) a))
</code></pre>

<p>So</p>

<pre><code>extractGF :: (Holey f, Holey g) ⇒
             g (f a) → g (f (Loc (g :. f) a))
extractGF = fmap (tweak2 ∘ second extract) ∘ extract
</code></pre>

<p>and</p>

<pre><code>instance (Holey f, Holey g) ⇒ Holey (g :. f) where
  type Der (g :.  f) = Der g :. f  :*:  Der f
  fillC (O dgfa :*: dfa) = O ∘ fillC dgfa ∘ fillC dfa
  extract = inO extractGF
</code></pre>

<p>where <code>inO</code> is from <a href="http://hackage.haskell.org/packages/archive/TypeCompose/latest/doc/html/Control-Compose.html" title="module documentation">Control.Compose</a>, and is defined using the ideas from <em><a href="http://conal.net/blog/posts/prettier-functions-for-wrapping-and-wrapping/" title="blog post">Prettier functions for wrapping and wrapping</a></em> and the notational improvement from Matt Hellige&#8217;s <em><a href="http://matt.immute.net/content/pointless-fun" title="blog post by Matt Hellige">Pointless fun</a></em>.</p>

<pre><code>-- | Apply a unary function within the 'O' constructor.
inO :: (g (f a) → g' (f' a')) → ((g :. f) a → (g' :. f') a')
inO = unO ~&gt; O

infixr 1 ~&gt;
-- | Add pre- and post processing
(~&gt;) :: (a' → a) → (b → b') → ((a → b) → (a' → b'))
(f ~&gt; h) g = h ∘ g ∘ f
</code></pre>

<p>In case you&#8217;re wondering, these definitions did not come to me effortlessly.
I sweated through the derivation, guided always by my intuition and the necessary types, as determined by the shape of <code>Der (g :. f)</code>.
The type-checker helped me get from one step to the next.</p>

<p>I do a lot of type-directed derivations of this style while I program in Haskell, with the type-checker checking each step for me.
I&#8217;d love to have mechanized help in <em>creating</em> these derivations, not just <em>checking</em> them.</p>

<h3>Zippers</h3>

<p>How does the <code>Holey</code> class relate to zippers?
As in a few recent blog posts, let&#8217;s use the fact that regular data types are isomorphic to fixed-points of functors.</p>

<p>Functor fixed-points are like function fixed points</p>

<pre><code>fix f = f (fix f)

type Fix f = f (Fix f)
</code></pre>

<p>However, Haskell doesn&#8217;t support recursive type synonyms, so use a <code>newtype</code>:</p>

<pre><code>newtype Fix f = Fix { unFix :: f (Fix f) }
</code></pre>

<p>A context for a functor fixed-point is either empty, if we&#8217;re at the very top of an &#8220;<code>f</code>-tree&#8221;, or it&#8217;s an <code>f</code>-context for <code>f (Fix f)</code>, and a parent context:</p>

<pre><code>data Context f = TopC | Context (Der f (Fix f)) (Context f)  -- first try
</code></pre>

<p>Hm.
On the outside, <code>Context f</code> looks like a list, so let&#8217;s use a list instead:</p>

<pre><code>type Context f = [Der f (Fix f)]
</code></pre>

<p>The location type we used above is</p>

<pre><code>type Loc f a = (Der f a, a)
</code></pre>

<p>Similarly, define a type of zippers (also called &#8220;locations&#8221;) for functor fixed-points:</p>

<pre><code>type Zipper f = (Context f, Fix f)
</code></pre>

<p>This <code>Zipper</code> type corresponds to a zipper, and has operations <code>up</code> and <code>down</code>.
The <code>down</code> motion can yield multiple results.</p>

<pre><code>up   :: Holey f ⇒ Zipper f →    Zipper f

down :: Holey f ⇒ Zipper f → f (Zipper f)
</code></pre>

<p>Since <code>down</code> yields an <code>f</code>-collection of locations, we do not need sibling navigation functions (<code>left</code> &amp; <code>right</code>).</p>

<p>To move up in <code>Zipper</code>, strip off a derivative (one-hole functor context) and fill the hole with the current tree, leaving the other derivatives as the remaining fixed-point context.
Like so:</p>

<pre><code>up   :: Holey f ⇒ Zipper f →    Zipper f
up (d:ds', t) = (ds', Fix (fill (d,t)))
</code></pre>

<p>To see how the typing works out:</p>

<pre><code>(d:ds', t) :: Zipper f
(d:ds', t) :: (Context f, Fix f)

d:ds' :: [Der f (Fix f)]

t :: Fix f

d   ::  Der f (Fix f)
ds' :: [Der f (Fix f)]

fill :: Loc f b → f b
fill :: (Der f b, b) → f b
fill :: (Der f (Fix f), Fix f) → f (Fix f)

fill (d,t) :: f (Fix f)

Fix (fill (d,t)) :: Fix f

(ds', Fix (fill (d,t))) :: (Context f, Fix f)
                        :: Zipper f
</code></pre>

<p>Note that the <code>up</code> motion fails when at the top of a zipper (empty context).
If desired, we can also provide an unfailing version (really, a version with explictly typed failure):</p>

<pre><code>up' :: Holey f =&gt; Zipper f -&gt; Maybe (Zipper f)
up' ([]   , _) = Nothing
up' l          = Just (up l)
</code></pre>

<p>To move down in an <code>f</code>-tree <code>t</code>, form the extractions of <code>t</code>, each of which has a derivative and a sub-tree.
The derivative becomes part of an extended fixed-point context, and the sub-tree becomes the new sub-tree of focus.</p>

<pre><code>down :: Holey f ⇒ Zipper f → f (Zipper f)
down (ds', t) = (fmap.first) (:ds') (extract (unFix t)) (unFix t))
</code></pre>

<p>The typing (in case you&#8217;re curious):</p>

<pre><code>(ds',t) :: Zipper f
        :: (Context f, Fix f)
        :: ([Der f (Fix f)], Fix f)

ds' :: [Der f (Fix f)]
t :: Fix f
unFix t :: f (Fix f)

extract (unFix t) :: f (Der f (Fix f), Fix f)

(fmap.first) (:ds') (extract (unFix t))
  :: ([Der f (Fix f)], Fix f)
  :: (Context f, Fix f)
  :: LocFix f
</code></pre>

<h3>Zipping back to regular data types</h3>

<p>I like the (functor) fixed-point perspective on regular data types, for its austere formal simplicity.
It shows me the naked essence of regular data types, so I can more easily see and more deeply understand patterns like memoization, derivatives, and zippers.</p>

<p>For convenience and friendliness of <em>use</em>, I prefer working with regular types directly, rather than through the (nearly) isomorphic form of functor fixed-points.
While the fixed-point perspective is formalism-friendly, the <em>pattern functor</em> perspective is more user-friendly, allowing us to work with our familiar regular data as they are.</p>

<p>As in <em><a href="http://conal.net/blog/posts/elegant-memoization-with-higher-order-types/" title="blog post">Elegant memoization with higher-order types</a></em>, let&#8217;s use the following class:</p>

<pre><code>class Functor (PF t) ⇒ Regular t where
  type PF t :: * → *
  wrap   :: PF t t → t
  unwrap :: t → PF t t
</code></pre>

<p>The idea is that a type <code>t</code> is isomorphic to <code>Fix (PF t)</code>, although really there may be more points of undefinedness in the fixed-point representation, so rather than an isomorphism, we have an embedding/projection pair.</p>

<p>The notions of context and location are similar to the ones above:</p>

<pre><code>type Context t = [Der (PF t) t]

type Zipper t = (Context t, t)
</code></pre>

<p>So are the <code>up</code> and <code>down</code> motions, in which <code>wrap</code> and <code>unwrap</code> replace <code>Fix</code> and <code>unFix</code>:</p>

<pre><code>up   :: (Regular t, Holey (PF t)) ⇒ Zipper t →       Zipper t
down :: (Regular t, Holey (PF t)) ⇒ Zipper t → PF t (Zipper t)

up (d:ds', t) = (ds', wrap (fill (d,t)))

down (ds', t) = (fmap.first) (:ds') (extract (unwrap t))
</code></pre>
<p><a href="http://conal.net/blog/?flattrss_redirect&amp;id=154&amp;md5=29e8305b61bfd15d10c9a8d4f4b13bdf"><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-angle-on-zippers/feed</wfw:commentRss>
		<slash:comments>16</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-angle-on-zippers&amp;language=en_GB&amp;category=text&amp;title=Another+angle+on+zippers&amp;description=The+zipper+is+an+efficient+and+elegant+data+structure+for+purely+functional+editing+of+tree-like+data+structures%2C+first+published+by+G%C3%A9rard+Huet.+Zippers+maintain+a+location+of+focus+in+a...&amp;tags=derivative%2Cfunctor%2Czipper%2Cblog" type="text/html" />
	</item>
		<item>
		<title>Differentiation of higher-order types</title>
		<link>http://conal.net/blog/posts/differentiation-of-higher-order-types</link>
		<comments>http://conal.net/blog/posts/differentiation-of-higher-order-types#comments</comments>
		<pubDate>Thu, 29 Jul 2010 02:45:51 +0000</pubDate>
		<dc:creator><![CDATA[Conal]]></dc:creator>
				<category><![CDATA[Functional programming]]></category>
		<category><![CDATA[derivative]]></category>
		<category><![CDATA[functor]]></category>
		<category><![CDATA[zipper]]></category>

		<guid isPermaLink="false">http://conal.net/blog/?p=140</guid>
		<description><![CDATA[A &#8220;one-hole context&#8221; is a data structure with one piece missing. Conor McBride pointed out that the derivative of a regular type is its type of one-hole contexts. When a data structure is assembled out of common functor combinators, a corresponding type of one-hole contexts can be derived mechanically by rules that mirror the standard [&#8230;]]]></description>
				<content:encoded><![CDATA[<!-- 

Title: Differentiation of higher-order types

Tags: derivative, functor, zipper

URL: http://conal.net/blog/posts/differentiation-of-higher-order-types/

-->

<!-- references -->

<!-- teaser -->

<p>A &#8220;one-hole context&#8221; is a data structure with one piece missing.
Conor McBride pointed out that <a href="http://www.cs.nott.ac.uk/~ctm/diff.pdf" title="paper by Conor McBride">the derivative of a regular type is its type of one-hole contexts</a>.
When a data structure is assembled out of common functor combinators, a corresponding type of one-hole contexts can be derived mechanically by rules that mirror the standard derivative rules learned in beginning differential calculus.</p>

<p>I&#8217;ve been playing with functor combinators lately.
I was delighted to find that the data-structure derivatives can be expressed directly using the standard functor combinators and type families.</p>

<p>The code in this blog post is taken from the Haskell library <a href="http://hackage.haskell.org/package/functor-combo" title="Hackage entry: functor-combo">functor-combo</a>.</p>

<p>See also the <a href="http://en.wikibooks.org/wiki/Haskell/Zippers" title="Wikibooks entry">Haskell Wikibooks page on zippers</a>, especially the section called &#8220;Differentiation of data types&#8221;.</p>

<p>I mean this post not as new research, but rather as a tidy, concrete presentation of some of Conor&#8217;s delightful insight.</p>

<!--
**Edits**:

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

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

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

<h3>Functor combinators</h3>

<p>Let&#8217;s use the same set of functor combinators as in <em><a href="http://conal.net/blog/posts/elegant-memoization-with-higher-order-types/" title="blog post">Elegant memoization with higher-order types</a></em> and <em><a href="http://conal.net/blog/posts/memoizing-higher-order-functions/" title="blog post">Memoizing higher-order functions</a></em>:</p>

<pre><code>data Void a   -- no constructors

type Unit a        = Const () a

data Const x a     = Const x

newtype Id a       = Id a

data (f :+: g) a   = InL (f a) | InR (g a)

data (f :*: g) a   = f a :*: g a

newtype (g :. f) a = O (g (f a))
</code></pre>

<h3>Derivatives</h3>

<p>The derivative of a functor is another functor.
Since the shape of the derivative is non-uniform (depends on the shape of the functor being differentiated) define a higher-order <a href="http://www.haskell.org/ghc/docs/latest/html/users_guide/type-families.html" title="GHC documentation on type families">type family</a>:</p>

<pre><code>type family Der (f :: (* → *)) :: (* → *)
</code></pre>

<p>The usual derivative rules can then be translated without applying much imagination.
That is, if we start with derivative rules in their <em>functional</em> form (e.g., as in the paper <em><a href="http://conal.net/blog/posts/paper-beautiful-differentiation/" title="blog post">Beautiful differentiation</a></em>, Section 2 and Figure 1).</p>

<p>For instance, the derivative of the constant function is the constant 0 function, and the derivative of the identity function is the constant 1 function.
If <code>der</code> is the derivative functional mapping functions (of real numbers) to functions,</p>

<pre><code>der (const x) ≡ 0
der id        ≡ 1
</code></pre>

<p>On the right-hand sides, I am exploiting the function instances of <code>Num</code> from the library <a href="http://hackage.haskell.org/cgi-bin/hackage-scripts/package/applicative-numbers" title="Haskell library">applicative-numbers</a>.
To be more explicit, I could have written &#8220;<code>const 0</code>&#8221; and &#8220;<code>const 1</code>&#8220;.</p>

<p>Correspondingly,</p>

<pre><code>type instance Der (Const x) = Void   -- 0

type instance Der Id        = Unit   -- 1
</code></pre>

<p>Note that the types <code>Void a</code> and <code>Unit a</code> have 0 and 1 element, respectively, if we ignore ⊥.
Moreover, <code>Void</code> is a sort of additive identity, and <code>Unit</code> is a sort of multiplicative identity, again ignoring ⊥.
For these reasons, <code>Void</code> and <code>Unit</code> might be more aptly named &#8220;<code>Zero</code>&#8221; and &#8220;<code>One</code>&#8220;.</p>

<p>The first rule says that the a value of type <code>Const x a</code> has no one-hole context (for type <code>a</code>), which is true, since there is an <code>x</code> but no <code>a</code>.
The second rule says that there is exactly one possible context for <code>Id a</code>, since the one and only <code>a</code> value must be removed, and no information remains.</p>

<p>A (one-hole) context for a sum is a context for the left or the right possibility of the sum:</p>

<pre><code>type instance Der (f :+: g) = Der f :+: Der g
</code></pre>

<p>Correspondingly, the derivative of a sum of functions is the sum of the functions&#8217; derivatives::</p>

<pre><code>der (f + g) ≡ der f + der g
</code></pre>

<p>Again I&#8217;m using the function <code>Num</code> instance from <a href="http://hackage.haskell.org/cgi-bin/hackage-scripts/package/applicative-numbers" title="Haskell library">applicative-numbers</a>.</p>

<p>For a pair, the one hole of a context can be made somewhere in the first component or somewhere in the second component.
So the pair context consists of a holey first component and a full second component or a full first component and a holey second component.</p>

<pre><code>type instance Der (f :*: g) = Der f :*: g  :+:  f :*: Der g
</code></pre>

<p>Similarly, for functions:</p>

<pre><code>der (f * g) ≡ der f * g + f * der g
</code></pre>

<p>Finally, consider functor composition.
If <code>g</code> and <code>f</code> are container types, then <code>(g :. f) a</code> is the type of <code>g</code> containers of <code>f</code> containers of <code>a</code> elements.
The <code>a</code>-shaped hole must come from one of the contained <code>f a</code> structures.</p>

<pre><code>type instance Der (g :. f) = (Der g :. f) :*: Der f
</code></pre>

<p>Here&#8217;s one way to think of this derivative functor:
to make an <code>a</code>-shaped hole in a <code>g (f a)</code>, first remove an <code>f a</code> structure, leaving an <code>(f a)</code>-shaped hole, and then put back all but an <code>a</code> value extracted from the removed <code>f a</code> struture.
So the overall (one-hole) context can be assembled from two parts: a <code>g</code> context of <code>f a</code> structures, and an <code>f</code> context of <code>a</code> values.</p>

<p>The corresponding rule for function derivatives:</p>

<pre><code>der (g ∘ f) ≡ (der g ∘ f) * der f
</code></pre>

<p>which again uses <code>Num</code> on functions.
Written out more explicitly:</p>

<pre><code>der (g ∘ f) a ≡ der g (f a)  * der f a
</code></pre>

<p>which may look more like the form you&#8217;re used to.</p>

<h3>Summary of derivatives</h3>

<p>To emphasize the correspondence between forms of differentiation, here are rules for <em>function</em> and <em>functor</em> derivatives:</p>

<pre><code>der (const x) ≡ 0
Der (Const x) ≡ Void

der id ≡ 1
Der Id ≡ Unit

der (f  +  g) ≡ der f  +  der g
Der (f :+: g) ≡ Der f :+: Der g

der (f  *  g) ≡ der f  *  g  +  f  *  der g
Der (f :*: g) ≡ Der f :*: g :+: f :*: Der g

der (g  ∘ f) ≡ (der g  ∘ f)  *  der f
Der (g :. f) ≡ (Der g :. f) :*: Der f
</code></pre>

<h3>Filling holes</h3>

<p>Each derivative functor is a one-hole container.
One useful operation on derivatives is filling that hole.</p>

<pre><code>fillC :: Functor f ⇒ Der f a → a → f a
</code></pre>

<p>The specifics of how to fill in a hole will depend on the choice of functor <code>f</code>, so let&#8217;s make the <code>fillC</code> operation a method of a new type class.
This new class is also a handy place to stash the associated type of derivatives, as an alternative to the top-level declarations above.</p>

<pre><code>class Functor f ⇒ Holey f where
  type Der f :: * → *
  fillC :: Der f a → a → f a
</code></pre>

<p>I&#8217;ll add one more method to this class in an upcoming post.</p>

<p>For <code>Const x</code>, there are no cases to handle, since there are no holes.</p>

<pre><code>instance Holey (Const x) where
  type Der (Const x) = Void
  fillC = error "fillC for Const x: no Der values"
</code></pre>

<p>I added a definition just to keep the compiler from complaining.
This particular <code>fillC</code> can only be applied to a value of type <code>Void a</code>, and there are no such values other than ⊥.</p>

<p>Is there a more elegant way to define functions over data types with no constructors?
One idea is to provide a single, polymorphic function over void types:</p>

<pre><code>  voidF :: Void a → b
  voidF = error "voidF: no value of type Void"
</code></pre>

<p>And use whenever as needed, e.g.,</p>

<pre><code>  fillC = voidF
</code></pre>

<p>Next is our identity functor:</p>

<pre><code>instance Holey Id where
  type Der Id = Unit
  fillC (Const ()) a = Id a
</code></pre>

<p>More succinctly,</p>

<pre><code>  fillC (Const ()) = Id
</code></pre>

<p>For sums,</p>

<pre><code>instance (Holey f, Holey g) ⇒ Holey (f :+: g) where
  type Der (f :+: g) = Der f :+: Der g
  fillC (InL df) a = InL (fillC df a)
  fillC (InR df) a = InR (fillC df a)
</code></pre>

<p>or</p>

<pre><code>  fillC (InL df) = InL ∘ fillC df
  fillC (InR df) = InR ∘ fillC df
</code></pre>

<p>Products also have two cases, since the derivative of a product is a sum:</p>

<pre><code>instance (Holey f, Holey g) ⇒ Holey (f :*: g) where
  type Der (f :*: g) = Der f :*: g  :+:  f :*: Der g
  fillC (InL (dfa :*:  ga)) a = fillC dfa a :*: ga
  fillC (InR ( fa :*: dga)) a = fa :*: fillC dga a
</code></pre>

<p>Less pointfully,</p>

<pre><code>  fillC (InL (dfa :*:  ga)) = (:*: ga) ∘ fillC dfa
  fillC (InR ( fa :*: dga)) = (fa :*:) ∘ fillC dga
</code></pre>

<p>Finally, functor composition:</p>

<pre><code>instance (Holey f, Holey g) ⇒ Holey (g :. f) where
  type Der (g :. f) = (Der g :. f) :*: Der f
  fillC (O dgfa :*: dfa) a = O (fillC dgfa (fillC dfa a))
</code></pre>

<p>The less pointful form is more telling.</p>

<pre><code>  fillC (O dgfa :*: dfa) = O ∘ fillC dgfa ∘ fillC dfa
</code></pre>

<p>In words: filling of the derivative of a composition is a composition of filling of the derivatives.</p>

<h3>Thoughts on composition</h3>

<p>Let&#8217;s return to the derivative rules for composition, i.e., the chain rule, on functions and on functors:</p>

<pre><code>der (g  ∘ f) ≡ (der g  ∘ f)  *  der f

Der (g :. f) ≡ (Der g :. f) :*: Der f
</code></pre>

<p>Written in this way, the functor rule looks quite compelling.
Something bothers me, however.
For functions, multiplication is a special case, not the general case, and is only meaningful and correct when differentiating functions from scalars to scalars.
In general, derivative values are <em>linear maps</em>, and the chain rule uses composition on linear maps rather than multiplication on scalars (that <em>represent</em> linear maps).
I&#8217;ve written several <a href="http://conal.net/blog/tag/derivative/" title="Posts on derivatives">posts on derivatives</a> and a paper <em><a href="http://conal.net/blog/posts/paper-beautiful-differentiation/" title="blog post">Beautiful differentiation</a></em>, describing this perspective, which comes from calculus on manifolds.</p>

<p>Look again at the less pointful formulation of <code>fillC</code> for derivatives of compositions:</p>

<pre><code>  fillC (O dgfa :*: dfa) = O ∘ fillC dgfa ∘ fillC dfa
</code></pre>

<p>The product in this case is just structural.
The actual use in <code>fillC</code> is indeed a composition of linear maps.
In this context, &#8220;linear&#8221; has a different meaning from before.
It&#8217;s another way of saying &#8220;fills a <em>one-hole</em> context&#8221; (as the linear patterns of term rewriting and of ML &amp; Haskell).</p>

<p>So maybe there&#8217;s a more general/abstract view of <em>functor</em> derivatives, just as there is a more general/abstract view of <em>function</em> derivatives.
In that view, we might replace the functor chain rule&#8217;s product with a notion of composition.</p>
<p><a href="http://conal.net/blog/?flattrss_redirect&amp;id=140&amp;md5=aa94cf980e9605e54025a8adb6e7d65f"><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/differentiation-of-higher-order-types/feed</wfw:commentRss>
		<slash:comments>5</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%2Fdifferentiation-of-higher-order-types&amp;language=en_GB&amp;category=text&amp;title=Differentiation+of+higher-order+types&amp;description=A+%26%238220%3Bone-hole+context%26%238221%3B+is+a+data+structure+with+one+piece+missing.+Conor+McBride+pointed+out+that+the+derivative+of+a+regular+type+is+its+type+of+one-hole+contexts.+When+a...&amp;tags=derivative%2Cfunctor%2Czipper%2Cblog" type="text/html" />
	</item>
		<item>
		<title>Details for non-strict memoization, part 1</title>
		<link>http://conal.net/blog/posts/details-for-nonstrict-memoization-part-1</link>
		<comments>http://conal.net/blog/posts/details-for-nonstrict-memoization-part-1#comments</comments>
		<pubDate>Tue, 27 Jul 2010 00:14:20 +0000</pubDate>
		<dc:creator><![CDATA[Conal]]></dc:creator>
				<category><![CDATA[Functional programming]]></category>
		<category><![CDATA[functor]]></category>
		<category><![CDATA[memoization]]></category>
		<category><![CDATA[trie]]></category>
		<category><![CDATA[unamb]]></category>

		<guid isPermaLink="false">http://conal.net/blog/?p=131</guid>
		<description><![CDATA[In Non-strict memoization, I sketched out a means of memoizing non-strict functions. I gave the essential insight but did not show the details of how a nonstrict memoization library comes together. In this new post, I give details, which are a bit delicate, in terms of the implementation described in Elegant memoization with higher-order types. [&#8230;]]]></description>
				<content:encoded><![CDATA[<!-- 

Title: Details for non-strict memoization, part 1

Tags: memoization, functor, trie, unamb

URL: http://conal.net/blog/posts/details-for-nonstrict-memoization-part-1/

-->

<!-- references -->

<!-- teaser -->

<p>In <em><a href="http://conal.net/blog/posts/nonstrict-memoization/" title="blog post">Non-strict memoization</a></em>, I sketched out a means of memoizing non-strict functions.
I gave the essential insight but did not show the details of how a nonstrict memoization library comes together.
In this new post, I give details, which are a bit delicate, in terms of the implementation described in <em><a href="http://conal.net/blog/posts/elegant-memoization-with-higher-order-types/" title="blog post">Elegant memoization with higher-order types</a></em>.</p>

<p>Near the end, I run into some trouble with regular data types, which I don&#8217;t know how to resolve cleanly and efficiently.</p>

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

<ul>
<li>2010-09-10: Fixed minor typos.</li>
</ul>

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

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

<h3>Hyper-strict memo tries</h3>

<p>Strict memoization (really <em>hyper-strict</em>) is centered on a family of trie functors, defined as a functor <code>Trie k</code>, associated with a type <code>k</code>.</p>

<pre><code>type k :→: v = Trie k v

class HasTrie k where
    type Trie k :: * → *
    trie   :: (k  →  v) → (k :→: v)
    untrie :: (k :→: v) → (k  →  v)
</code></pre>

<p>The simplest instance is for the unit type:</p>

<pre><code>instance HasTrie () where
  type Trie ()  = Id
  trie   f      = Id (f ())
  untrie (Id v) = λ () → v
</code></pre>

<p>For consistency with other types, I just made a small change from the previous version, which used <code>const v</code> instead of the stricter <code>λ () → v</code>.</p>

<p>Sums and products are a little more intricate:</p>

<pre><code>instance (HasTrie a, HasTrie b) ⇒ HasTrie (Either a b) where
  type Trie (Either a b) = Trie a :*: Trie b
  trie   f           = trie (f ∘ Left) :*: trie (f ∘ Right)
  untrie (ta :*: tb) = untrie ta `either` untrie tb

instance (HasTrie a, HasTrie b) ⇒ HasTrie (a , b) where
  type Trie (a , b) = Trie a :. Trie b
  trie   f = O (trie (trie ∘ curry f))
  untrie (O tt) = uncurry (untrie ∘ untrie tt)
</code></pre>

<p>These trie types are not just strict, they&#8217;re <em>hyper-strict</em>.
During trie search, arguments get thorougly evaluated.
(See Section 9 in the paper <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>.)
In other words, all of the points of possible undefinedness are lost.</p>

<h3>Strict and non-strict memo tries</h3>

<p>The formulation of strict tries will look very like the hyper-strict tries we&#8217;ve already seen, with new names for the associated trie type and the conversion methods:</p>

<pre><code>type k :→ v = STrie k v

class HasTrie k where
    type STrie k :: * → *
    sTrie   ::             (k  → v) → (k :→ v)
    sUntrie :: HasLub v ⇒ (k :→ v) → (k  → v)
</code></pre>

<p>Besides renaming, I&#8217;ve also added a <code>HasLub</code> constraint for <code>sUntrie</code>, which we&#8217;ll need later.</p>

<p>For instance, the (almost) simplest strict trie is the one for the unit type, defined exactly as before (with new names):</p>

<pre><code>instance HasTrie () where
  type STrie ()  = Id
  sTrie   f      = Id (f ())
  sUntrie (Id v) = λ () → v
</code></pre>

<p>For <em>non-strict</em> memoization, we&#8217;ll want to recover all of the points of possible undefinedness lost in hyper-strict memoization.
At every level of a structured value, there is the possibility of ⊥ or of a non-⊥ value.
Correspondingly, a non-strict trie consists of the value corresponding to the argument ⊥, together with a strict (but <em>not</em> hyper-strict) trie for the non-⊥ values:</p>

<pre><code>data Trie k v = Trie v (k :→ v)

type k :→: v = Trie k v
</code></pre>

<p>The conversions between functions and non-strict tries are no longer methods, as they can be defined uniformly for all domain types.
To form a non-strict trie, capture the function&#8217;s value at ⊥, and build a strict (but not hyper-strict) trie:</p>

<pre><code>trie   :: (HasTrie k          ) ⇒ (k  →  v) → (k :→: v)
trie f = Trie (f ⊥) (sTrie f)
</code></pre>

<p>To convert back from a non-strict trie to a (now memoized) function, combine the information from two sources: the original function&#8217;s value at ⊥, and the function resulting from the strict (but not hyper-strict) trie:</p>

<pre><code>untrie :: (HasTrie k, HasLub v) ⇒ (k :→: v) → (k  →  v)
untrie (Trie b t) = const b ⊔ sUntrie t
</code></pre>

<p>The least-upper-bound (⊔) here is well-defined because its arguments are information-compatible (consistent, non-contradictory).
More strongly, <code>const b ⊑ sUntrie t</code>, i.e., the first argument is an information approximation to (contains no information absent from) the second argument.
Now we see the need for <code>HasLub v</code> in the type of <code>sUntrie</code> above: functions are ⊔-able exactly when their result types are.</p>

<h3>Sums</h3>

<p>Just as non-strict tries contain strict tries, so also strict tries contain non-strict tries.
For instance, consider a sum type, <code>Either a b</code>.
An element is either ⊥ or <code>Left x</code> or <code>Right y</code>, for <code>x :: a</code> and <code>y :: b</code>.
The types <code>a</code> and <code>b</code> also contain a bottom element, so we&#8217;ll need non-strict memo tries for them:</p>

<pre><code>instance (HasTrie a, HasTrie b) ⇒ HasTrie (Either a b) where
  type STrie (Either a b) = Trie a :*: Trie b
  sTrie   f           = trie (f ∘ Left) :*: trie (f ∘ Right)
  sUntrie (ta :*: tb) = untrie ta `either` untrie tb
</code></pre>

<p>Just as in the unit instance (above), the only visible change from hyper-strict to strict is that the left-hand sides use the strict trie type and operations.
The right-hand sides are written exactly as before, though now they refer to non-strict tries and their operations.</p>

<h3>Products</h3>

<p>With product, we run into some trouble.
As a first attempt, change only the names on the left-hand side:</p>

<pre><code>instance (HasTrie a, HasTrie b) ⇒ HasTrie (a , b) where
  type STrie (a , b) = Trie a :. Trie b
  sTrie   f      = O (trie (trie ∘ curry f))
  sUntrie (O tt) = uncurry (untrie ∘ untrie tt)
</code></pre>

<p>This <code>sUntrie</code> definition, however, leads to an error in type-checking:</p>

<pre><code>Could not deduce (HasLub (Trie b v)) from the context (HasLub v)
  arising from a use of `untrie'
</code></pre>

<p>The troublesome <code>untrie</code> use is the one applied directly to <code>tt</code>.
(Thank you for column numbers, GHC.)</p>

<p>So what&#8217;s going on here?
Since <code>sUntrie</code> in this definition takes a <code>(a,b) :→ v</code>, or equivalently, <code>STrie (a,b) v</code>,</p>

<pre><code>O tt :: (a,b) :→ v
     :: STrie (a,b) v
     :: (Trie a :. Trie b) v
</code></pre>

<p>The definition of type composition (from <a href="http://conal.net/blog/posts/elegant-memoization-with-higher-order-types/" title="blog post">an earlier post</a>) is</p>

<pre><code>newtype (g :. f) x = O (g (f x))
</code></pre>

<p>So</p>

<pre><code>tt :: Trie a (Trie b v)
   :: a :→: b :→: v
</code></pre>

<p>and</p>

<pre><code>untrie tt :: HasLub (b :→: v) ⇒ a → (b :→: v)
</code></pre>

<p>The <code>HasLub</code> constraint comes from the type of <code>untrie</code> (above).</p>

<p>Continuing,</p>

<pre><code>untrie ∘ untrie tt ::
  (HasLub v, HasLub (b :→: v)) ⇒ a → (b → v)

uncurry (untrie ∘ untrie tt) ::
  (HasLub v, HasLub (b :→: v)) ⇒ (a , b) → v
</code></pre>

<p>which is <em>almost</em> the required type but contains the extra requirement that <code>HasLub (b :→: v)</code>.</p>

<p>Hm.</p>

<p>Looking at the definition of <code>Trie</code> and the definitions of <code>STrie</code> for various domain types <code>b</code>, I think it&#8217;s the case that <code>HasLub (b :→: v)</code>, whenever <code>HasLub v</code>, exactly as needed.
In principle, I could make this requirement of <code>b</code> explicit as a superclass for <code>HasTrie</code>:</p>

<pre><code>class (forall v. HasLub v ⇒ HasLub (b :→: v)) ⇒ HasTrie k where ...
</code></pre>

<p>However, Haskell&#8217;s type system isn&#8217;t quite expressive enough, even with GHC extensions (as far as I know).</p>

<h4>A possible solution</h4>

<p>We could instead define a functor-level variant of <code>HasLub</code>:</p>

<pre><code>class HasLubF f where
  lubF :: HasLub v ⇒ f v → f v → f v
</code></pre>

<p>and then use <code>lubF</code> instead of <code>(⊔)</code> in <code>sUntrie</code>.
The revised <code>HasTrie</code> class definition:</p>

<pre><code>class HasLubF (Trie k) ⇒ HasTrie k where
    type STrie k :: * → *
    sTrie   ::             (k  → v) → (k :→ v)
    sUntrie :: HasLub v ⇒ (k :→ v) → (k  → v)
</code></pre>

<p>I would rather not replicate and modify the <code>HasLub</code> class and all of its instances, so I&#8217;m going to set this idea aside and look for another.</p>

<h4>Another route</h4>

<p>Let&#8217;s return to the problematic definition of <code>sUntrie</code> for pairs:</p>

<pre><code>sUntrie (O tt) = uncurry (untrie ∘ untrie tt)
</code></pre>

<p>and recall that <code>tt :: a :→: b :→: v</code>.
The strategy here was to first convert the outer trie (with domain <code>a</code>) and then the inner trie (with domain <code>b</code>).</p>

<p>Alternatively, we might reverse the order.</p>

<p>If we&#8217;re going to convert inside-out instead of outside-in, then we&#8217;ll need a way to transform each of the <em>range</em> elements of a trie.
Which is exactly what <code>fmap</code> is for.
If only we had a functor instance for <code>Trie a</code>, then we could re-define <code>sUntrie</code> on pair tries as follows:</p>

<pre><code>sUntrie (O tt) = uncurry (untrie (fmap untrie tt))
</code></pre>

<p>As a sanity check, try compiling this definition.
Sure enough, it&#8217;s okay except for a missing <code>Functor</code> instance:</p>

<pre><code>Could not deduce (Functor (Trie a))
  from the context (HasTrie (a, b), HasTrie a, HasTrie b)
  arising from a use of `fmap'
</code></pre>

<p>Fixed easily enough:</p>

<pre><code>instance Functor (STrie k) ⇒ Functor (Trie k) where
  fmap f (Trie b t) = Trie (f b) (fmap f t)
</code></pre>

<p>Or even, using the GHC language extensions <code>DeriveFunctor</code> and <code>StandaloneDeriving</code>, just</p>

<pre><code>deriving instance Functor (STrie k) ⇒ Functor (Trie k)
</code></pre>

<p>Now we get a slightly different error message.
We&#8217;re now missing a Functor instance for <code>STrie a</code> instead of <code>Trie a</code>:</p>

<pre><code>Could not deduce (Functor (STrie a))
  from the context (HasTrie (a, b), HasTrie a, HasTrie b)
  arising from a use of `fmap'
</code></pre>

<p>By the way, we can also construct tries inside-out, if we want:</p>

<pre><code>sTrie f = O (fmap trie (trie (curry f)))
</code></pre>

<p>So we&#8217;ll be in good shape <em>if</em> we can satisfy the <code>Functor</code> requirement on strict tries.
Fortunately, all of the strict trie (higher-order) types appearing are indeed functors, since we built them up using functor combinators.</p>

<p>Still, we&#8217;ll have to help the type-checker <em>prove</em> that all of the trie types it involved must indeed be functors.
Again, a superclass constraint can capture this requirement:</p>

<pre><code>class Functor (STrie k) ⇒ HasTrie k where ...
</code></pre>

<p>Unlike <code>HasLub</code>, this time the required constraint is already at the functor level, so we don&#8217;t have to define a new class.
We don&#8217;t even have to define any new instances, as our functor combinators come with <code>Functor</code> instances, all of which can be derived automatically by GHC.</p>

<p>With this one change, all of the <code>HasTrie</code> instances go through!</p>

<h3>Isomorphisms</h3>

<p>As pointed out in <em><a href="http://conal.net/blog/posts/memoizing-higher-order-functions/" title="blog post">Memoizing higher-order functions</a></em>, type isomorphism is the central, repeated theme of functional memoization.
In addition to the isomorphism between functions and tries, the tries for many types are given via isomorphism with other types that have tries.
In this way, we only have to define tries for our tiny set of functor combinators.</p>

<p>Isomorphism support is as in <em><a href="http://conal.net/blog/posts/elegant-memoization-with-higher-order-types/" title="blog post">Elegant memoization with higher-order types</a></em>, just using the new names:</p>

<pre><code>#define HasTrieIsomorph(Context,Type,IsoType,toIso,fromIso) 
instance Context ⇒ HasTrie (Type) where { 
  type STrie (Type) = STrie (IsoType); 
  sTrie f = sTrie (f ∘ (fromIso)); 
  sUntrie t = sUntrie t ∘ (toIso); 
}
</code></pre>

<p>Note the use of strict tries even on the right-hand sides.</p>

<p><em>Aside:</em> as mentioned in <em><a href="http://conal.net/blog/posts/composing-memo-tries/" title="blog post">Composing memo tries</a></em>, <code>trie</code>/<code>untrie</code> forms not just an isomorphism but a pair of <a href="http://conal.net/blog/tag/type-class-morphism/" title="Posts on type class morphisms">type class morphism</a>s (TCMs).
(For motivation and examples of TCMs in software design, see <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>.)</p>

<h3>Regular data types</h3>

<p><em>Regular data types</em> are isomorphic to fixed-points of functors.
<em><a href="http://conal.net/blog/posts/elegant-memoization-with-higher-order-types/" title="blog post">Elegant memoization with higher-order types</a></em> gives a brief introduction to these notions and pointers to more information.
That post also shows how to use the <code>Regular</code> type class and its instances (defined for other purposes as well) to provide hyper-strict memo tries for all regular data types.</p>

<p>Switching from hyper-strict to non-strict raises an awkward issue.
The functor isomorphisms we used are only correct for fully defined data-types.
When we allow full or partial undefinedness, as in a lazy language like Haskell, our isomorphisms break down.</p>

<p>Following <em><a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.142.4778" title="Paper by Thomas Noort, Alexey Rodriguez, Stefan Holdermans, Johan Jeuring, Bastiaan Heeren">A Lightweight Approach to Datatype-Generic Rewriting</a></em>, here is the class I used, where &#8220;<code>PF</code>&#8221; stands for &#8220;pattern functor&#8221;:</p>

<pre><code>class Functor (PF t) ⇒ Regular t where
  type PF t :: * → *
  unwrap :: t → PF t t
  wrap   :: PF t t → t
</code></pre>

<p>The <code>unwrap</code> method peels off a single layer from a regular type.
For example, the top level of a list is either a unit (nil) or a pair (cons) of an element and a hole in which a list can be placed.</p>

<pre><code>instance Regular [a] where
  type PF [a] = Unit :+: Const a :*: Id   -- note Unit == Const ()

  unwrap []     = InL (Const ())
  unwrap (a:as) = InR (Const a :*: Id as)

  wrap (InL (Const ()))          = []
  wrap (InR (Const a :*: Id as)) = a:as
</code></pre>

<p>The catch here is that the <code>unwrap</code> and <code>wrap</code> methods do not really form an isomorphism.
Instead, they satisfy a weaker connection: they form embedding/projection pair.
That is,</p>

<pre><code>wrap ∘ unwrap ≡ id
unwrap ∘ wrap ⊑ id
</code></pre>

<p>To see the mismatch between <code>[a]</code> and <code>PF [a] [a]</code>, note that the latter has opportunities for partial undefinedness that have no corresponding opportunities in <code>[a]</code>.
Specifically, ⊥ could occur at type <code>Const () [a]</code>, <code>()</code>,  <code>(Const a :*: Id) [a]</code>, <code>Const a [a]</code>, or <code>Id [a]</code>.
Any of these ⊥ values will result in <code>wrap</code> returning ⊥ altogether.
For instance, if</p>

<pre><code>oops :: PF [Integer]
oops = InR (⊥ :*: Id [3,5])
</code></pre>

<p>then</p>

<pre><code>unwrap (wrap oops) ≡ unwrap ⊥ ≡ ⊥ ⊑ oops
</code></pre>

<p>By examining various cases, we can prove that <code>unwrap (wrap p) ⊑ p</code> for all <code>p</code>, which is to say <code>unwrap ∘ wrap ⊑ id</code>, since
information ordering on functions is defined point-wise.
(See <em><a href="http://conal.net/blog/posts/merging-partial-values/" title="blog post">Merging partial values</a></em>.)</p>

<p>Examining the definition of <code>unwrap</code> above shows that it does not give rise to the troublesome ⊥ points, and so a trivial equational proof shows that <code>wrap ∘ unwrap ≡ id</code>.</p>

<p>In the context of memoization, the additional undefined values are problematic.
Consider the case of lists.
The specification macro</p>

<pre><code>HasTrieRegular1([], ListSTrie)
</code></pre>

<p>expands into a <code>newtype</code> and its <code>HasTrie</code> instance.
Changing only the associated type and method names in the <a href="http://conal.net/blog/posts/elegant-memoization-with-higher-order-types/" title="blog post">version for hyper-strict memoization</a>:</p>

<pre><code>newtype ListSTrie a v = ListSTrie (PF [a] [a] :→: v)

instance HasTrie a ⇒ HasTrie [a] where
  type STrie [a] = ListSTrie a
  sTrie f = ListSTrie (sTrie (f . wrap))
  sUntrie (ListSTrie t) = sUntrie t . unwrap
</code></pre>

<p>Note that the trie in <code>ListSTrie</code> trie contains entries for many ⊥ sub-elements that do not correspond to any list values.
The memoized function is <code>f ∘ wrap</code>, which will have many fewer ⊥ possibilities than the trie structure supports.
At each of the superfluous ⊥ points, the function sampled is strict, so the <code>Trie</code> (rather than <code>STrie</code>) will contain a predictable ⊥.
Considering the definition of <code>untrie</code>:</p>

<pre><code>untrie (Trie b t) = const b ⊔ sUntrie t
</code></pre>

<p>we know <code>b ≡ ⊥</code>, and so <code>const b ⊔ sUntrie t ≡ sUntrie t</code>.
Thus, at these points, the ⊥ value is never helpful, and we could use a strict (though not hyper-strict) trie instead of a non-strict trie.</p>

<p>Perhaps we could safely ignore this whole issue and lose only some efficiency, rather than correctness.
Still, I&#8217;d rather build and traverse just the right trie for our regular types.</p>

<p>As this post is already longer than I intended, and my attention is wandering, I&#8217;ll publish it here and pick up later.
Comments &amp; suggestions please!</p>
<p><a href="http://conal.net/blog/?flattrss_redirect&amp;id=131&amp;md5=21d7a6c4a22de6280e624f13d3efce1f"><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/details-for-nonstrict-memoization-part-1/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%2Fdetails-for-nonstrict-memoization-part-1&amp;language=en_GB&amp;category=text&amp;title=Details+for+non-strict+memoization%2C+part+1&amp;description=In+Non-strict+memoization%2C+I+sketched+out+a+means+of+memoizing+non-strict+functions.+I+gave+the+essential+insight+but+did+not+show+the+details+of+how+a+nonstrict+memoization+library+comes...&amp;tags=functor%2Cmemoization%2Ctrie%2Cunamb%2Cblog" type="text/html" />
	</item>
		<item>
		<title>Elegant memoization with higher-order types</title>
		<link>http://conal.net/blog/posts/elegant-memoization-with-higher-order-types</link>
		<comments>http://conal.net/blog/posts/elegant-memoization-with-higher-order-types#comments</comments>
		<pubDate>Wed, 21 Jul 2010 04:48:22 +0000</pubDate>
		<dc:creator><![CDATA[Conal]]></dc:creator>
				<category><![CDATA[Functional programming]]></category>
		<category><![CDATA[functor]]></category>
		<category><![CDATA[isomorphism]]></category>
		<category><![CDATA[memoization]]></category>
		<category><![CDATA[trie]]></category>

		<guid isPermaLink="false">http://conal.net/blog/?p=117</guid>
		<description><![CDATA[A while back, I got interested in functional memoization, especially after seeing some code from Spencer Janssen using the essential idea of Ralf Hinze&#8217;s paper Generalizing Generalized Tries. The blog post Elegant memoization with functional memo tries describes a library, MemoTrie, based on both of these sources, and using associated data types. I would have [&#8230;]]]></description>
				<content:encoded><![CDATA[<!-- 

Title: Elegant memoization with higher-order types

Tags: functor, memoization, isomorphism, trie

URL: http://conal.net/blog/posts/elegant-memoization-with-higher-order-types/

-->

<!-- references -->

<!-- teaser -->

<p>A while back, I got interested in functional memoization, especially after seeing some code from Spencer Janssen using the essential idea of Ralf Hinze&#8217;s paper <em><a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.8.4069" title="Paper: &quot;Generalizing Generalized Tries&quot; by Ralf Hinze">Generalizing Generalized Tries</a></em>.
The blog post <em><a href="http://conal.net/blog/posts/elegant-memoization-with-functional-memo-tries/" title="blog post">Elegant memoization with functional memo tries</a></em> describes a library, <a href="http://haskell.org/haskellwiki/MemoTrie" title="Haskell wiki page for the MemoTrie library">MemoTrie</a>, based on both of these sources, and using <a href="http://www.cse.unsw.edu.au/~chak/papers/papers.html#assoc" title="Paper: &quot;Associated Types with Class&quot;">associated data types</a>.
I would have rather used associated type synonyms and standard types, but I couldn&#8217;t see how to get the details to work out.
Recently, while playing with functor combinators, I realized that they might work for memoization, which they do quite nicely.</p>

<p>This blog post shows how functor combinators lead to an even more elegant formulation of functional memoization.
The code is available as part of the <a href="http://hackage.haskell.org/package/functor-combo" title="Hackage entry: functor-combo">functor-combo</a> package.</p>

<p>The techniques in this post are not so much new as they are ones that have recently been sinking in for me.
See <em><a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.8.4069" title="Paper: &quot;Generalizing Generalized Tries&quot; by Ralf Hinze">Generalizing Generalized Tries</a></em>, as well as <em><a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.140.2412" title="Paper by Alexey Rodriguez, Stefan Holdermans, Andres Löh, and Johan Jeuring">Generic programming with fixed points for mutually recursive datatypes</a></em>.</p>

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

<ul>
<li>2011-01-28: Fixed small typo: &#8220;<em>b^^a^^</em>&#8221; ⟼ &#8220;<em>b<sup>a</sup></em>&#8220;</li>
<li>2010-09-10: Corrected <code>Const</code> definition to use <code>newtype</code> instead of <code>data</code>.</li>
<li>2010-09-10: Added missing <code>Unit</code> type definition (as <code>Const ()</code>).</li>
</ul>

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

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

<h3>Tries as associated data type</h3>

<p>The <a href="http://haskell.org/haskellwiki/MemoTrie" title="Haskell wiki page for the MemoTrie library">MemoTrie</a> library is centered on a class <code>HasTrie</code> with an associated data type of tries (efficient indexing structures for memoized functions):</p>

<pre><code>class HasTrie k where
    data (:→:) k :: * → *
    trie   :: (k  →  v) → (k :→: v)
    untrie :: (k :→: v) → (k  →  v)
</code></pre>

<p>The type <code>a :→: b</code> represents a trie that maps values of type <code>a</code> to values of type <code>b</code>.
The trie representation depends only on <code>a</code>.</p>

<p>Memoization is a simple combination of these two methods:</p>

<pre><code>memo :: HasTrie a ⇒ (a → b) → (a → b)
memo = untrie . trie
</code></pre>

<p>The <code>HasTrie</code> instance definitions correspond to isomorphisms invoving function types.
The isomorphisms correspond to the familiar rules of exponents, if we translate <em>a → b</em> into <em>b<sup>a</sup></em>.
(See <em><a href="http://conal.net/blog/posts/elegant-memoization-with-functional-memo-tries/" title="blog post">Elegant memoization with functional memo tries</a></em> for more explanation.)</p>

<pre><code>instance HasTrie () where
    data () :→: x = UnitTrie x
    trie f = UnitTrie (f ())
    untrie (UnitTrie x) = const x

instance (HasTrie a, HasTrie b) ⇒ HasTrie (Either a b) where
    data (Either a b) :→: x = EitherTrie (a :→: x) (b :→: x)
    trie f = EitherTrie (trie (f . Left)) (trie (f . Right))
    untrie (EitherTrie s t) = either (untrie s) (untrie t)

instance (HasTrie a, HasTrie b) ⇒ HasTrie (a,b) where
    data (a,b) :→: x = PairTrie (a :→: (b :→: x))
    trie f = PairTrie (trie (trie . curry f))
    untrie (PairTrie t) = uncurry (untrie .  untrie t)
</code></pre>

<h3>Functors and functor combinators</h3>

<p>For notational convenience, let &#8220;<code>(:→:)</code>&#8221; be a synonym for &#8220;<code>Trie</code>&#8220;:</p>

<pre><code>type k :→: v = Trie k v
</code></pre>

<p>And replace the associated <code>data</code> with an associated <code>type</code>.</p>

<pre><code>class HasTrie k where
    type Trie k :: * → *
    trie   :: (k  →  v) → (k :→: v)
    untrie :: (k :→: v) → (k  →  v)
</code></pre>

<p>Then, imitating the three <code>HasTrie</code> instances above,</p>

<pre><code>type Trie () v = v

type Trie (Either a b) v = (Trie a v, Trie b v)

type Trie (a,b) v = Trie a (Trie b v)
</code></pre>

<p>Imagine that we have type lambdas for writing higher-kinded types.</p>

<pre><code>type Trie () = λ v → v

type Trie (Either a b) = λ v → (Trie a v, Trie b v)

type Trie (a,b) = λ v → Trie a (Trie b v)
</code></pre>

<p>Type lambdas are often written as &#8220;Λ&#8221; (capital &#8220;λ&#8221;) instead.
In the land of values, these three right-hand sides correspond to common building blocks for functions, namely identity, product, and composition:</p>

<pre><code>id      = λ v → v
f *** g = λ v → (f v, g v)
g  .  f = λ v → g (f v)
</code></pre>

<p>These building blocks arise in the land of types.</p>

<pre><code>newtype Id a = Id a

data (f :*: g) a = f a :*: g a

newtype (g :. f) a = O (g (f a))
</code></pre>

<p>where <code>Id</code>, <code>f</code> and <code>g</code> are functors.
Sum and a constant functor are also common building blocks:</p>

<pre><code>data (f :+: g) a = InL (f a) | InR (g a)

newtype Const x a = Const x

type Unit = Const () -- one non-⊥ inhabitant
</code></pre>

<h3>Tries as associated type synonym</h3>

<p>Given these standard definitions, we can eliminate the special-purpose data types used, replacing them with our standard functor combinators:</p>

<pre><code>instance HasTrie () where
  type Trie ()  = Id
  trie   f      = Id (f ())
  untrie (Id v) = const v

instance (HasTrie a, HasTrie b) =&gt; HasTrie (Either a b) where
  type Trie (Either a b) = Trie a :*: Trie b
  trie   f           = trie (f . Left) :*: trie (f . Right)
  untrie (ta :*: tb) = untrie ta `either` untrie tb

instance (HasTrie a, HasTrie b) ⇒ HasTrie (a , b) where
  type Trie (a , b) = Trie a :. Trie b
  trie   f      = O (trie (trie . curry f))
  untrie (O tt) = uncurry (untrie . untrie tt)
</code></pre>

<p>At first blush, it might appear that we&#8217;ve simply moved the data type definitions outside of the instances.
However, the extracted functor combinators have other uses, as explored in polytypic programming.
I&#8217;ll point out some of these uses in the next few blog posts.</p>

<h3>Isomorphisms</h3>

<p>Many types are isomorphic variations, and so their corresponding tries can share a common representation.
For instance, triples are isomorphic to nested pairs:</p>

<pre><code>detrip :: (a,b,c) → ((a,b),c)
detrip (a,b,c) = ((a,b),c)

trip :: ((a,b),c) → (a,b,c)
trip ((a,b),c) = (a,b,c)
</code></pre>

<p>A trie for triples can be a a trie for pairs (already defined).
The <code>trie</code> and <code>untrie</code> methods then just perform conversions around the corresponding methods on pairs:</p>

<pre><code>instance (HasTrie a, HasTrie b, HasTrie c) ⇒ HasTrie (a,b,c) where
    type Trie (a,b,c) = Trie ((a,b),c)
    trie f = trie (f . trip)
    untrie t = untrie t . detrip
</code></pre>

<p>All type isomorphisms can use this same pattern.
I don&#8217;t think Haskell is sufficiently expressive to capture this pattern within the language, so I&#8217;ll resort to a C macro.
There are five parameters:</p>

<ul>
<li><code>Context</code>: the instance context;</li>
<li><code>Type</code>: the type whose instance is being defined;</li>
<li><code>IsoType</code>: the isomorphic type;</li>
<li><code>toIso</code>: conversion function <em>to</em> <code>IsoType</code>; and</li>
<li><code>fromIso</code>: conversion function <em>from</em> <code>IsoType</code>.</li>
</ul>

<p>The macro:</p>

<pre><code>#define HasTrieIsomorph(Context,Type,IsoType,toIso,fromIso)  
instance Context ⇒ HasTrie (Type) where {  
  type Trie (Type) = Trie (IsoType);  
  trie f = trie (f . (fromIso));  
  untrie t = untrie t . (toIso);  
}
</code></pre>

<p>Now we can easily define <code>HasTrie</code> instances:</p>

<pre><code>HasTrieIsomorph( (), Bool, Either () ()
               ,  c -&gt; if c then Left () else Right ()
               , either ( () -&gt; True) ( () -&gt; False))

HasTrieIsomorph( (HasTrie a, HasTrie b, HasTrie c), (a,b,c), ((a,b),c)
               , λ (a,b,c) → ((a,b),c), λ ((a,b),c) → (a,b,c))

HasTrieIsomorph( (HasTrie a, HasTrie b, HasTrie c, HasTrie d)
               , (a,b,c,d), ((a,b,c),d)
               , λ (a,b,c,d) → ((a,b,c),d), λ ((a,b,c),d) → (a,b,c,d))
</code></pre>

<p>In most (but not all) cases, the first argument (<code>Context</code>) could simply be that the isomorphic type <code>HasTrie</code>, e.g.,</p>

<pre><code>HasTrieIsomorph( HasTrie ((a,b),c), (a,b,c), ((a,b),c)
               , λ (a,b,c) → ((a,b),c), λ ((a,b),c) → (a,b,c))
</code></pre>

<p>We could define another macro that captures this pattern and requires one fewer argument.
On the other hand, there is merit to keeping the contextual requirements explicit.</p>

<h3>Regular data types</h3>

<p>A regular data type is one in which the recursive uses are at the same type.
Functions over such types are often defined via <em>monomorphic</em> recursion.
Data types that do not satisfy this constraint are called &#8220;<a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.31.3551" title="Paper by Richard Bird and Lambert Meertens">nested</a>&#8220;.</p>

<p>As in several recent generic programming systems, regular data types can be encoded generically through a type class that unwraps one level of functor from a type.
The regular data type is the fixpoint of that functor.
See, e.g., <em><a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.14.6390" title="Paper by Ulf Norell and Patrik Jansson">Polytypic programming in Haskell</a></em>.
Adopting the style of <em><a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.142.4778" title="Paper by Thomas Noort, Alexey Rodriguez, Stefan Holdermans, Johan Jeuring, Bastiaan Heeren">A Lightweight Approach to Datatype-Generic Rewriting</a></em>,</p>

<pre><code>class Functor (PF t) ⇒ Regular t where
  type PF t :: * → *
  wrap   :: PF t t → t
  unwrap :: t → PF t t
</code></pre>

<p>Here &#8220;<code>PF</code>&#8221; stands for &#8220;pattern functor&#8221;.</p>

<p>The pattern functors can be constructed out of the functor combinators above.
For instance, a list at the top level is either empty or a value and a list.
Translating this description:</p>

<pre><code>instance Regular [a] where
  type PF [a] = Unit :+: Const a :*: Id

  unwrap []     = InL (Const ())
  unwrap (a:as) = InR (Const a :*: Id as)

  wrap (InL (Const ()))          = []
  wrap (InR (Const a :*: Id as)) = a:as
</code></pre>

<p>As another example, consider rose trees ([<code>Data.Tree</code>][]):</p>

<pre><code>data Tree  a = Node a [Tree a]

instance Regular (Tree a) where

  type PF (Tree a) = Const a :*: []

  unwrap (Node a ts) = Const a :*: ts

  wrap (Const a :*: ts) = Node a ts
</code></pre>

<p>Regular types allow for even more succinct <code>HasTrie</code> instance implementations.
Specialize <code>HasTrieIsomorph</code> further:</p>

<pre><code>#define HasTrieRegular(Context,Type)  
HasTrieIsomorph(Context, Type, PF (Type) (Type) , unwrap, wrap)
</code></pre>

<p>For instance, for lists and rose trees:</p>

<pre><code>HasTrieRegular(HasTrie a, [a])
HasTrieRegular(HasTrie a, Tree a)
</code></pre>

<p>The <code>HasTrieRegular</code> macro could be specialized even further for single-parameter polymorphic data types:</p>

<pre><code>#define HasTrieRegular1(TypeCon) HasTrieRegular(HasTrie a, TypeCon a)

HasTrieRegular1([])
HasTrieRegular1(Tree)
</code></pre>

<p>You might wonder if I&#8217;m cheating here, by claiming very simple trie specifications when I&#8217;m really just shuffling code around.
After all, the complexity removed from <code>HasTrie</code> instances shows up in <code>Regular</code> instances.
The win in making this shuffle is that <code>Regular</code> is handy for other purposes, as illustrated in <em><a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.140.2412" title="Paper by Alexey Rodriguez, Stefan Holdermans, Andres Löh, and Johan Jeuring">Generic programming with fixed points for mutually recursive datatypes</a></em> (including <code>fold</code>, <code>unfold</code>, and <code>fmap</code>).
(More examples in <em><a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.142.4778" title="Paper by Thomas Noort, Alexey Rodriguez, Stefan Holdermans, Johan Jeuring, Bastiaan Heeren">A Lightweight Approach to Datatype-Generic Rewriting</a></em>.)</p>

<h3>Trouble</h3>

<p>Sadly, these elegant trie definitions have a problem.
Trying to compile them leads to a error message from GHC.
For instance,</p>

<pre><code>Nested type family application
  in the type family application: Trie (PF [a] [a])
(Use -XUndecidableInstances to permit this)
</code></pre>

<p>Adding <code>UndecidableInstances</code> silences this error message, but leads to nontermination in the compiler.</p>

<p>Expanding definitions, I can see the likely cause of nontermination.
The definition in terms of a type family allows an infinite type to sneak through, and I guess GHC&#8217;s type checker is unfolding infinitely.</p>

<p>As a simpler example:</p>

<pre><code>{-# LANGUAGE TypeFamilies, UndecidableInstances #-}

type family List a :: *

type instance List a = Either () (a, List a)

-- Hangs ghc 6.12.1:
nil :: List a
nil = Left ()
</code></pre>

<h3>A solution</h3>

<p>Since GHC&#8217;s type-checker cannot handle directly recursive types, perhaps we can use a standard avoidance strategy, namely introducing a <code>newtype</code> or <code>data</code> definition to break the cycle.
For instance, as a trie for <code>[a]</code>, we got into trouble by using the trie of the unwrapped form of <code>[a]</code>, i.e., <code>Trie (PF [a] [a])</code>.
So instead,</p>

<pre><code>newtype ListTrie a v = ListTrie (Trie (PF [a] [a]) v)
</code></pre>

<p>which is to say</p>

<pre><code>newtype ListTrie a v = ListTrie (PF [a] [a] :→: v)
</code></pre>

<p>Now <code>wrap</code> and <code>unwrap</code> as before, and add &amp; remove <code>ListTrie</code> as needed:</p>

<pre><code>instance HasTrie a ⇒ HasTrie [a] where
  type Trie [a] = ListTrie a
  trie f = ListTrie (trie (f . wrap))
  untrie (ListTrie t) = untrie t . unwrap
</code></pre>

<p>Again, abstract the boilerplate code into a C macro:</p>

<pre><code>#define HasTrieRegular(Context,Type,TrieType,TrieCon) 
newtype TrieType v = TrieCon (PF (Type) (Type) :→: v); 
instance Context ⇒ HasTrie (Type) where { 
  type Trie (Type) = TrieType; 
  trie f = TrieCon (trie (f . wrap)); 
  untrie (TrieCon t) = untrie t . unwrap; 
}
</code></pre>

<p>For instance,</p>

<pre><code>HasTrieRegular(HasTrie a, [a] , ListTrie a, ListTrie)
HasTrieRegular(HasTrie a, Tree, TreeTrie a, TreeTrie)
</code></pre>

<p>Again, simplify a bit with a specialization to unary regular types:</p>

<pre><code>#define HasTrieRegular1(TypeCon,TrieCon) 
HasTrieRegular(HasTrie a, TypeCon a, TrieCon a, TrieCon)
</code></pre>

<p>And then use the following declarations instead:</p>

<pre><code>HasTrieRegular1([]  , ListTrie)
HasTrieRegular1(Tree, TreeTrie)
</code></pre>

<p>Similarly for binary etc as needed.</p>

<p>The second macro parameter (<code>TrieCon</code>) is just a name, which I don&#8217;t to be used other than in the macro-generated code.
It could be eliminated, if there were a way to gensym the name.
Perhaps with Template Haskell?</p>

<h3>Conclusion</h3>

<p>I like the elegance of constructing memo tries in terms of common functor combinators.
Standard pattern functors allow for extremely succinct trie specifications for regular data types.
However, these specifications lead to nontermination of the type checker, which can then be avoided by the standard trick of introducing a newtype to break type recursion.
As often, this trick brings introduces some clumsiness.
Perhaps the problem can also be avoided by using a formulation using <em>bifunctors</em>, as in <em><a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.60.5251" title="Paper by Jeremy Gibbons">Design Patterns as Higher-Order Datatype-Generic Programs</a></em> and <em><a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.14.6390" title="Paper by Ulf Norell and Patrik Jansson">Polytypic programming in Haskell</a></em>, which allows the fixed-point nature of regular data types to be exposed.</p>
<p><a href="http://conal.net/blog/?flattrss_redirect&amp;id=117&amp;md5=32e9a954390ac5cfba0f5fb929af467d"><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/elegant-memoization-with-higher-order-types/feed</wfw:commentRss>
		<slash:comments>6</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%2Felegant-memoization-with-higher-order-types&amp;language=en_GB&amp;category=text&amp;title=Elegant+memoization+with+higher-order+types&amp;description=A+while+back%2C+I+got+interested+in+functional+memoization%2C+especially+after+seeing+some+code+from+Spencer+Janssen+using+the+essential+idea+of+Ralf+Hinze%26%238217%3Bs+paper+Generalizing+Generalized+Tries.+The+blog...&amp;tags=functor%2Cisomorphism%2Cmemoization%2Ctrie%2Cblog" type="text/html" />
	</item>
		<item>
		<title>Paper: Beautiful differentiation</title>
		<link>http://conal.net/blog/posts/paper-beautiful-differentiation</link>
		<comments>http://conal.net/blog/posts/paper-beautiful-differentiation#comments</comments>
		<pubDate>Tue, 24 Feb 2009 08:05:10 +0000</pubDate>
		<dc:creator><![CDATA[Conal]]></dc:creator>
				<category><![CDATA[Functional programming]]></category>
		<category><![CDATA[applicative functor]]></category>
		<category><![CDATA[beautiful code]]></category>
		<category><![CDATA[calculus on manifolds]]></category>
		<category><![CDATA[derivative]]></category>
		<category><![CDATA[functor]]></category>
		<category><![CDATA[linear map]]></category>
		<category><![CDATA[math]]></category>
		<category><![CDATA[paper]]></category>

		<guid isPermaLink="false">http://conal.net/blog/?p=85</guid>
		<description><![CDATA[I have another paper draft for submission to ICFP 2009. This one is called Beautiful differentiation, The paper is a culmination of the several posts I&#8217;ve written on derivatives and automatic differentiation (AD). I&#8217;m happy with how the derivation keeps getting simpler. Now I&#8217;ve boiled extremely general higher-order AD down to a Functor and Applicative [&#8230;]]]></description>
				<content:encoded><![CDATA[<!-- 

Title: Paper: Beautiful differentiation

Tags: derivative, functor, applicative functor, beautiful code, calculus on manifolds, linear map, math, paper

URL: http://conal.net/blog/posts/paper-beautiful-differentiation/

-->

<!-- references -->

<!-- teaser -->

<p>I have another paper draft for submission to <a href="http://www.cs.nott.ac.uk/~gmh/icfp09.html" title="conference page">ICFP 2009</a>.
This one is called <em><a href="http://conal.net/papers/beautiful-differentiation" title="paper">Beautiful differentiation</a></em>, 
The paper is a culmination of the <a href="http://conal.net/blog/tag/derivative/">several posts</a> I&#8217;ve written on derivatives and automatic differentiation (AD).
I&#8217;m happy with how the derivation keeps getting simpler.
Now I&#8217;ve boiled extremely general higher-order AD down to a <code>Functor</code> and <code>Applicative</code> morphism.</p>

<p>I&#8217;d love to get some readings and feedback.
I&#8217;m a bit over the page the limit, so I&#8217;ll have to do some trimming before submitting.</p>

<p>The abstract:</p>

<blockquote>
  <p>Automatic differentiation (AD) is a precise, efficient, and convenient
  method for computing derivatives of functions. Its implementation can be
  quite simple even when extended to compute all of the higher-order
  derivatives as well. The higher-dimensional case has also been tackled,
  though with extra complexity. This paper develops an implementation of
  higher-dimensional, higher-order differentiation in the extremely
  general and elegant setting of <em>calculus on manifolds</em> and derives that
  implementation from a simple and precise specification.</p>
  
  <p>In order to motivate and discover the implementation, the paper poses
  the question &#8220;What does AD mean, independently of implementation?&#8221; An
  answer arises in the form of <em>naturality</em> of sampling a function and its
  derivative. Automatic differentiation flows out of this naturality
  condition, together with the chain rule. Graduating from first-order to
  higher-order AD corresponds to sampling all derivatives instead of just
  one. Next, the notion of a derivative is generalized via the notions of
  vector space and linear maps. The specification of AD adapts to this
  elegant and very general setting, which even <em>simplifies</em> the
  development.</p>
</blockquote>

<p>You can <a href="http://conal.net/papers/beautiful-differentiation" title="paper">get the paper and see current errata here</a>.</p>

<p>The submission deadline is March 2, so comments before then are most helpful to me.</p>

<p>Enjoy, and thanks!</p>

<!--
**Edits**:

* 2009-02-09: just fiddling around
-->
<p><a href="http://conal.net/blog/?flattrss_redirect&amp;id=85&amp;md5=2f6565c8f001a5925c3e6dbd29158c37"><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/paper-beautiful-differentiation/feed</wfw:commentRss>
		<slash:comments>22</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%2Fpaper-beautiful-differentiation&amp;language=en_GB&amp;category=text&amp;title=Paper%3A+Beautiful+differentiation&amp;description=I+have+another+paper+draft+for+submission+to+ICFP+2009.+This+one+is+called+Beautiful+differentiation%2C+The+paper+is+a+culmination+of+the+several+posts+I%26%238217%3Bve+written+on+derivatives+and...&amp;tags=applicative+functor%2Cbeautiful+code%2Ccalculus+on+manifolds%2Cderivative%2Cfunctor%2Clinear+map%2Cmath%2Cpaper%2Cblog" type="text/html" />
	</item>
	</channel>
</rss>
