<?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; tree</title>
	<atom:link href="http://conal.net/blog/tag/tree/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>From tries to trees</title>
		<link>http://conal.net/blog/posts/from-tries-to-trees</link>
		<comments>http://conal.net/blog/posts/from-tries-to-trees#comments</comments>
		<pubDate>Tue, 01 Feb 2011 18:36:32 +0000</pubDate>
		<dc:creator><![CDATA[Conal]]></dc:creator>
				<category><![CDATA[Functional programming]]></category>
		<category><![CDATA[number]]></category>
		<category><![CDATA[tree]]></category>
		<category><![CDATA[trie]]></category>
		<category><![CDATA[vector]]></category>

		<guid isPermaLink="false">http://conal.net/blog/?p=314</guid>
		<description><![CDATA[This post is the last of a series of six relating numbers, vectors, and trees, revolving around the themes of static size-typing and memo tries. We&#8217;ve seen that length-typed vectors form a trie for bounded numbers, and can handily represent numbers as well. We&#8217;ve also seen that n-dimensional vectors themselves have an elegant trie, which [&#8230;]]]></description>
				<content:encoded><![CDATA[<!-- teaser -->

<p
>This post is the last of a series of six relating numbers, vectors, and trees, revolving around the themes of static size-typing and <a href="http://conal.net/blog/tag/memoization/" title="Posts on memoization"
  >memo</a
  > <a href="http://conal.net/blog/tag/trie/" title="Posts on tries"
  >tries</a
  >. We&#8217;ve seen that length-typed vectors form a trie for bounded numbers, and can handily represent numbers as well. We&#8217;ve also seen that <span class="math"
  ><em
    >n</em
    ></span
  >-dimensional vectors themselves have an elegant trie, which is the <span class="math"
  ><em
    >n</em
    ></span
  >-ary composition of the element type&#8217;s trie functor:</p
>

<pre class="sourceCode haskell"
><code
  ><span class="kw"
    >type</span
    > <span class="dt"
    >VTrie</span
    > n a <span class="fu"
    >=</span
    > <span class="dt"
    >Trie</span
    > a <span class="fu"
    >:^</span
    > n <br
     /></code
  ></pre
>

<p
>where for any functor <code
  >f</code
  > and natural number type <code
  >n</code
  >,</p
>

<pre class="sourceCode haskell"
><code
  >f <span class="fu"
    >:^</span
    > n <span class="dt"
    >&#8773;</span
    > f &#8728; &#8943; &#8728; f  <span class="co"
    >-- (n times)</span
    ><br
     /></code
  ></pre
>

<p
>This final post in the series places this elegant mechanism of <span class="math"
  ><em
    >n</em
    ></span
  >-ary functor composition into a familiar &amp; useful context, namely trees. Again, type-encoded Peano numbers are central. Just as <code
  >BNat</code
  > uses these number types to (statically) bound natural numbers (e.g., for a vector index or a numerical digit), and <code
  >Vec</code
  > uses number types to capture vector <em
  >length</em
  >, we'll next use number types to capture tree <em
  >depth</em
  >.</p
>

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

<ul
><li
  >2011-02-02: Changes thanks to comments from Sebastian Fischer<ul
    ><li
      >Added note about number representations and leading zeros (without size-typing).</li
      ><li
      >Added pointer to <a href="http://conal.net/blog/posts/memoizing-polymorphic-functions-via-unmemoization/" title="blog post"
    ><em
      >Memoizing polymorphic functions via unmemoization</em
      ></a
    > for derivation of <code
    >Tree d a &#8773; [d] &#8594; a</code
    >.</li
      ><li
      >Fixed signatures for some <code
    >Branch</code
    > variants, bringing type parameter <code
    >a</code
    > into parens.</li
      ><li
      >Clarification about number of <code
    >VecTree</code
    > vs pairing constructors in remarks on left- vs right-folded trees.</li
      ></ul
    ></li
  ><li
  >2011-02-06: Fixed link to <a href="http://www.eecs.usma.edu/webs/people/okasaki/pubs.html#icfp99" title="Paper by Chris Okasaki"
    ><em
      >From Fast Exponentiation to Square Matrices</em
      ></a
    >.</li
  ></ul
>

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

<div id="infinite-trees"
><h3
  >Infinite trees</h3
  ><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 played with a number of container types, looking at which ones are tries over what domain types. I referred to these domain types as &quot;index types&quot; for the container type. One such container was a type of infinite binary trees with values at every node:</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >data</span
      > <span class="dt"
      >BinTree</span
      > a <span class="fu"
      >=</span
      > <span class="dt"
      >BinTree</span
      > a (<span class="dt"
      >BinTree</span
      > a) (<span class="dt"
      >BinTree</span
      > a)<br
       /></code
    ></pre
  ><p
  >By the usual exponent laws, this <code
    >BinTree</code
    > functor is (isomorphic to) the functor of tries over a type of binary natural numbers formulated as follows:</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >data</span
      > <span class="dt"
      >BinNat</span
      > <span class="fu"
      >=</span
      > <span class="dt"
      >Zero</span
      > <span class="fu"
      >|</span
      > <span class="dt"
      >Even</span
      > <span class="dt"
      >BinNat</span
      > <span class="fu"
      >|</span
      > <span class="dt"
      >Odd</span
      > <span class="dt"
      >BinNat</span
      ><br
       /></code
    ></pre
  ><p
  >As a variation on this <code
    >BinTree</code
    >, we can replace the two subtrees with a <em
    >pair</em
    > of subtrees:</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >data</span
      > <span class="dt"
      >BinTree</span
      > a <span class="fu"
      >=</span
      > <span class="dt"
      >BinTree</span
      > a (<span class="dt"
      >Pair</span
      > (<span class="dt"
      >BinTree</span
      > a))<br
       /></code
    ></pre
  ><p
  >Where <code
    >Pair</code
    > could be defined as</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >data</span
      > <span class="dt"
      >Pair</span
      > a <span class="fu"
      >=</span
      > <span class="dt"
      >Pair</span
      > a a<br
       /></code
    ></pre
  ><p
  >or, using <a href="http://conal.net/blog/posts/elegant-memoization-with-higher-order-types/" title="blog post"
    >functor combinators</a
    >,</p
  ><pre class="sourceCode haskell"
  ><code
    ><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
      ><br
       /></code
    ></pre
  ><p
  >The reformulation of <code
    >BinTree</code
    > leads to a slightly different representation for our index type, a little-endian list of bits:</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >data</span
      > <span class="dt"
      >BinNat</span
      > <span class="fu"
      >=</span
      > <span class="dt"
      >Zero</span
      > <span class="fu"
      >|</span
      > <span class="dt"
      >NonZero</span
      > <span class="dt"
      >Bool</span
      > <span class="dt"
      >BinNat</span
      ><br
       /></code
    ></pre
  ><p
  >or simply</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >type</span
      > <span class="dt"
      >BinNat</span
      > <span class="fu"
      >=</span
      > [<span class="dt"
      >Bool</span
      >]<br
       /></code
    ></pre
  ><p
  >Note that <code
    >Bool</code
    > is the index type for <code
    >Pair</code
    > (and conversely, <code
    >Pair</code
    > is the trie for <code
    >Bool</code
    >), which suggests that we play this same trick for <em
    >all</em
    > index types and their corresponding trie functors. Generalizing,</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >data</span
      > <span class="dt"
      >Tree</span
      > d a <span class="fu"
      >=</span
      > <span class="dt"
      >Tree</span
      > a (d &#8603; <span class="dt"
      >Tree</span
      > d a)<br
       /></code
    ></pre
  ><p
  >where <code
    >k &#8603; v</code
    > is short for <code
    >Trie k v</code
    >, and <code
    >Trie k</code
    > is the trie functor associated with the type <code
    >k</code
    >. See <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
  ><p
  >These generalized trees are indexed by little-endian natural numbers over a &quot;digit&quot; type <code
    >d</code
    >:</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="dt"
      >Tree</span
      > d a <span class="dt"
      >&#8773;</span
      > [d] &#8594; a<br
       /></code
    ></pre
  ><p
  >which is to say that <code
    >Tree d</code
    > is a trie for <code
    >[d]</code
    >. See <a href="http://conal.net/blog/posts/memoizing-polymorphic-functions-via-unmemoization/" title="blog post"
    ><em
      >Memoizing polymorphic functions via unmemoization</em
      ></a
    > for a derivation.</p
  ><p
  >Note that all of these number representations have a serious problem, which is that they distinguish between number representations that differ only by leading zeros. The size-typed versions do not have this problem.</p
  ></div
>

<div id="finite-trees"
><h3
  >Finite trees</h3
  ><p
  >The reason I chose infinite trees was that the finite tree types I knew of have choice-points/alternatives, and so are isomorphic to sums. I don't know of trie-construction techniques that synthesize sums.</p
  ><p
  >Can we design a tree type that is both finite and choice-free? We've already tackled a similar challenge above with lists earlier in previous posts.</p
  ><p
  >In <a href="http://conal.net/blog/posts/fixing-lists/" title="blog post"
    ><em
      >Fixing lists</em
      ></a
    >, I wanted to &quot;fix&quot; lists, in the sense of eliminating the choice points in the standard type <code
    >[a]</code
    > so that the result could be a trie. Doing so led to the type <code
    >Vec n a</code
    >, which appears to have choice points, due to the two constructors <code
    >ZVec</code
    > and <code
    >(:&lt;)</code
    >, but for any given <code
    >n</code
    >, at most one constructor is applicable. (For this reason, regular algebraic data types are inadequate.) For handy review,</p
  ><pre class="sourceCode haskell"
  ><code
    ><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
  >Let's try the same trick with trees, fixing depth instead length, to get depth-typed binary trees:</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >data</span
      > <span class="dt"
      >BinTree</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"
      >Leaf</span
      >   <span class="dv"
      >&#8759;</span
      > a                         &#8594; <span class="dt"
      >BinTree</span
      > <span class="dt"
      >Z</span
      >     a<br
       />  <span class="dt"
      >Branch</span
      > <span class="dv"
      >&#8759;</span
      > <span class="dt"
      >BinTree</span
      > n a &#8594; <span class="dt"
      >BinTree</span
      > n a &#8594; <span class="dt"
      >BinTree</span
      > (<span class="dt"
      >S</span
      > n) a<br
       /></code
    ></pre
  ><p
  >Again, we can replace the two subtrees with a single pair of subtrees in the <code
    >Branch</code
    > constructor::</p
  ><pre class="sourceCode haskell"
  ><code
    >  <span class="dt"
      >Branch</span
      > <span class="dv"
      >&#8759;</span
      > <span class="dt"
      >Pair</span
      > (<span class="dt"
      >BinTree</span
      > n) a &#8594; <span class="dt"
      >BinTree</span
      > (<span class="dt"
      >S</span
      > n) a<br
       /></code
    ></pre
  ><p
  >Or, recalling that <code
    >Bool</code
    > is the index type for <code
    >Pair</code
    >:</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >data</span
      > <span class="dt"
      >BinTree</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"
      >Leaf</span
      >   <span class="dv"
      >&#8759;</span
      >                    a &#8594; <span class="dt"
      >BinTree</span
      > <span class="dt"
      >Z</span
      >     a<br
       />  <span class="dt"
      >Branch</span
      > <span class="dv"
      >&#8759;</span
      > (<span class="dt"
      >Bool</span
      > &#8603; <span class="dt"
      >BinTree</span
      > n a) &#8594; <span class="dt"
      >BinTree</span
      > (<span class="dt"
      >S</span
      > n) a<br
       /></code
    ></pre
  ><p
  >The use of <code
    >Bool</code
    > is rather ad hoc. Its useful property is isomorphism with <code
    >1 + 1</code
    >, whose corresponding trie functor is <code
    >Id + Id</code
    >, i.e., <code
    >Pair</code
    >. In the post <a href="http://conal.net/blog/posts/type-bounded-numbers/" title="blog post"
    ><em
      >Type-bounded numbers</em
      ></a
    >, we saw another, more systematic, type isomorphic to <code
    >1 + 1</code
    >, which is <code
    >BNat TwoT</code
    > (i.e., <code
    >BNat (S (S Z))</code
    >), which is the type of natural numbers less than two.</p
  ><pre class="sourceCode haskell"
  ><code
    >  <span class="dt"
      >Branch</span
      > <span class="dv"
      >&#8759;</span
      > (<span class="dt"
      >BNat</span
      > <span class="dt"
      >TwoT</span
      > &#8603; <span class="dt"
      >BinTree</span
      > n a) &#8594; <span class="dt"
      >BinTree</span
      > (<span class="dt"
      >S</span
      > n) a<br
       /></code
    ></pre
  ><p
  >This replacement suggests a generalization from binary trees to <span class="math"
    ><em
      >b</em
      ></span
    >-ary trees (i.e., having branch factor <span class="math"
    ><em
      >b</em
      ></span
    >).</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >data</span
      > <span class="dt"
      >VecTree</span
      > <span class="dv"
      >&#8759;</span
      > <span class="fu"
      >*</span
      > &#8594; <span class="fu"
      >*</span
      > &#8594; <span class="fu"
      >*</span
      > &#8594; <span class="fu"
      >*</span
      > <span class="kw"
      >where</span
      ><br
       />  <span class="dt"
      >Leaf</span
      >   <span class="dv"
      >&#8759;</span
      >                        a &#8594; <span class="dt"
      >VecTree</span
      > b <span class="dt"
      >Z</span
      >     a<br
       />  <span class="dt"
      >Branch</span
      > <span class="dv"
      >&#8759;</span
      > (<span class="dt"
      >BNat</span
      > b &#8603; <span class="dt"
      >VecTree</span
      > b n a) &#8594; <span class="dt"
      >VecTree</span
      > b (<span class="dt"
      >S</span
      > n) a<br
       /></code
    ></pre
  ><p
  >Recall that the motivation for <code
    >BNat b</code
    > was as an index type for <code
    >Vec b</code
    >, which is to say that <code
    >Vec b</code
    > turned out to be the trie functor for the type <code
    >BNat b</code
    >. With this relationship in mind, the <code
    >Branch</code
    > type is equivalent to</p
  ><pre class="sourceCode haskell"
  ><code
    >  <span class="dt"
      >Branch</span
      > <span class="dv"
      >&#8759;</span
      > <span class="dt"
      >Vec</span
      > b (<span class="dt"
      >VecTree</span
      > b n a) &#8594; <span class="dt"
      >VecTree</span
      > b (<span class="dt"
      >S</span
      > n) a<br
       /></code
    ></pre
  ><p
  >Unsurprisingly then, a <span class="math"
    ><em
      >b</em
      ></span
    >-ary tree is either a single leaf value or a branch node containing <span class="math"
    ><em
      >b</em
      ></span
    > subtrees. Also, the depth of a leaf is zero, and the depth of a branch node containing <span class="math"
    ><em
      >b</em
      ></span
    > subtrees each of of depth <span class="math"
    ><em
      >n</em
      ></span
    > is <span class="math"
    ><em
      >n</em
      > + 1</span
    >.</p
  ><p
  >We can also generalize this <code
    >VecTree</code
    > type by replacing <code
    >Vec b</code
    > with an arbitrary functor <code
    >f</code
    >:</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >data</span
      > <span class="dt"
      >FTree</span
      > <span class="dv"
      >&#8759;</span
      > (<span class="fu"
      >*</span
      > &#8594; <span class="fu"
      >*</span
      >) &#8594; <span class="fu"
      >*</span
      > &#8594; <span class="fu"
      >*</span
      > &#8594; <span class="fu"
      >*</span
      > <span class="kw"
      >where</span
      ><br
       />  <span class="dt"
      >Leaf</span
      >   <span class="dv"
      >&#8759;</span
      >               a &#8594; <span class="dt"
      >FTree</span
      > f <span class="dt"
      >Z</span
      >     a<br
       />  <span class="dt"
      >Branch</span
      > <span class="dv"
      >&#8759;</span
      > f (<span class="dt"
      >FTree</span
      > f n) a &#8594; <span class="dt"
      >FTree</span
      > f (<span class="dt"
      >S</span
      > n) a<br
       /><br
       /><span class="kw"
      >type</span
      > <span class="dt"
      >VecTree</span
      > b <span class="fu"
      >=</span
      > <span class="dt"
      >FTree</span
      > (<span class="dt"
      >Vec</span
      > b)<br
       /></code
    ></pre
  ><p
  >Better yet, introduce an intermediate generalization, using the property that <code
    >Vec b &#8801; Trie (BNat b)</code
    >:</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >type</span
      > <span class="dt"
      >TrieTree</span
      > i <span class="fu"
      >=</span
      > <span class="dt"
      >FTree</span
      > (<span class="dt"
      >Trie</span
      > i)<br
       /><br
       /><span class="kw"
      >type</span
      > <span class="dt"
      >VecTree</span
      > b <span class="fu"
      >=</span
      > <span class="dt"
      >TrieTree</span
      > (<span class="dt"
      >BNat</span
      > b)<br
       /></code
    ></pre
  ><p
  >With the exception of the most general form (<code
    >FTree</code
    >), these trees are also tries.</p
  ></div
>

<div id="generalizing-and-inverting-our-trees"
><h3
  >Generalizing and inverting our trees</h3
  ><p
  >The <code
    >FTree</code
    > type looks very like another data type that came up above, namely right-folded <span class="math"
    ><em
      >b</em
      ></span
    >-ary functor composition:</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >data</span
      > (<span class="fu"
      >:^</span
      >) <span class="dv"
      >&#8759;</span
      > (<span class="fu"
      >*</span
      > &#8594; <span class="fu"
      >*</span
      >) &#8594; <span class="fu"
      >*</span
      > &#8594; (<span class="fu"
      >*</span
      > &#8594; <span class="fu"
      >*</span
      >) <span class="kw"
      >where</span
      ><br
       />  <span class="dt"
      >ZeroC</span
      > <span class="dv"
      >&#8759;</span
      >             a  &#8594; (f <span class="fu"
      >:^</span
      > <span class="dt"
      >Z</span
      >    ) a<br
       />  <span class="dt"
      >SuccC</span
      > <span class="dv"
      >&#8759;</span
      > f ((f <span class="fu"
      >:^</span
      > n) a) &#8594; (f <span class="fu"
      >:^</span
      > (<span class="dt"
      >S</span
      > n)) a<br
       /></code
    ></pre
  ><p
  >These two types are not just similar; they're identical (different only in naming, i.e., <span class="math"
    >α</span
    >-equivalent), so we can use <code
    >f :^ n</code
    > in place of <code
    >FTree f n</code
    >:</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >type</span
      > <span class="dt"
      >TrieTree</span
      > i <span class="fu"
      >=</span
      > (<span class="fu"
      >:^</span
      >) (<span class="dt"
      >Trie</span
      > i)<br
       /></code
    ></pre
  ><p
  >Instead of <em
    >right-folded</em
    > functor composition, we could go with left-folded. What difference would it make to our notions of <span class="math"
    ><em
      >b</em
      ></span
    >-ary or binary trees?</p
  ><p
  >First look at (right-folded) <code
    >BinTree</code
    >:</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >data</span
      > <span class="dt"
      >BinTree</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"
      >Leaf</span
      >   <span class="dv"
      >&#8759;</span
      >                  a &#8594; <span class="dt"
      >BinTree</span
      > <span class="dt"
      >Z</span
      >     a<br
       />  <span class="dt"
      >Branch</span
      > <span class="dv"
      >&#8759;</span
      > <span class="dt"
      >Pair</span
      > (<span class="dt"
      >BinTree</span
      > n) a &#8594; <span class="dt"
      >BinTree</span
      > (<span class="dt"
      >S</span
      > n) a<br
       /></code
    ></pre
  ><p
  >Equivalently,</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >data</span
      > <span class="dt"
      >BinTree</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"
      >Leaf</span
      >   <span class="dv"
      >&#8759;</span
      >                         a &#8594; <span class="dt"
      >BinTree</span
      > <span class="dt"
      >Z</span
      >     a<br
       />  <span class="dt"
      >Branch</span
      > <span class="dv"
      >&#8759;</span
      > (<span class="dt"
      >BNat</span
      > <span class="dt"
      >TwoT</span
      > &#8603; <span class="dt"
      >BinTree</span
      > n a) &#8594; <span class="dt"
      >BinTree</span
      > (<span class="dt"
      >S</span
      > n) a<br
       /></code
    ></pre
  ><p
  >With left-folding, the <code
    >Branch</code
    > constructors would be</p
  ><pre class="sourceCode haskell"
  ><code
    >  <span class="dt"
      >Branch</span
      > <span class="dv"
      >&#8759;</span
      > <span class="dt"
      >BinTree</span
      > n (<span class="dt"
      >Pair</span
      > a) &#8594; <span class="dt"
      >BinTree</span
      > (<span class="dt"
      >S</span
      > n) a<br
       /></code
    ></pre
  ><p
  >or</p
  ><pre class="sourceCode haskell"
  ><code
    >  <span class="dt"
      >Branch</span
      > <span class="dv"
      >&#8759;</span
      > <span class="dt"
      >BinTree</span
      > n (<span class="dt"
      >BNat</span
      > <span class="dt"
      >TwoT</span
      > &#8603; a) &#8594; <span class="dt"
      >BinTree</span
      > (<span class="dt"
      >S</span
      > n) a<br
       /></code
    ></pre
  ><p
  >Then (right-folded) <code
    >VecTree</code
    >:</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >data</span
      > <span class="dt"
      >VecTree</span
      > <span class="dv"
      >&#8759;</span
      > <span class="fu"
      >*</span
      > &#8594; <span class="fu"
      >*</span
      > &#8594; <span class="fu"
      >*</span
      > &#8594; <span class="fu"
      >*</span
      > <span class="kw"
      >where</span
      ><br
       />  <span class="dt"
      >Leaf</span
      >   <span class="dv"
      >&#8759;</span
      >                        a &#8594; <span class="dt"
      >VecTree</span
      > b <span class="dt"
      >Z</span
      >     a<br
       />  <span class="dt"
      >Branch</span
      > <span class="dv"
      >&#8759;</span
      > (<span class="dt"
      >BNat</span
      > b &#8603; <span class="dt"
      >VecTree</span
      > b n a) &#8594; <span class="dt"
      >VecTree</span
      > b (<span class="dt"
      >S</span
      > n) a<br
       /></code
    ></pre
  ><p
  >Equivalently,</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >data</span
      > <span class="dt"
      >VecTree</span
      > <span class="dv"
      >&#8759;</span
      > <span class="fu"
      >*</span
      > &#8594; <span class="fu"
      >*</span
      > &#8594; <span class="fu"
      >*</span
      > &#8594; <span class="fu"
      >*</span
      > <span class="kw"
      >where</span
      ><br
       />  <span class="dt"
      >Leaf</span
      >   <span class="dv"
      >&#8759;</span
      >                    a  &#8594; <span class="dt"
      >VecTree</span
      > b <span class="dt"
      >Z</span
      >     a<br
       />  <span class="dt"
      >Branch</span
      > <span class="dv"
      >&#8759;</span
      > <span class="dt"
      >Vec</span
      > b (<span class="dt"
      >VecTree</span
      > b n a) &#8594; <span class="dt"
      >VecTree</span
      > b (<span class="dt"
      >S</span
      > n) a<br
       /></code
    ></pre
  ><p
  >With left-folding:</p
  ><pre class="sourceCode haskell"
  ><code
    >  <span class="dt"
      >Branch</span
      > <span class="dv"
      >&#8759;</span
      > <span class="dt"
      >VecTree</span
      > b n (<span class="dt"
      >BNat</span
      > b &#8603; a) &#8594; <span class="dt"
      >VecTree</span
      > b (<span class="dt"
      >S</span
      > n) a<br
       /></code
    ></pre
  ><p
  >or</p
  ><pre class="sourceCode haskell"
  ><code
    >  <span class="dt"
      >Branch</span
      > <span class="dv"
      >&#8759;</span
      > <span class="dt"
      >VecTree</span
      > b n (<span class="dt"
      >Vec</span
      > b a) &#8594; <span class="dt"
      >VecTree</span
      > b (<span class="dt"
      >S</span
      > n) a<br
       /></code
    ></pre
  ><p
  >In shifting from right- to left-folding, our tree structuring becomes inverted. Now a &quot;<span class="math"
    ><em
      >b</em
      ></span
    >-ary&quot; tree really has only <em
    >one</em
    > subtree per branch node, not <span class="math"
    ><em
      >b</em
      ></span
    > subtrees.</p
  ><p
  >For instance, right-folded a binary tree of depth two might look like</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="dt"
      >Branch</span
      > (<span class="dt"
      >Branch</span
      > (<span class="dt"
      >Leaf</span
      > <span class="dv"
      >0</span
      >, <span class="dt"
      >Leaf</span
      > <span class="dv"
      >1</span
      >), <span class="dt"
      >Branch</span
      > (<span class="dt"
      >Leaf</span
      > <span class="dv"
      >2</span
      >, <span class="dt"
      >Leaf</span
      > <span class="dv"
      >3</span
      >))<br
       /></code
    ></pre
  ><p
  >For readability, I'm using normal pairs instead of 2-vectors or <code
    >Pair</code
    > pairs here. In contrast, the corresponding left-folded a binary tree would look like</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="dt"
      >Branch</span
      > (<span class="dt"
      >Branch</span
      > (<span class="dt"
      >Leaf</span
      > ((<span class="dv"
      >0</span
      >,<span class="dv"
      >1</span
      >),(<span class="dv"
      >2</span
      >,<span class="dv"
      >3</span
      >))))<br
       /></code
    ></pre
  ><p
  >Note that the <code
    >VecTree</code
    > constructors are in a linear chain, forming an outer shell, and the number of such constructors is the one more than the depth, and hence logarithmic in the number of leaves. The right-folded form has <code
    >VecTree</code
    > constructors scattered throughout the tree, and the number of such constructors is exponential in the depth, and hence linear in the number of leaves. (As Sebastian Fischer pointed out, however, the number of <em
    >pairing</em
    > constructors is not reduced in the left-folded form.)</p
  ><p
  >For more examples of this sort of inversion, see Chris Okasaki's gem of a paper <a href="http://www.eecs.usma.edu/webs/people/okasaki/pubs.html#icfp99" title="Paper by Chris Okasaki"
    ><em
      >From Fast Exponentiation to Square Matrices</em
      ></a
    >.</p
  ></div
>

<div id="what-sort-of-trees-do-we-have"
><h3
  >What sort of trees do we have?</h3
  ><p
  >I pulled a bit of a bait-and-switch above in reformulating trees. The initial infinite tree type had values <em
    >and</em
    > branching at every node:</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >data</span
      > <span class="dt"
      >BinTree</span
      > a <span class="fu"
      >=</span
      > <span class="dt"
      >BinTree</span
      > a (<span class="dt"
      >BinTree</span
      > a) (<span class="dt"
      >BinTree</span
      > a)<br
       /></code
    ></pre
  ><p
  >In contrast, the depth-typed trees (whether binary, <span class="math"
    ><em
      >b</em
      ></span
    >-ary, trie-ary, or functor-ary) all have strict separation of leaf nodes from branching nodes.</p
  ><p
  >A conventional, finite binary tree data type might look like</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >data</span
      > <span class="dt"
      >BinTree</span
      > a <span class="fu"
      >=</span
      > <span class="dt"
      >Leaf</span
      > a <span class="fu"
      >|</span
      > <span class="dt"
      >Branch</span
      > (<span class="dt"
      >Pair</span
      > (<span class="dt"
      >BinTree</span
      > a))<br
       /></code
    ></pre
  ><p
  >Its inverted (left-folded) form:</p
  ><pre class="sourceCode haskell"
  ><code
    ><span class="kw"
      >data</span
      > <span class="dt"
      >BinTree</span
      > a <span class="fu"
      >=</span
      > <span class="dt"
      >Leaf</span
      > a <span class="fu"
      >|</span
      > <span class="dt"
      >Branch</span
      > (<span class="dt"
      >BinTree</span
      > (<span class="dt"
      >Pair</span
      > a))<br
       /></code
    ></pre
  ><p
  >When we had depth typing, the right- and left-folded forms were equally expressive. They both described &quot;perfect&quot; trees, with each depth consisting entirely of branching or (for the deepest level) entirely of values. (I'm speaking figuratively for the left-folded case, since literally there is no branching.)</p
  ><p
  >Without depth typing, the expressiveness differs significantly. Right-folded trees can be ragged, with leaves occurring at various depths in the same tree. Left-folded binary trees of depth <span class="math"
    ><em
      >n</em
      ></span
    > can only be perfect, even though the depth is determined dynamically, not statically (i.e., not from type).</p
  ><p
  >Dynamically-depthed binary trees generalize to <span class="math"
    ><em
      >b</em
      ></span
    >-ary, trie-ary, and functor-ary versions. In each case, the left-folded versions are much more statically constrained than their right-folded counterparts.</p
  ></div
>

<div id="from-here"
><h3
  >From here</h3
  ><p
  >This post is the last of a six-part series on tries and static size-typing in the context of numbers, vectors, and trees. Maybe you're curious where these ideas came from and where they might be going.</p
  ><p
  >I got interested in these relationships while noodling over some imperative, data-parallel programs. I asked one one of my standard questions: What elegant beauty is hiding deep beneath these low-level implementation details. In this case, prominent details include array indices, bit fiddling, and power-of-two restrictions, which led me to play with binary numbers. Moreover, parallel algorithms often use a divide-and-conquer strategy. That strategy hints at balanced binary trees, which then can be indexed by binary numbers (bit sequences). Indexing brought memo tries to mind.</p
  ><p
  >I expect to write soon about some ideas &amp; techniques for deriving low-level, side-effecting, parallel algorithms from semantically simple and elegant specifications.</p
  ></div
>
<p><a href="http://conal.net/blog/?flattrss_redirect&amp;id=314&amp;md5=209bdcd3e572f837b906074e674313d9"><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/from-tries-to-trees/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=conal&amp;popout=1&amp;url=http%3A%2F%2Fconal.net%2Fblog%2Fposts%2Ffrom-tries-to-trees&amp;language=en_GB&amp;category=text&amp;title=From+tries+to+trees&amp;description=This+post+is+the+last+of+a+series+of+six+relating+numbers%2C+vectors%2C+and+trees%2C+revolving+around+the+themes+of+static+size-typing+and+memo+tries.+We%26%238217%3Bve+seen+that+length-typed+vectors...&amp;tags=number%2Ctree%2Ctrie%2Cvector%2Cblog" type="text/html" />
	</item>
	</channel>
</rss>
