Sophie

Sophie

distrib > Fedora > 14 > x86_64 > media > updates > by-pkgid > 692428056ac305d613b0f3c0c1f947ff > files > 22

ghc-MemoTrie-devel-0.4.9-1.fc14.i686.rpm

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<!-- Generated by HsColour, http://www.cs.york.ac.uk/fp/darcs/hscolour/ -->
<title>src/Data/MemoTrie.hs</title>
<link type='text/css' rel='stylesheet' href='hscolour.css' />
</head>
<body>
<pre><a name="line-1"></a><span class='hs-comment'>{-# LANGUAGE GADTs, TypeFamilies, TypeOperators, ScopedTypeVariables, CPP #-}</span>
<a name="line-2"></a><span class='hs-comment'>{-# OPTIONS_GHC -Wall -fenable-rewrite-rules #-}</span>
<a name="line-3"></a><span class='hs-comment'>-- ScopedTypeVariables works around a 6.10 bug.  The forall keyword is</span>
<a name="line-4"></a><span class='hs-comment'>-- supposed to be recognized in a RULES pragma.</span>
<a name="line-5"></a>
<a name="line-6"></a><span class='hs-comment'>----------------------------------------------------------------------</span>
<a name="line-7"></a><span class='hs-comment'>-- |</span>
<a name="line-8"></a><span class='hs-comment'>-- Module      :  Data.MemoTrie</span>
<a name="line-9"></a><span class='hs-comment'>-- Copyright   :  (c) Conal Elliott 2008</span>
<a name="line-10"></a><span class='hs-comment'>-- License     :  BSD3</span>
<a name="line-11"></a><span class='hs-comment'>-- </span>
<a name="line-12"></a><span class='hs-comment'>-- Maintainer  :  conal@conal.net</span>
<a name="line-13"></a><span class='hs-comment'>-- Stability   :  experimental</span>
<a name="line-14"></a><span class='hs-comment'>-- </span>
<a name="line-15"></a><span class='hs-comment'>-- Trie-based memoizer</span>
<a name="line-16"></a><span class='hs-comment'>-- Adapted from sjanssen's paste: \"a lazy trie\" &lt;<a href="http://hpaste.org/3839">http://hpaste.org/3839</a>&gt;.</span>
<a name="line-17"></a><span class='hs-comment'>----------------------------------------------------------------------</span>
<a name="line-18"></a>
<a name="line-19"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>MemoTrie</span>
<a name="line-20"></a>  <span class='hs-layout'>(</span> <span class='hs-conid'>HasTrie</span><span class='hs-layout'>(</span><span class='hs-keyglyph'>..</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span> <span class='hs-varid'>domain</span><span class='hs-layout'>,</span> <span class='hs-varid'>idTrie</span><span class='hs-layout'>,</span> <span class='hs-layout'>(</span><span class='hs-varop'>@.@</span><span class='hs-layout'>)</span>
<a name="line-21"></a>  <span class='hs-comment'>-- , trie2, trie3, untrie2, untrie3</span>
<a name="line-22"></a>  <span class='hs-layout'>,</span> <span class='hs-varid'>memo</span><span class='hs-layout'>,</span> <span class='hs-varid'>memo2</span><span class='hs-layout'>,</span> <span class='hs-varid'>memo3</span><span class='hs-layout'>,</span> <span class='hs-varid'>mup</span>
<a name="line-23"></a>  <span class='hs-layout'>,</span> <span class='hs-varid'>inTrie</span><span class='hs-layout'>,</span> <span class='hs-varid'>inTrie2</span><span class='hs-layout'>,</span> <span class='hs-varid'>inTrie3</span>
<a name="line-24"></a>  <span class='hs-comment'>-- , untrieBits</span>
<a name="line-25"></a>  <span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
<a name="line-26"></a>
<a name="line-27"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Bits</span>
<a name="line-28"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Word</span>
<a name="line-29"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Int</span>
<a name="line-30"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Applicative</span>
<a name="line-31"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Arrow</span> <span class='hs-layout'>(</span><span class='hs-varid'>first</span><span class='hs-layout'>,</span><span class='hs-layout'>(</span><span class='hs-varop'>&amp;&amp;&amp;</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-32"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Monoid</span>
<a name="line-33"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Function</span> <span class='hs-layout'>(</span><span class='hs-varid'>on</span><span class='hs-layout'>)</span>
<a name="line-34"></a>
<a name="line-35"></a><span class='hs-comment'>-- import Prelude hiding (id,(.))</span>
<a name="line-36"></a><span class='hs-comment'>-- import Control.Category</span>
<a name="line-37"></a><span class='hs-comment'>-- import Control.Arrow</span>
<a name="line-38"></a>
<a name="line-39"></a><span class='hs-keyword'>infixr</span> <span class='hs-num'>0</span> <span class='hs-conop'>:-&gt;:</span>
<a name="line-40"></a>
<a name="line-41"></a><span class='hs-comment'>-- | Mapping from all elements of @a@ to the results of some function</span>
<a name="line-42"></a><span class='hs-keyword'>class</span> <span class='hs-conid'>HasTrie</span> <span class='hs-varid'>a</span> <span class='hs-keyword'>where</span>
<a name="line-43"></a>    <span class='hs-comment'>-- | Representation of trie with domain type @a@</span>
<a name="line-44"></a>    <span class='hs-keyword'>data</span> <span class='hs-layout'>(</span><span class='hs-conop'>:-&gt;:</span><span class='hs-layout'>)</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>::</span> <span class='hs-varop'>*</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varop'>*</span>
<a name="line-45"></a>    <span class='hs-comment'>-- | Create the trie for the entire domain of a function</span>
<a name="line-46"></a>    <span class='hs-varid'>trie</span>   <span class='hs-keyglyph'>::</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span>  <span class='hs-keyglyph'>-&gt;</span>  <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span>
<a name="line-47"></a>    <span class='hs-comment'>-- | Convert a trie to a function, i.e., access a field of the trie</span>
<a name="line-48"></a>    <span class='hs-varid'>untrie</span> <span class='hs-keyglyph'>::</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span>  <span class='hs-keyglyph'>-&gt;</span>  <span class='hs-varid'>b</span><span class='hs-layout'>)</span>
<a name="line-49"></a>    <span class='hs-comment'>-- | List the trie elements.  Order of keys (@:: a@) is always the same.</span>
<a name="line-50"></a>    <span class='hs-varid'>enumerate</span> <span class='hs-keyglyph'>::</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-layout'>,</span><span class='hs-varid'>b</span><span class='hs-layout'>)</span><span class='hs-keyglyph'>]</span>
<a name="line-51"></a>
<a name="line-52"></a><a name="domain"></a><span class='hs-comment'>-- | Domain elements of a trie</span>
<a name="line-53"></a><span class='hs-definition'>domain</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>HasTrie</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>a</span><span class='hs-keyglyph'>]</span>
<a name="line-54"></a><span class='hs-definition'>domain</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>map</span> <span class='hs-varid'>fst</span> <span class='hs-layout'>(</span><span class='hs-varid'>enumerate</span> <span class='hs-layout'>(</span><span class='hs-varid'>trie</span> <span class='hs-layout'>(</span><span class='hs-varid'>const</span> <span class='hs-varid'>oops</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-55"></a> <span class='hs-keyword'>where</span>
<a name="line-56"></a>   <span class='hs-varid'>oops</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>error</span> <span class='hs-str'>"Data.MemoTrie.domain: range element evaluated."</span>
<a name="line-57"></a>
<a name="line-58"></a><span class='hs-comment'>-- Hm: domain :: [Bool] doesn't produce any output.</span>
<a name="line-59"></a>
<a name="line-60"></a><span class='hs-keyword'>instance</span> <span class='hs-layout'>(</span><span class='hs-conid'>HasTrie</span> <span class='hs-varid'>a</span><span class='hs-layout'>,</span> <span class='hs-conid'>Eq</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>Eq</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
<a name="line-61"></a>  <span class='hs-layout'>(</span><span class='hs-varop'>==</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varop'>==</span><span class='hs-layout'>)</span> <span class='hs-varop'>`on`</span> <span class='hs-layout'>(</span><span class='hs-varid'>map</span> <span class='hs-varid'>snd</span> <span class='hs-varop'>.</span> <span class='hs-varid'>enumerate</span><span class='hs-layout'>)</span>
<a name="line-62"></a>
<a name="line-63"></a><span class='hs-keyword'>instance</span> <span class='hs-layout'>(</span><span class='hs-conid'>HasTrie</span> <span class='hs-varid'>a</span><span class='hs-layout'>,</span> <span class='hs-conid'>Show</span> <span class='hs-varid'>a</span><span class='hs-layout'>,</span> <span class='hs-conid'>Show</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>Show</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
<a name="line-64"></a>  <span class='hs-varid'>show</span> <span class='hs-varid'>t</span> <span class='hs-keyglyph'>=</span> <span class='hs-str'>"Trie: "</span> <span class='hs-varop'>++</span> <span class='hs-varid'>show</span> <span class='hs-layout'>(</span><span class='hs-varid'>enumerate</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span>
<a name="line-65"></a>
<a name="line-66"></a><span class='hs-comment'>{-
<a name="line-67"></a>trie2 :: (HasTrie a, HasTrie b) =&gt;
<a name="line-68"></a>         (a -&gt; b -&gt; c) -&gt; (a :-&gt;: b :-&gt;: c)
<a name="line-69"></a>-- trie2 h = trie $ \ a -&gt; trie $ \ b -&gt; h a b
<a name="line-70"></a>-- trie2 h = trie $ \ a -&gt; trie (h a)
<a name="line-71"></a>trie2 h = trie (trie . h)
<a name="line-72"></a>-- trie2 h = trie (fmap trie h)
<a name="line-73"></a>-- trie2 = (fmap.fmap) trie trie
<a name="line-74"></a>
<a name="line-75"></a>
<a name="line-76"></a>trie3 :: (HasTrie a, HasTrie b, HasTrie c) =&gt;
<a name="line-77"></a>         (a -&gt; b -&gt; c -&gt; d) -&gt; (a :-&gt;: b :-&gt;: c :-&gt;: d)
<a name="line-78"></a>trie3 h = trie (trie2 . h)
<a name="line-79"></a>
<a name="line-80"></a>untrie2 :: (HasTrie a, HasTrie b) =&gt;
<a name="line-81"></a>          (a :-&gt;: b :-&gt;: c)-&gt; (a -&gt; b -&gt; c)
<a name="line-82"></a>untrie2 tt = untrie . untrie tt
<a name="line-83"></a>
<a name="line-84"></a>
<a name="line-85"></a>untrie3 :: (HasTrie a, HasTrie b, HasTrie c) =&gt;
<a name="line-86"></a>          (a :-&gt;: b :-&gt;: c :-&gt;: d)-&gt; (a -&gt; b -&gt; c -&gt; d)
<a name="line-87"></a>untrie3 tt = untrie2 . untrie tt
<a name="line-88"></a>-}</span>
<a name="line-89"></a>
<a name="line-90"></a>
<a name="line-91"></a><span class='hs-comment'>{-# RULES
<a name="line-92"></a>"trie/untrie"   forall t. trie (untrie t) = t
<a name="line-93"></a> #-}</span>
<a name="line-94"></a>
<a name="line-95"></a><span class='hs-comment'>-- Don't include the dual rule:</span>
<a name="line-96"></a><span class='hs-comment'>--   "untrie/trie"   forall f. untrie (trie f) = f</span>
<a name="line-97"></a><span class='hs-comment'>-- which would defeat memoization.</span>
<a name="line-98"></a><span class='hs-comment'>--</span>
<a name="line-99"></a><span class='hs-comment'>-- TODO: experiment with rule application.  Maybe re-enable "untrie/trie"</span>
<a name="line-100"></a><span class='hs-comment'>-- but fiddle with phases, so it won't defeat 'memo'.</span>
<a name="line-101"></a>
<a name="line-102"></a><a name="memo"></a><span class='hs-comment'>-- | Trie-based function memoizer</span>
<a name="line-103"></a><span class='hs-definition'>memo</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>HasTrie</span> <span class='hs-varid'>t</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>t</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>t</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span>
<a name="line-104"></a><span class='hs-definition'>memo</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>untrie</span> <span class='hs-varop'>.</span> <span class='hs-varid'>trie</span>
<a name="line-105"></a>
<a name="line-106"></a><a name="memo2"></a><span class='hs-comment'>-- | Memoize a binary function, on its first argument and then on its</span>
<a name="line-107"></a><span class='hs-comment'>-- second.  Take care to exploit any partial evaluation.</span>
<a name="line-108"></a><span class='hs-definition'>memo2</span> <span class='hs-keyglyph'>::</span> <span class='hs-layout'>(</span><span class='hs-conid'>HasTrie</span> <span class='hs-varid'>s</span><span class='hs-layout'>,</span><span class='hs-conid'>HasTrie</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>t</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>t</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span>
<a name="line-109"></a>
<a name="line-110"></a><a name="memo3"></a><span class='hs-comment'>-- | Memoize a ternary function on successive arguments.  Take care to</span>
<a name="line-111"></a><span class='hs-comment'>-- exploit any partial evaluation.</span>
<a name="line-112"></a><span class='hs-definition'>memo3</span> <span class='hs-keyglyph'>::</span> <span class='hs-layout'>(</span><span class='hs-conid'>HasTrie</span> <span class='hs-varid'>r</span><span class='hs-layout'>,</span><span class='hs-conid'>HasTrie</span> <span class='hs-varid'>s</span><span class='hs-layout'>,</span><span class='hs-conid'>HasTrie</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>r</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>t</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>r</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>t</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span>
<a name="line-113"></a>
<a name="line-114"></a><a name="mup"></a><span class='hs-comment'>-- | Lift a memoizer to work with one more argument.</span>
<a name="line-115"></a><span class='hs-definition'>mup</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>HasTrie</span> <span class='hs-varid'>t</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>b</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>c</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>t</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>t</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>c</span><span class='hs-layout'>)</span>
<a name="line-116"></a><span class='hs-definition'>mup</span> <span class='hs-varid'>mem</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>memo</span> <span class='hs-layout'>(</span><span class='hs-varid'>mem</span> <span class='hs-varop'>.</span> <span class='hs-varid'>f</span><span class='hs-layout'>)</span>
<a name="line-117"></a>
<a name="line-118"></a><span class='hs-definition'>memo2</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>mup</span> <span class='hs-varid'>memo</span>
<a name="line-119"></a><span class='hs-definition'>memo3</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>mup</span> <span class='hs-varid'>memo2</span>
<a name="line-120"></a>
<a name="line-121"></a><a name="inTrie"></a><span class='hs-comment'>-- | Apply a unary function inside of a trie</span>
<a name="line-122"></a><span class='hs-definition'>inTrie</span> <span class='hs-keyglyph'>::</span> <span class='hs-layout'>(</span><span class='hs-conid'>HasTrie</span> <span class='hs-varid'>a</span><span class='hs-layout'>,</span> <span class='hs-conid'>HasTrie</span> <span class='hs-varid'>c</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=&gt;</span>
<a name="line-123"></a>          <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varid'>a</span>  <span class='hs-keyglyph'>-&gt;</span>  <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>c</span>  <span class='hs-keyglyph'>-&gt;</span>  <span class='hs-varid'>d</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-124"></a>       <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>c</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>d</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-125"></a><span class='hs-definition'>inTrie</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>untrie</span> <span class='hs-varop'>~&gt;</span> <span class='hs-varid'>trie</span>
<a name="line-126"></a>
<a name="line-127"></a><a name="inTrie2"></a><span class='hs-comment'>-- | Apply a binary function inside of a trie</span>
<a name="line-128"></a><span class='hs-definition'>inTrie2</span> <span class='hs-keyglyph'>::</span> <span class='hs-layout'>(</span><span class='hs-conid'>HasTrie</span> <span class='hs-varid'>a</span><span class='hs-layout'>,</span> <span class='hs-conid'>HasTrie</span> <span class='hs-varid'>c</span><span class='hs-layout'>,</span> <span class='hs-conid'>HasTrie</span> <span class='hs-varid'>e</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=&gt;</span>
<a name="line-129"></a>           <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varid'>a</span>  <span class='hs-keyglyph'>-&gt;</span>  <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>c</span>  <span class='hs-keyglyph'>-&gt;</span>  <span class='hs-varid'>d</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>e</span>  <span class='hs-keyglyph'>-&gt;</span>  <span class='hs-varid'>f</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-130"></a>        <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>c</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>d</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>e</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>f</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-131"></a><span class='hs-definition'>inTrie2</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>untrie</span> <span class='hs-varop'>~&gt;</span> <span class='hs-varid'>inTrie</span>
<a name="line-132"></a>
<a name="line-133"></a><a name="inTrie3"></a><span class='hs-comment'>-- | Apply a ternary function inside of a trie</span>
<a name="line-134"></a><span class='hs-definition'>inTrie3</span> <span class='hs-keyglyph'>::</span> <span class='hs-layout'>(</span><span class='hs-conid'>HasTrie</span> <span class='hs-varid'>a</span><span class='hs-layout'>,</span> <span class='hs-conid'>HasTrie</span> <span class='hs-varid'>c</span><span class='hs-layout'>,</span> <span class='hs-conid'>HasTrie</span> <span class='hs-varid'>e</span><span class='hs-layout'>,</span> <span class='hs-conid'>HasTrie</span> <span class='hs-varid'>g</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=&gt;</span>
<a name="line-135"></a>           <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varid'>a</span>  <span class='hs-keyglyph'>-&gt;</span>  <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>c</span>  <span class='hs-keyglyph'>-&gt;</span>  <span class='hs-varid'>d</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>e</span>  <span class='hs-keyglyph'>-&gt;</span>  <span class='hs-varid'>f</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>g</span>  <span class='hs-keyglyph'>-&gt;</span>  <span class='hs-varid'>h</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-136"></a>        <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>c</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>d</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>e</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>f</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>g</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>h</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-137"></a><span class='hs-definition'>inTrie3</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>untrie</span> <span class='hs-varop'>~&gt;</span> <span class='hs-varid'>inTrie2</span>
<a name="line-138"></a>
<a name="line-139"></a>
<a name="line-140"></a><span class='hs-comment'>---- Instances</span>
<a name="line-141"></a>
<a name="line-142"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>HasTrie</span> <span class='hs-conid'>()</span> <span class='hs-keyword'>where</span>
<a name="line-143"></a>    <span class='hs-keyword'>data</span> <span class='hs-conid'>()</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>UnitTrie</span> <span class='hs-varid'>a</span>
<a name="line-144"></a>    <span class='hs-varid'>trie</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>UnitTrie</span> <span class='hs-layout'>(</span><span class='hs-varid'>f</span> <span class='hs-conid'>()</span><span class='hs-layout'>)</span>
<a name="line-145"></a>    <span class='hs-varid'>untrie</span> <span class='hs-layout'>(</span><span class='hs-conid'>UnitTrie</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyglyph'>\</span> <span class='hs-conid'>()</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>a</span>
<a name="line-146"></a>    <span class='hs-varid'>enumerate</span> <span class='hs-layout'>(</span><span class='hs-conid'>UnitTrie</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyglyph'>[</span><span class='hs-layout'>(</span><span class='hs-conid'>()</span><span class='hs-layout'>,</span><span class='hs-varid'>a</span><span class='hs-layout'>)</span><span class='hs-keyglyph'>]</span>
<a name="line-147"></a>
<a name="line-148"></a><span class='hs-comment'>-- Proofs of inverse properties:</span>
<a name="line-149"></a>
<a name="line-150"></a><span class='hs-comment'>{-
<a name="line-151"></a>    untrie (trie f)
<a name="line-152"></a>      == { trie def }
<a name="line-153"></a>    untrie (UnitTrie (f ()))
<a name="line-154"></a>      == { untrie def }
<a name="line-155"></a>    \ () -&gt; (f ())
<a name="line-156"></a>      == { const-unit }
<a name="line-157"></a>    f   
<a name="line-158"></a>
<a name="line-159"></a>    trie (untrie (UnitTrie a))
<a name="line-160"></a>      == { untrie def }
<a name="line-161"></a>    trie (\ () -&gt; a)
<a name="line-162"></a>      == { trie def }
<a name="line-163"></a>    UnitTrie ((\ () -&gt; a) ())
<a name="line-164"></a>      == { beta-reduction }
<a name="line-165"></a>    UnitTrie a
<a name="line-166"></a>
<a name="line-167"></a>Oops -- the last step of the first direction is bogus when f is non-strict.
<a name="line-168"></a>Can be fixed by using @const a@ in place of @\ () -&gt; a@, but I can't do
<a name="line-169"></a>the same for other types, like integers or sums.
<a name="line-170"></a>
<a name="line-171"></a>All of these proofs have this same bug, unless we restrict ourselves to
<a name="line-172"></a>memoizing hyper-strict functions.
<a name="line-173"></a>
<a name="line-174"></a>-}</span>
<a name="line-175"></a>
<a name="line-176"></a>
<a name="line-177"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>HasTrie</span> <span class='hs-conid'>Bool</span> <span class='hs-keyword'>where</span>
<a name="line-178"></a>    <span class='hs-keyword'>data</span> <span class='hs-conid'>Bool</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>x</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>BoolTrie</span> <span class='hs-varid'>x</span> <span class='hs-varid'>x</span>
<a name="line-179"></a>    <span class='hs-varid'>trie</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>BoolTrie</span> <span class='hs-layout'>(</span><span class='hs-varid'>f</span> <span class='hs-conid'>False</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>f</span> <span class='hs-conid'>True</span><span class='hs-layout'>)</span>
<a name="line-180"></a>    <span class='hs-varid'>untrie</span> <span class='hs-layout'>(</span><span class='hs-conid'>BoolTrie</span> <span class='hs-varid'>f</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>if'</span> <span class='hs-varid'>f</span> <span class='hs-varid'>t</span>
<a name="line-181"></a>    <span class='hs-varid'>enumerate</span> <span class='hs-layout'>(</span><span class='hs-conid'>BoolTrie</span> <span class='hs-varid'>f</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyglyph'>[</span><span class='hs-layout'>(</span><span class='hs-conid'>False</span><span class='hs-layout'>,</span><span class='hs-varid'>f</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span><span class='hs-layout'>(</span><span class='hs-conid'>True</span><span class='hs-layout'>,</span><span class='hs-varid'>t</span><span class='hs-layout'>)</span><span class='hs-keyglyph'>]</span>
<a name="line-182"></a>
<a name="line-183"></a><a name="if'"></a><span class='hs-comment'>-- | Conditional with boolean last.</span>
<a name="line-184"></a><span class='hs-comment'>-- Spec: @if' (f False) (f True) == f@</span>
<a name="line-185"></a><span class='hs-definition'>if'</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>x</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>x</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Bool</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>x</span>
<a name="line-186"></a><span class='hs-definition'>if'</span> <span class='hs-varid'>t</span> <span class='hs-keyword'>_</span> <span class='hs-conid'>False</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>t</span>
<a name="line-187"></a><span class='hs-definition'>if'</span> <span class='hs-keyword'>_</span> <span class='hs-varid'>e</span> <span class='hs-conid'>True</span>  <span class='hs-keyglyph'>=</span> <span class='hs-varid'>e</span>
<a name="line-188"></a>
<a name="line-189"></a><span class='hs-comment'>{-
<a name="line-190"></a>    untrie (trie f)
<a name="line-191"></a>      == { trie def }
<a name="line-192"></a>    untrie (BoolTrie (f False) (f True))
<a name="line-193"></a>      == { untrie def }
<a name="line-194"></a>    if' (f False) (f True)
<a name="line-195"></a>      == { if' spec }
<a name="line-196"></a>    f
<a name="line-197"></a>
<a name="line-198"></a>    trie (untrie (BoolTrie f t))
<a name="line-199"></a>      == { untrie def }
<a name="line-200"></a>    trie (if' f t)
<a name="line-201"></a>      == { trie def }
<a name="line-202"></a>    BoolTrie (if' f t False) (if' f t True)
<a name="line-203"></a>      == { if' spec }
<a name="line-204"></a>    BoolTrie f t
<a name="line-205"></a>-}</span>
<a name="line-206"></a>
<a name="line-207"></a>
<a name="line-208"></a><span class='hs-keyword'>instance</span> <span class='hs-layout'>(</span><span class='hs-conid'>HasTrie</span> <span class='hs-varid'>a</span><span class='hs-layout'>,</span> <span class='hs-conid'>HasTrie</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>HasTrie</span> <span class='hs-layout'>(</span><span class='hs-conid'>Either</span> <span class='hs-varid'>a</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
<a name="line-209"></a>    <span class='hs-keyword'>data</span> <span class='hs-layout'>(</span><span class='hs-conid'>Either</span> <span class='hs-varid'>a</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>x</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>EitherTrie</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>x</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>b</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>x</span><span class='hs-layout'>)</span>
<a name="line-210"></a>    <span class='hs-varid'>trie</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>EitherTrie</span> <span class='hs-layout'>(</span><span class='hs-varid'>trie</span> <span class='hs-layout'>(</span><span class='hs-varid'>f</span> <span class='hs-varop'>.</span> <span class='hs-conid'>Left</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>trie</span> <span class='hs-layout'>(</span><span class='hs-varid'>f</span> <span class='hs-varop'>.</span> <span class='hs-conid'>Right</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-211"></a>    <span class='hs-varid'>untrie</span> <span class='hs-layout'>(</span><span class='hs-conid'>EitherTrie</span> <span class='hs-varid'>s</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>either</span> <span class='hs-layout'>(</span><span class='hs-varid'>untrie</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>untrie</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span>
<a name="line-212"></a>    <span class='hs-varid'>enumerate</span> <span class='hs-layout'>(</span><span class='hs-conid'>EitherTrie</span> <span class='hs-varid'>s</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>enum'</span> <span class='hs-conid'>Left</span> <span class='hs-varid'>s</span> <span class='hs-varop'>`weave`</span> <span class='hs-varid'>enum'</span> <span class='hs-conid'>Right</span> <span class='hs-varid'>t</span>
<a name="line-213"></a>
<a name="line-214"></a><a name="enum'"></a><span class='hs-definition'>enum'</span> <span class='hs-keyglyph'>::</span> <span class='hs-layout'>(</span><span class='hs-conid'>HasTrie</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>a'</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-layout'>(</span><span class='hs-varid'>a'</span><span class='hs-layout'>,</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span><span class='hs-keyglyph'>]</span>
<a name="line-215"></a><span class='hs-definition'>enum'</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>fmap</span><span class='hs-varop'>.</span><span class='hs-varid'>first</span><span class='hs-layout'>)</span> <span class='hs-varid'>f</span> <span class='hs-varop'>.</span> <span class='hs-varid'>enumerate</span>
<a name="line-216"></a>
<a name="line-217"></a><a name="weave"></a><span class='hs-definition'>weave</span> <span class='hs-keyglyph'>::</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>a</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>a</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>a</span><span class='hs-keyglyph'>]</span>
<a name="line-218"></a><span class='hs-conid'>[]</span> <span class='hs-varop'>`weave`</span> <span class='hs-keyword'>as</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>as</span>
<a name="line-219"></a><span class='hs-keyword'>as</span> <span class='hs-varop'>`weave`</span> <span class='hs-conid'>[]</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>as</span>
<a name="line-220"></a><a name="weave"></a><span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-conop'>:</span><span class='hs-keyword'>as</span><span class='hs-layout'>)</span> <span class='hs-varop'>`weave`</span> <span class='hs-varid'>bs</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>a</span> <span class='hs-conop'>:</span> <span class='hs-layout'>(</span><span class='hs-varid'>bs</span> <span class='hs-varop'>`weave`</span> <span class='hs-keyword'>as</span><span class='hs-layout'>)</span>
<a name="line-221"></a>
<a name="line-222"></a><span class='hs-comment'>{-
<a name="line-223"></a>    untrie (trie f)
<a name="line-224"></a>       == { trie def }
<a name="line-225"></a>    untrie (EitherTrie (trie (f . Left)) (trie (f . Right)))
<a name="line-226"></a>       == { untrie def }
<a name="line-227"></a>    either (untrie (trie (f . Left))) (untrie (trie (f . Right)))
<a name="line-228"></a>       == { untrie . trie }
<a name="line-229"></a>    either (f . Left) (f . Right)
<a name="line-230"></a>       == { either }
<a name="line-231"></a>    f
<a name="line-232"></a>
<a name="line-233"></a>    trie (untrie (EitherTrie s t))
<a name="line-234"></a>       == { untrie def }
<a name="line-235"></a>    trie (either (untrie s) (untrie t))
<a name="line-236"></a>       == { trie def }
<a name="line-237"></a>    EitherTrie (trie (either (untrie s) (untrie t) . Left))
<a name="line-238"></a>               (trie (either (untrie s) (untrie t) . Right))
<a name="line-239"></a>       == { either }
<a name="line-240"></a>    EitherTrie (trie (untrie s)) (trie (untrie t))
<a name="line-241"></a>       == { trie . untrie }
<a name="line-242"></a>    EitherTrie s t
<a name="line-243"></a>-}</span>
<a name="line-244"></a>
<a name="line-245"></a>
<a name="line-246"></a><span class='hs-keyword'>instance</span> <span class='hs-layout'>(</span><span class='hs-conid'>HasTrie</span> <span class='hs-varid'>a</span><span class='hs-layout'>,</span> <span class='hs-conid'>HasTrie</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>HasTrie</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-layout'>,</span><span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
<a name="line-247"></a>    <span class='hs-keyword'>data</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-layout'>,</span><span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>x</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>PairTrie</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-layout'>(</span><span class='hs-varid'>b</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>x</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-248"></a>    <span class='hs-varid'>trie</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>PairTrie</span> <span class='hs-layout'>(</span><span class='hs-varid'>trie</span> <span class='hs-layout'>(</span><span class='hs-varid'>trie</span> <span class='hs-varop'>.</span> <span class='hs-varid'>curry</span> <span class='hs-varid'>f</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-249"></a>    <span class='hs-varid'>untrie</span> <span class='hs-layout'>(</span><span class='hs-conid'>PairTrie</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>uncurry</span> <span class='hs-layout'>(</span><span class='hs-varid'>untrie</span> <span class='hs-varop'>.</span>  <span class='hs-varid'>untrie</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span>
<a name="line-250"></a>    <span class='hs-varid'>enumerate</span> <span class='hs-layout'>(</span><span class='hs-conid'>PairTrie</span> <span class='hs-varid'>tt</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span>
<a name="line-251"></a>      <span class='hs-keyglyph'>[</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-layout'>,</span><span class='hs-varid'>b</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span><span class='hs-varid'>x</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>|</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-layout'>,</span><span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>enumerate</span> <span class='hs-varid'>tt</span> <span class='hs-layout'>,</span> <span class='hs-layout'>(</span><span class='hs-varid'>b</span><span class='hs-layout'>,</span><span class='hs-varid'>x</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>enumerate</span> <span class='hs-varid'>t</span> <span class='hs-keyglyph'>]</span>
<a name="line-252"></a>
<a name="line-253"></a><span class='hs-comment'>{-
<a name="line-254"></a>    untrie (trie f)
<a name="line-255"></a>      == { trie def }
<a name="line-256"></a>    untrie (PairTrie (trie (trie . curry f)))
<a name="line-257"></a>      == { untrie def }
<a name="line-258"></a>    uncurry (untrie . untrie (trie (trie . curry f)))
<a name="line-259"></a>      == { untrie . trie }
<a name="line-260"></a>    uncurry (untrie . trie . curry f)
<a name="line-261"></a>      == { untrie . untrie }
<a name="line-262"></a>    uncurry (curry f)
<a name="line-263"></a>      == { uncurry . curry }
<a name="line-264"></a>    f
<a name="line-265"></a>
<a name="line-266"></a>    trie (untrie (PairTrie t))
<a name="line-267"></a>      == { untrie def }
<a name="line-268"></a>    trie (uncurry (untrie .  untrie t))
<a name="line-269"></a>      == { trie def }
<a name="line-270"></a>    PairTrie (trie (trie . curry (uncurry (untrie .  untrie t))))
<a name="line-271"></a>      == { curry . uncurry }
<a name="line-272"></a>    PairTrie (trie (trie . untrie .  untrie t))
<a name="line-273"></a>      == { trie . untrie }
<a name="line-274"></a>    PairTrie (trie (untrie t))
<a name="line-275"></a>      == { trie . untrie }
<a name="line-276"></a>    PairTrie t
<a name="line-277"></a>-}</span>
<a name="line-278"></a>
<a name="line-279"></a><span class='hs-keyword'>instance</span> <span class='hs-layout'>(</span><span class='hs-conid'>HasTrie</span> <span class='hs-varid'>a</span><span class='hs-layout'>,</span> <span class='hs-conid'>HasTrie</span> <span class='hs-varid'>b</span><span class='hs-layout'>,</span> <span class='hs-conid'>HasTrie</span> <span class='hs-varid'>c</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>HasTrie</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-layout'>,</span><span class='hs-varid'>b</span><span class='hs-layout'>,</span><span class='hs-varid'>c</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
<a name="line-280"></a>    <span class='hs-keyword'>data</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-layout'>,</span><span class='hs-varid'>b</span><span class='hs-layout'>,</span><span class='hs-varid'>c</span><span class='hs-layout'>)</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>x</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>TripleTrie</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-layout'>,</span><span class='hs-varid'>b</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span><span class='hs-varid'>c</span><span class='hs-layout'>)</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>x</span><span class='hs-layout'>)</span>
<a name="line-281"></a>    <span class='hs-varid'>trie</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>TripleTrie</span> <span class='hs-layout'>(</span><span class='hs-varid'>trie</span> <span class='hs-layout'>(</span><span class='hs-varid'>f</span> <span class='hs-varop'>.</span> <span class='hs-varid'>trip</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-282"></a>    <span class='hs-varid'>untrie</span> <span class='hs-layout'>(</span><span class='hs-conid'>TripleTrie</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>untrie</span> <span class='hs-varid'>t</span> <span class='hs-varop'>.</span> <span class='hs-varid'>detrip</span>
<a name="line-283"></a>    <span class='hs-varid'>enumerate</span> <span class='hs-layout'>(</span><span class='hs-conid'>TripleTrie</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>enum'</span> <span class='hs-varid'>trip</span> <span class='hs-varid'>t</span>
<a name="line-284"></a>
<a name="line-285"></a><a name="trip"></a><span class='hs-definition'>trip</span> <span class='hs-keyglyph'>::</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-layout'>,</span><span class='hs-varid'>b</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span><span class='hs-varid'>c</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-layout'>,</span><span class='hs-varid'>b</span><span class='hs-layout'>,</span><span class='hs-varid'>c</span><span class='hs-layout'>)</span>
<a name="line-286"></a><span class='hs-definition'>trip</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-layout'>,</span><span class='hs-varid'>b</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span><span class='hs-varid'>c</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-layout'>,</span><span class='hs-varid'>b</span><span class='hs-layout'>,</span><span class='hs-varid'>c</span><span class='hs-layout'>)</span>
<a name="line-287"></a>
<a name="line-288"></a><a name="detrip"></a><span class='hs-definition'>detrip</span> <span class='hs-keyglyph'>::</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-layout'>,</span><span class='hs-varid'>b</span><span class='hs-layout'>,</span><span class='hs-varid'>c</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-layout'>,</span><span class='hs-varid'>b</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span><span class='hs-varid'>c</span><span class='hs-layout'>)</span>
<a name="line-289"></a><span class='hs-definition'>detrip</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-layout'>,</span><span class='hs-varid'>b</span><span class='hs-layout'>,</span><span class='hs-varid'>c</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-layout'>,</span><span class='hs-varid'>b</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span><span class='hs-varid'>c</span><span class='hs-layout'>)</span>
<a name="line-290"></a>
<a name="line-291"></a>
<a name="line-292"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>HasTrie</span> <span class='hs-varid'>x</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>HasTrie</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>x</span><span class='hs-keyglyph'>]</span> <span class='hs-keyword'>where</span>
<a name="line-293"></a>    <span class='hs-keyword'>data</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>x</span><span class='hs-keyglyph'>]</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>ListTrie</span> <span class='hs-layout'>(</span><span class='hs-conid'>Either</span> <span class='hs-conid'>()</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-layout'>,</span><span class='hs-keyglyph'>[</span><span class='hs-varid'>x</span><span class='hs-keyglyph'>]</span><span class='hs-layout'>)</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span>
<a name="line-294"></a>    <span class='hs-varid'>trie</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>ListTrie</span> <span class='hs-layout'>(</span><span class='hs-varid'>trie</span> <span class='hs-layout'>(</span><span class='hs-varid'>f</span> <span class='hs-varop'>.</span> <span class='hs-varid'>list</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-295"></a>    <span class='hs-varid'>untrie</span> <span class='hs-layout'>(</span><span class='hs-conid'>ListTrie</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>untrie</span> <span class='hs-varid'>t</span> <span class='hs-varop'>.</span> <span class='hs-varid'>delist</span>
<a name="line-296"></a>    <span class='hs-varid'>enumerate</span> <span class='hs-layout'>(</span><span class='hs-conid'>ListTrie</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>enum'</span> <span class='hs-varid'>list</span> <span class='hs-varid'>t</span>
<a name="line-297"></a>
<a name="line-298"></a><a name="list"></a><span class='hs-definition'>list</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Either</span> <span class='hs-conid'>()</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-layout'>,</span><span class='hs-keyglyph'>[</span><span class='hs-varid'>x</span><span class='hs-keyglyph'>]</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>x</span><span class='hs-keyglyph'>]</span>
<a name="line-299"></a><span class='hs-definition'>list</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>either</span> <span class='hs-layout'>(</span><span class='hs-varid'>const</span> <span class='hs-conid'>[]</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>uncurry</span> <span class='hs-layout'>(</span><span class='hs-conop'>:</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-300"></a>
<a name="line-301"></a><a name="delist"></a><span class='hs-definition'>delist</span> <span class='hs-keyglyph'>::</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>x</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Either</span> <span class='hs-conid'>()</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-layout'>,</span><span class='hs-keyglyph'>[</span><span class='hs-varid'>x</span><span class='hs-keyglyph'>]</span><span class='hs-layout'>)</span>
<a name="line-302"></a><span class='hs-definition'>delist</span> <span class='hs-conid'>[]</span>     <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Left</span> <span class='hs-conid'>()</span>
<a name="line-303"></a><span class='hs-definition'>delist</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-conop'>:</span><span class='hs-varid'>xs</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Right</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-layout'>,</span><span class='hs-varid'>xs</span><span class='hs-layout'>)</span>
<a name="line-304"></a>
<a name="line-305"></a><span class='hs-cpp'>#define WordInstance(Type,TrieType)\</span>
<a name="line-306"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>HasTrie</span> <span class='hs-conid'>Type</span> <span class='hs-keyword'>where</span> <span class='hs-keyglyph'>\</span>
<a name="line-307"></a>    <span class='hs-keyword'>data</span> <span class='hs-conid'>Type</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>TrieType</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>[</span><span class='hs-conid'>Bool</span><span class='hs-keyglyph'>]</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span><span class='hs-layout'>;</span><span class='hs-keyglyph'>\</span>
<a name="line-308"></a>    <span class='hs-varid'>trie</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>TrieType</span> <span class='hs-layout'>(</span><span class='hs-varid'>trie</span> <span class='hs-layout'>(</span><span class='hs-varid'>f</span> <span class='hs-varop'>.</span> <span class='hs-varid'>unbits</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span><span class='hs-layout'>;</span><span class='hs-keyglyph'>\</span>
<a name="line-309"></a>    <span class='hs-varid'>untrie</span> <span class='hs-layout'>(</span><span class='hs-conid'>TrieType</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>untrie</span> <span class='hs-varid'>t</span> <span class='hs-varop'>.</span> <span class='hs-varid'>bits</span><span class='hs-layout'>;</span><span class='hs-keyglyph'>\</span>
<a name="line-310"></a>    <span class='hs-varid'>enumerate</span> <span class='hs-layout'>(</span><span class='hs-conid'>TrieType</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>enum'</span> <span class='hs-varid'>unbits</span> <span class='hs-varid'>t</span>
<a name="line-311"></a>
<a name="line-312"></a><span class='hs-conid'>WordInstance</span><span class='hs-layout'>(</span><span class='hs-conid'>Word</span><span class='hs-layout'>,</span><span class='hs-conid'>WordTrie</span><span class='hs-layout'>)</span>
<a name="line-313"></a><span class='hs-conid'>WordInstance</span><span class='hs-layout'>(</span><span class='hs-conid'>Word8</span><span class='hs-layout'>,</span><span class='hs-conid'>Word8Trie</span><span class='hs-layout'>)</span>
<a name="line-314"></a><span class='hs-conid'>WordInstance</span><span class='hs-layout'>(</span><span class='hs-conid'>Word16</span><span class='hs-layout'>,</span><span class='hs-conid'>Word16Trie</span><span class='hs-layout'>)</span>
<a name="line-315"></a><span class='hs-conid'>WordInstance</span><span class='hs-layout'>(</span><span class='hs-conid'>Word32</span><span class='hs-layout'>,</span><span class='hs-conid'>Word32Trie</span><span class='hs-layout'>)</span>
<a name="line-316"></a><span class='hs-conid'>WordInstance</span><span class='hs-layout'>(</span><span class='hs-conid'>Word64</span><span class='hs-layout'>,</span><span class='hs-conid'>Word64Trie</span><span class='hs-layout'>)</span>
<a name="line-317"></a>
<a name="line-318"></a><span class='hs-comment'>-- instance HasTrie Word where</span>
<a name="line-319"></a><span class='hs-comment'>--     data Word :-&gt;: a = WordTrie ([Bool] :-&gt;: a)</span>
<a name="line-320"></a><span class='hs-comment'>--     trie f = WordTrie (trie (f . unbits))</span>
<a name="line-321"></a><span class='hs-comment'>--     untrie (WordTrie t) = untrie t . bits</span>
<a name="line-322"></a><span class='hs-comment'>--     enumerate (WordTrie t) = enum' unbits t</span>
<a name="line-323"></a>
<a name="line-324"></a>
<a name="line-325"></a><a name="bits"></a><span class='hs-comment'>-- | Extract bits in little-endian order</span>
<a name="line-326"></a><span class='hs-definition'>bits</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Bits</span> <span class='hs-varid'>t</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-varid'>t</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>Bool</span><span class='hs-keyglyph'>]</span>
<a name="line-327"></a><span class='hs-definition'>bits</span> <span class='hs-num'>0</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>[]</span>
<a name="line-328"></a><span class='hs-definition'>bits</span> <span class='hs-varid'>x</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>testBit</span> <span class='hs-varid'>x</span> <span class='hs-num'>0</span> <span class='hs-conop'>:</span> <span class='hs-varid'>bits</span> <span class='hs-layout'>(</span><span class='hs-varid'>shiftR</span> <span class='hs-varid'>x</span> <span class='hs-num'>1</span><span class='hs-layout'>)</span>
<a name="line-329"></a>
<a name="line-330"></a><a name="unbit"></a><span class='hs-comment'>-- | Convert boolean to 0 (False) or 1 (True)</span>
<a name="line-331"></a><span class='hs-definition'>unbit</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Num</span> <span class='hs-varid'>t</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>Bool</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>t</span>
<a name="line-332"></a><span class='hs-definition'>unbit</span> <span class='hs-conid'>False</span> <span class='hs-keyglyph'>=</span> <span class='hs-num'>0</span>
<a name="line-333"></a><span class='hs-definition'>unbit</span> <span class='hs-conid'>True</span>  <span class='hs-keyglyph'>=</span> <span class='hs-num'>1</span>
<a name="line-334"></a>
<a name="line-335"></a><a name="unbits"></a><span class='hs-comment'>-- | Bit list to value</span>
<a name="line-336"></a><span class='hs-definition'>unbits</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Bits</span> <span class='hs-varid'>t</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>Bool</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>t</span>
<a name="line-337"></a><span class='hs-definition'>unbits</span> <span class='hs-conid'>[]</span> <span class='hs-keyglyph'>=</span> <span class='hs-num'>0</span>
<a name="line-338"></a><span class='hs-definition'>unbits</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-conop'>:</span><span class='hs-varid'>xs</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>unbit</span> <span class='hs-varid'>x</span> <span class='hs-varop'>.|.</span> <span class='hs-varid'>shiftL</span> <span class='hs-layout'>(</span><span class='hs-varid'>unbits</span> <span class='hs-varid'>xs</span><span class='hs-layout'>)</span> <span class='hs-num'>1</span>
<a name="line-339"></a>
<a name="line-340"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>HasTrie</span> <span class='hs-conid'>Char</span> <span class='hs-keyword'>where</span>
<a name="line-341"></a>    <span class='hs-keyword'>data</span> <span class='hs-conid'>Char</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>CharTrie</span> <span class='hs-layout'>(</span><span class='hs-conid'>Int</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span>
<a name="line-342"></a>    <span class='hs-varid'>untrie</span> <span class='hs-layout'>(</span><span class='hs-conid'>CharTrie</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-varid'>n</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>untrie</span> <span class='hs-varid'>t</span> <span class='hs-layout'>(</span><span class='hs-varid'>fromEnum</span> <span class='hs-varid'>n</span><span class='hs-layout'>)</span>
<a name="line-343"></a>    <span class='hs-varid'>trie</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>CharTrie</span> <span class='hs-layout'>(</span><span class='hs-varid'>trie</span> <span class='hs-layout'>(</span><span class='hs-varid'>f</span> <span class='hs-varop'>.</span> <span class='hs-varid'>toEnum</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-344"></a>    <span class='hs-varid'>enumerate</span> <span class='hs-layout'>(</span><span class='hs-conid'>CharTrie</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>enum'</span> <span class='hs-varid'>toEnum</span> <span class='hs-varid'>t</span>
<a name="line-345"></a>
<a name="line-346"></a><span class='hs-comment'>-- Although Int is a Bits instance, we can't use bits directly for</span>
<a name="line-347"></a><span class='hs-comment'>-- memoizing, because the "bits" function gives an infinite result, since</span>
<a name="line-348"></a><span class='hs-comment'>-- shiftR (-1) 1 == -1.  Instead, convert between Int and Word, and use</span>
<a name="line-349"></a><span class='hs-comment'>-- a Word trie.  Any Integral type can be handled similarly.</span>
<a name="line-350"></a>
<a name="line-351"></a><span class='hs-cpp'>#define IntInstance(IntType,WordType,TrieType) \</span>
<a name="line-352"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>HasTrie</span> <span class='hs-conid'>IntType</span> <span class='hs-keyword'>where</span> <span class='hs-keyglyph'>\</span>
<a name="line-353"></a>    <span class='hs-keyword'>data</span> <span class='hs-conid'>IntType</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>TrieType</span> <span class='hs-layout'>(</span><span class='hs-conid'>WordType</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span><span class='hs-layout'>;</span> <span class='hs-keyglyph'>\</span>
<a name="line-354"></a>    <span class='hs-varid'>untrie</span> <span class='hs-layout'>(</span><span class='hs-conid'>TrieType</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-varid'>n</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>untrie</span> <span class='hs-varid'>t</span> <span class='hs-layout'>(</span><span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>n</span><span class='hs-layout'>)</span><span class='hs-layout'>;</span> <span class='hs-keyglyph'>\</span>
<a name="line-355"></a>    <span class='hs-varid'>trie</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>TrieType</span> <span class='hs-layout'>(</span><span class='hs-varid'>trie</span> <span class='hs-layout'>(</span><span class='hs-varid'>f</span> <span class='hs-varop'>.</span> <span class='hs-varid'>fromIntegral</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span><span class='hs-layout'>;</span> <span class='hs-keyglyph'>\</span>
<a name="line-356"></a>    <span class='hs-varid'>enumerate</span> <span class='hs-layout'>(</span><span class='hs-conid'>TrieType</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>enum'</span> <span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>t</span>
<a name="line-357"></a>
<a name="line-358"></a><span class='hs-conid'>IntInstance</span><span class='hs-layout'>(</span><span class='hs-conid'>Int</span><span class='hs-layout'>,</span><span class='hs-conid'>Word</span><span class='hs-layout'>,</span><span class='hs-conid'>IntTrie</span><span class='hs-layout'>)</span>
<a name="line-359"></a><span class='hs-conid'>IntInstance</span><span class='hs-layout'>(</span><span class='hs-conid'>Int8</span><span class='hs-layout'>,</span><span class='hs-conid'>Word8</span><span class='hs-layout'>,</span><span class='hs-conid'>Int8Trie</span><span class='hs-layout'>)</span>
<a name="line-360"></a><span class='hs-conid'>IntInstance</span><span class='hs-layout'>(</span><span class='hs-conid'>Int16</span><span class='hs-layout'>,</span><span class='hs-conid'>Word16</span><span class='hs-layout'>,</span><span class='hs-conid'>Int16Trie</span><span class='hs-layout'>)</span>
<a name="line-361"></a><span class='hs-conid'>IntInstance</span><span class='hs-layout'>(</span><span class='hs-conid'>Int32</span><span class='hs-layout'>,</span><span class='hs-conid'>Word32</span><span class='hs-layout'>,</span><span class='hs-conid'>Int32Trie</span><span class='hs-layout'>)</span>
<a name="line-362"></a><span class='hs-conid'>IntInstance</span><span class='hs-layout'>(</span><span class='hs-conid'>Int64</span><span class='hs-layout'>,</span><span class='hs-conid'>Word64</span><span class='hs-layout'>,</span><span class='hs-conid'>Int64Trie</span><span class='hs-layout'>)</span>
<a name="line-363"></a>
<a name="line-364"></a><span class='hs-comment'>-- For unbounded integers, we don't have a corresponding Word type, so</span>
<a name="line-365"></a><span class='hs-comment'>-- extract the sign bit.</span>
<a name="line-366"></a>
<a name="line-367"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>HasTrie</span> <span class='hs-conid'>Integer</span> <span class='hs-keyword'>where</span>
<a name="line-368"></a>    <span class='hs-keyword'>data</span> <span class='hs-conid'>Integer</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>IntegerTrie</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-conid'>Bool</span><span class='hs-layout'>,</span><span class='hs-keyglyph'>[</span><span class='hs-conid'>Bool</span><span class='hs-keyglyph'>]</span><span class='hs-layout'>)</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span>
<a name="line-369"></a>    <span class='hs-varid'>trie</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>IntegerTrie</span> <span class='hs-layout'>(</span><span class='hs-varid'>trie</span> <span class='hs-layout'>(</span><span class='hs-varid'>f</span> <span class='hs-varop'>.</span> <span class='hs-varid'>unbitsZ</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-370"></a>    <span class='hs-varid'>untrie</span> <span class='hs-layout'>(</span><span class='hs-conid'>IntegerTrie</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>untrie</span> <span class='hs-varid'>t</span> <span class='hs-varop'>.</span> <span class='hs-varid'>bitsZ</span>
<a name="line-371"></a>    <span class='hs-varid'>enumerate</span> <span class='hs-layout'>(</span><span class='hs-conid'>IntegerTrie</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>enum'</span> <span class='hs-varid'>unbitsZ</span> <span class='hs-varid'>t</span>
<a name="line-372"></a>
<a name="line-373"></a>
<a name="line-374"></a><a name="unbitsZ"></a><span class='hs-definition'>unbitsZ</span> <span class='hs-keyglyph'>::</span> <span class='hs-layout'>(</span><span class='hs-conid'>Bits</span> <span class='hs-varid'>n</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>Bool</span><span class='hs-layout'>,</span><span class='hs-keyglyph'>[</span><span class='hs-conid'>Bool</span><span class='hs-keyglyph'>]</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>n</span>
<a name="line-375"></a><span class='hs-definition'>unbitsZ</span> <span class='hs-layout'>(</span><span class='hs-varid'>positive</span><span class='hs-layout'>,</span><span class='hs-varid'>bs</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>sig</span> <span class='hs-layout'>(</span><span class='hs-varid'>unbits</span> <span class='hs-varid'>bs</span><span class='hs-layout'>)</span>
<a name="line-376"></a> <span class='hs-keyword'>where</span>
<a name="line-377"></a>   <span class='hs-varid'>sig</span> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>positive</span>  <span class='hs-keyglyph'>=</span> <span class='hs-varid'>id</span>
<a name="line-378"></a>       <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>negate</span>
<a name="line-379"></a>
<a name="line-380"></a><a name="bitsZ"></a><span class='hs-definition'>bitsZ</span> <span class='hs-keyglyph'>::</span> <span class='hs-layout'>(</span><span class='hs-conid'>Ord</span> <span class='hs-varid'>n</span><span class='hs-layout'>,</span> <span class='hs-conid'>Bits</span> <span class='hs-varid'>n</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-varid'>n</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>Bool</span><span class='hs-layout'>,</span><span class='hs-keyglyph'>[</span><span class='hs-conid'>Bool</span><span class='hs-keyglyph'>]</span><span class='hs-layout'>)</span>
<a name="line-381"></a><span class='hs-definition'>bitsZ</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varop'>&gt;=</span> <span class='hs-num'>0</span><span class='hs-layout'>)</span> <span class='hs-varop'>&amp;&amp;&amp;</span> <span class='hs-layout'>(</span><span class='hs-varid'>bits</span> <span class='hs-varop'>.</span> <span class='hs-varid'>abs</span><span class='hs-layout'>)</span>
<a name="line-382"></a>
<a name="line-383"></a><span class='hs-comment'>-- bitsZ n = (sign n, bits (abs n))</span>
<a name="line-384"></a>
<a name="line-385"></a>
<a name="line-386"></a>
<a name="line-387"></a><span class='hs-comment'>-- TODO: make these definitions more systematic.</span>
<a name="line-388"></a>
<a name="line-389"></a>
<a name="line-390"></a><span class='hs-comment'>---- Instances</span>
<a name="line-391"></a>
<a name="line-392"></a><span class='hs-comment'>{-
<a name="line-393"></a>
<a name="line-394"></a>The \"semantic function\" 'untrie' is a morphism over 'Monoid', 'Functor',
<a name="line-395"></a>'Applicative', 'Monad', 'Category', and 'Arrow', i.e.,
<a name="line-396"></a>
<a name="line-397"></a>  untrie mempty          == mempty
<a name="line-398"></a>  untrie (s `mappend` t) == untrie s `mappend` untrie t
<a name="line-399"></a>
<a name="line-400"></a>  untrie (fmap f t)      == fmap f (untrie t)
<a name="line-401"></a>
<a name="line-402"></a>  untrie (pure a)        == pure a
<a name="line-403"></a>  untrie (tf &lt;*&gt; tx)     == untrie tf &lt;*&gt; untrie tx
<a name="line-404"></a>
<a name="line-405"></a>  untrie (return a)      == return a
<a name="line-406"></a>  untrie (u &gt;&gt;= k)       == untrie u &gt;&gt;= untrie . k
<a name="line-407"></a>
<a name="line-408"></a>  untrie id              == id
<a name="line-409"></a>  untrie (s . t)         == untrie s . untrie t
<a name="line-410"></a>
<a name="line-411"></a>  untrie (arr f)         == arr f
<a name="line-412"></a>  untrie (first t)       == first (untrie t)
<a name="line-413"></a>
<a name="line-414"></a>These morphism properties imply that all of the expected laws hold,
<a name="line-415"></a>assuming that we interpret equality semantically (or observationally).
<a name="line-416"></a>For instance,
<a name="line-417"></a>
<a name="line-418"></a>  untrie (mempty `mappend` a)
<a name="line-419"></a>    == untrie mempty `mappend` untrie a
<a name="line-420"></a>    == mempty `mappend` untrie a
<a name="line-421"></a>    == untrie a
<a name="line-422"></a>
<a name="line-423"></a>  untrie (fmap f (fmap g a))
<a name="line-424"></a>    == fmap f (untrie (fmap g a))
<a name="line-425"></a>    == fmap f (fmap g (untrie a))
<a name="line-426"></a>    == fmap (f.g) (untrie a)
<a name="line-427"></a>    == untrie (fmap (f.g) a)
<a name="line-428"></a>
<a name="line-429"></a>The implementation instances then follow from applying 'trie' to both
<a name="line-430"></a>sides of each of these morphism laws.
<a name="line-431"></a>
<a name="line-432"></a>-}</span>
<a name="line-433"></a>
<a name="line-434"></a><span class='hs-comment'>{-
<a name="line-435"></a>instance (HasTrie a, Monoid b) =&gt; Monoid (a :-&gt;: b) where
<a name="line-436"></a>  mempty  = trie mempty
<a name="line-437"></a>  s `mappend` t = trie (untrie s `mappend` untrie t)
<a name="line-438"></a>
<a name="line-439"></a>instance HasTrie a =&gt; Functor ((:-&gt;:) a) where
<a name="line-440"></a>  fmap f t      = trie (fmap f (untrie t))
<a name="line-441"></a>
<a name="line-442"></a>instance HasTrie a =&gt; Applicative ((:-&gt;:) a) where
<a name="line-443"></a>  pure b        = trie (pure b)
<a name="line-444"></a>  tf &lt;*&gt; tx     = trie (untrie tf &lt;*&gt; untrie tx)
<a name="line-445"></a>
<a name="line-446"></a>instance HasTrie a =&gt; Monad ((:-&gt;:) a) where
<a name="line-447"></a>  return a      = trie (return a)
<a name="line-448"></a>  u &gt;&gt;= k       = trie (untrie u &gt;&gt;= untrie . k)
<a name="line-449"></a>
<a name="line-450"></a>-- instance Category (:-&gt;:) where
<a name="line-451"></a>--   id            = trie id
<a name="line-452"></a>--   s . t         = trie (untrie s . untrie t)
<a name="line-453"></a>
<a name="line-454"></a>-- instance Arrow (:-&gt;:) where
<a name="line-455"></a>--   arr f         = trie (arr f)
<a name="line-456"></a>--   first t       = trie (first (untrie t))
<a name="line-457"></a>-}</span>
<a name="line-458"></a>
<a name="line-459"></a><span class='hs-comment'>-- Simplify, using inTrie, inTrie2</span>
<a name="line-460"></a>
<a name="line-461"></a><span class='hs-keyword'>instance</span> <span class='hs-layout'>(</span><span class='hs-conid'>HasTrie</span> <span class='hs-varid'>a</span><span class='hs-layout'>,</span> <span class='hs-conid'>Monoid</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>Monoid</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
<a name="line-462"></a>  <span class='hs-varid'>mempty</span>  <span class='hs-keyglyph'>=</span> <span class='hs-varid'>trie</span> <span class='hs-varid'>mempty</span>
<a name="line-463"></a>  <span class='hs-varid'>mappend</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>inTrie2</span> <span class='hs-varid'>mappend</span>
<a name="line-464"></a>
<a name="line-465"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>HasTrie</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>Functor</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-conop'>:-&gt;:</span><span class='hs-layout'>)</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
<a name="line-466"></a>  <span class='hs-varid'>fmap</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>inTrie</span> <span class='hs-layout'>(</span><span class='hs-varid'>fmap</span> <span class='hs-varid'>f</span><span class='hs-layout'>)</span>
<a name="line-467"></a>
<a name="line-468"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>HasTrie</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>Applicative</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-conop'>:-&gt;:</span><span class='hs-layout'>)</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
<a name="line-469"></a>  <span class='hs-varid'>pure</span> <span class='hs-varid'>b</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>trie</span> <span class='hs-layout'>(</span><span class='hs-varid'>pure</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span>
<a name="line-470"></a>  <span class='hs-layout'>(</span><span class='hs-varop'>&lt;*&gt;</span><span class='hs-layout'>)</span>  <span class='hs-keyglyph'>=</span> <span class='hs-varid'>inTrie2</span> <span class='hs-layout'>(</span><span class='hs-varop'>&lt;*&gt;</span><span class='hs-layout'>)</span>
<a name="line-471"></a>
<a name="line-472"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>HasTrie</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>Monad</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-conop'>:-&gt;:</span><span class='hs-layout'>)</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
<a name="line-473"></a>  <span class='hs-varid'>return</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>trie</span> <span class='hs-layout'>(</span><span class='hs-varid'>return</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span>
<a name="line-474"></a>  <span class='hs-varid'>u</span> <span class='hs-varop'>&gt;&gt;=</span> <span class='hs-varid'>k</span>  <span class='hs-keyglyph'>=</span> <span class='hs-varid'>trie</span> <span class='hs-layout'>(</span><span class='hs-varid'>untrie</span> <span class='hs-varid'>u</span> <span class='hs-varop'>&gt;&gt;=</span> <span class='hs-varid'>untrie</span> <span class='hs-varop'>.</span> <span class='hs-varid'>k</span><span class='hs-layout'>)</span>
<a name="line-475"></a>
<a name="line-476"></a><a name="idTrie"></a><span class='hs-comment'>-- | Identity trie</span>
<a name="line-477"></a><span class='hs-definition'>idTrie</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>HasTrie</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-varid'>a</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>a</span>
<a name="line-478"></a><span class='hs-definition'>idTrie</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>trie</span> <span class='hs-varid'>id</span>
<a name="line-479"></a>
<a name="line-480"></a><span class='hs-keyword'>infixr</span> <span class='hs-num'>9</span> <span class='hs-varop'>@.@</span>
<a name="line-481"></a><a name="@.@"></a><span class='hs-comment'>-- | Trie composition</span>
<a name="line-482"></a><span class='hs-layout'>(</span><span class='hs-varop'>@.@</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>::</span> <span class='hs-layout'>(</span><span class='hs-conid'>HasTrie</span> <span class='hs-varid'>a</span><span class='hs-layout'>,</span> <span class='hs-conid'>HasTrie</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=&gt;</span>
<a name="line-483"></a>         <span class='hs-layout'>(</span><span class='hs-varid'>b</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>c</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-conop'>:-&gt;:</span> <span class='hs-varid'>c</span><span class='hs-layout'>)</span>
<a name="line-484"></a><span class='hs-layout'>(</span><span class='hs-varop'>@.@</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>inTrie2</span> <span class='hs-layout'>(</span><span class='hs-varop'>.</span><span class='hs-layout'>)</span>
<a name="line-485"></a>
<a name="line-486"></a>
<a name="line-487"></a>
<a name="line-488"></a><span class='hs-comment'>-- instance Category (:-&gt;:) where</span>
<a name="line-489"></a><span class='hs-comment'>--   id  = idTrie</span>
<a name="line-490"></a><span class='hs-comment'>--   (.) = (.:)</span>
<a name="line-491"></a>
<a name="line-492"></a><span class='hs-comment'>-- instance Arrow (:-&gt;:) where</span>
<a name="line-493"></a><span class='hs-comment'>--   arr f = trie (arr f)</span>
<a name="line-494"></a><span class='hs-comment'>--   first = inTrie first</span>
<a name="line-495"></a>
<a name="line-496"></a><span class='hs-comment'>{-
<a name="line-497"></a>
<a name="line-498"></a>Correctness of these instances follows by applying 'untrie' to each side
<a name="line-499"></a>of each definition and using the property @'untrie' . 'trie' == 'id'@.
<a name="line-500"></a>
<a name="line-501"></a>The `Category` and `Arrow` instances don't quite work, however, because of
<a name="line-502"></a>necessary but disallowed `HasTrie` constraints on the domain type.
<a name="line-503"></a>
<a name="line-504"></a>-}</span>
<a name="line-505"></a>
<a name="line-506"></a>
<a name="line-507"></a><span class='hs-comment'>---- To go elsewhere</span>
<a name="line-508"></a>
<a name="line-509"></a><span class='hs-comment'>-- Matt Hellige's notation for @argument f . result g@.</span>
<a name="line-510"></a><span class='hs-comment'>-- &lt;<a href="http://matt.immute.net/content/pointless-fun">http://matt.immute.net/content/pointless-fun</a>&gt;</span>
<a name="line-511"></a>
<a name="line-512"></a><a name="~>"></a><span class='hs-layout'>(</span><span class='hs-varop'>~&gt;</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>::</span> <span class='hs-layout'>(</span><span class='hs-varid'>a'</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>b</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>b'</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>a'</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>b'</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-513"></a><a name="g"></a><span class='hs-definition'>g</span> <span class='hs-varop'>~&gt;</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>f</span> <span class='hs-varop'>.</span><span class='hs-layout'>)</span> <span class='hs-varop'>.</span> <span class='hs-layout'>(</span><span class='hs-varop'>.</span> <span class='hs-varid'>g</span><span class='hs-layout'>)</span>
<a name="line-514"></a>
<a name="line-515"></a><span class='hs-comment'>{-
<a name="line-516"></a>-- Examples
<a name="line-517"></a>f1,f1' :: Int -&gt; Int
<a name="line-518"></a>f1 n = n + n
<a name="line-519"></a>
<a name="line-520"></a>f1' = memo f1
<a name="line-521"></a>-}</span>
</pre></body>
</html>