<?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>LAMBDAPHONE &#187; library</title>
	<atom:link href="http://coder.bsimmons.name/blog/tag/library/feed/" rel="self" type="application/rss+xml" />
	<link>http://coder.bsimmons.name/blog</link>
	<description>fragmentary ideas  ䷿  intellectual what-nots  ䷷  and haskell programming  ䷴</description>
	<lastBuildDate>Tue, 27 Jul 2010 16:58:03 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>An alternative definition for Data.List.groupBy</title>
		<link>http://coder.bsimmons.name/blog/2010/02/an-alternative-definition-for-datalistgroupby/</link>
		<comments>http://coder.bsimmons.name/blog/2010/02/an-alternative-definition-for-datalistgroupby/#comments</comments>
		<pubDate>Wed, 10 Feb 2010 18:15:50 +0000</pubDate>
		<dc:creator>jberryman</dc:creator>
				<category><![CDATA[haskell]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[short]]></category>
		<category><![CDATA[sorting]]></category>

		<guid isPermaLink="false">http://coder.bsimmons.name/blog/?p=318</guid>
		<description><![CDATA[<p>The function <a href="http://haskell.org/ghc/docs/latest/html/libraries/base-4.2.0.0/Data-List.html#v:groupBy"><code>groupBy</code></a> from haskell&#8217;s standard library is defined in terms of <code>span</code>, the effect being that the supplied predicate function is used to compare the first element of a group with successive elements.</p>
<p>This isn&#8217;t clear from the&#8230; <a href="http://coder.bsimmons.name/blog/2010/02/an-alternative-definition-for-datalistgroupby/" class="read_more">   [ R E A D &#124; M O R E ]</a></p>]]></description>
			<content:encoded><![CDATA[<p>The function <a href="http://haskell.org/ghc/docs/latest/html/libraries/base-4.2.0.0/Data-List.html#v:groupBy"><code>groupBy</code></a> from haskell&#8217;s standard library is defined in terms of <code>span</code>, the effect being that the supplied predicate function is used to compare the first element of a group with successive elements.</p>
<p>This isn&#8217;t clear from the docs, and you might try to do this and wonder at the output you got:</p>
<blockquote><pre>*Main> groupBy (< =) [3,4,5,3,2,1,4,4,1,1,2,3,4,5,4,5,6,7]
[[3,4,5,3],[2],[1,4,4,1,1,2,3,4,5,4,5,6,7]]</pre>
</pre>
</blockquote>
<p><span id="more-318"></span></p>
<p>We can redefine <code>groupBy</code> as follows, so that the supplied predicate function compares adjacent elements one-by-one and returns <code>True</code> if they should be grouped together:</p>
<p><blockquote class="vimblock"><br />
<span class="Comment">&gt;</span>&nbsp;groupBy' <span class="Statement">::</span>&nbsp;(a&nbsp;<span class="Statement">-&gt;</span>&nbsp;a&nbsp;<span class="Statement">-&gt;</span>&nbsp;<span class="Type">Bool</span>)&nbsp;<span class="Statement">-&gt;</span>&nbsp;[a]&nbsp;<span class="Statement">-&gt;</span>&nbsp;[[a]]<br />
<span class="Comment">&gt;</span>&nbsp;groupBy' c&nbsp;[]&nbsp;&nbsp;&nbsp;&nbsp; <span class="Statement">=</span>&nbsp;[]<br />
<span class="Comment">&gt;</span>&nbsp;groupBy' c&nbsp;(a<span class="Statement">:</span>as)&nbsp;<span class="Statement">=</span>&nbsp;(a<span class="Statement">:</span>ys)&nbsp;<span class="Statement">:</span>&nbsp;groupBy' c&nbsp;zs<br />
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp; <span class="Type">where</span>&nbsp;(ys,zs)&nbsp;<span class="Statement">=</span>&nbsp;spanC&nbsp;a&nbsp;as<br />
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spanC&nbsp;_&nbsp;&nbsp;[]&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">=</span>&nbsp;([],&nbsp;[])<br />
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spanC&nbsp;a' (x<span class="Statement">:</span>xs)<br />
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Statement">|</span>&nbsp;a' <span class="Statement">`c`</span>&nbsp;x&nbsp;&nbsp; <span class="Statement">=</span>&nbsp;<span class="Statement">let</span>&nbsp;(ps,qs)&nbsp;<span class="Statement">=</span>&nbsp;spanC&nbsp;x&nbsp;xs&nbsp;<br />
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">in</span>&nbsp;(x<span class="Statement">:</span>ps,qs)<br />
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Statement">|</span>&nbsp;<span class="Identifier">otherwise</span>&nbsp;<span class="Statement">=</span>&nbsp;([],&nbsp;x<span class="Statement">:</span>xs)<br />
<br /></blockquote></p>
<p>Now we can use the <code>groupBy</code> function to return a list of ascending lists, like we (probably) wanted:</p>
<blockquote><pre>*Main> groupBy' (< =) [3,4,5,3,2,1,4,4,1,1,2,3,4,5,4,5,6,7]
[[3,4,5],[3],[2],[1,4,4],[1,1,2,3,4,5],[4,5,6,7]]</pre>
</pre>
</blockquote>
<p>The functionality is of course the same for <code>groupBy (==)</code>.</p>
]]></content:encoded>
			<wfw:commentRss>http://coder.bsimmons.name/blog/2010/02/an-alternative-definition-for-datalistgroupby/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>The Definition of Data.List.group</title>
		<link>http://coder.bsimmons.name/blog/2010/02/the-definition-of-datalistgroup/</link>
		<comments>http://coder.bsimmons.name/blog/2010/02/the-definition-of-datalistgroup/#comments</comments>
		<pubDate>Sat, 06 Feb 2010 16:00:40 +0000</pubDate>
		<dc:creator>jberryman</dc:creator>
				<category><![CDATA[haskell]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[short]]></category>

		<guid isPermaLink="false">http://coder.bsimmons.name/blog/?p=312</guid>
		<description><![CDATA[<p>I&#8217;ve been thinking quite a bit lately about a category of functions that are always a bit awkward to define: they involve cases where we would like to traverse a recursive data structure and do something with the data that&#8230; <a href="http://coder.bsimmons.name/blog/2010/02/the-definition-of-datalistgroup/" class="read_more">   [ R E A D &#124; M O R E ]</a></p>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been thinking quite a bit lately about a category of functions that are always a bit awkward to define: they involve cases where we would like to traverse a recursive data structure and do something with the data that we have passed over but which is &#8220;gone now&#8221;.<br />
<span id="more-312"></span><br />
There are many examples of functions like these in the haskell standard libraries: <code><a href="http://haskell.org/ghc/docs/latest/html/libraries/base-4.2.0.0/src/GHC-List.html#span">span</a></code>, <code><a href="http://haskell.org/ghc/docs/latest/html/libraries/base-4.2.0.0/src/GHC-List.html#splitAt">splitAt</a></code>, etc.</p>
<p>A function like <code>group</code> is in this category. It&#8217;s conceptually very simple, but defining it actually requires a bit of indirection. Here I&#8217;ve translated the definition from <code>Data.List</code> to use explicit recursion:</p>
<p><blockquote class="vimblock"><br />
<span class="lnr">66 </span><span class="Comment">&gt;</span>&nbsp;group&nbsp;<span class="Statement">::</span>&nbsp;(<span class="Type">Eq</span>&nbsp;a)&nbsp;<span class="Statement">=&gt;</span>&nbsp;[a]&nbsp;<span class="Statement">-&gt;</span>&nbsp;[[a]]<br />
<span class="lnr">67 </span><span class="Comment">&gt;</span>&nbsp;group&nbsp;[]&nbsp;&nbsp;&nbsp;&nbsp; <span class="Statement">=</span>&nbsp;[]<br />
<span class="lnr">68 </span><span class="Comment">&gt;</span>&nbsp;group&nbsp;(a<span class="Statement">:</span>as)&nbsp;<span class="Statement">=</span>&nbsp;(a<span class="Statement">:</span>ys)&nbsp;<span class="Statement">:</span>&nbsp;group&nbsp;zs<br />
<span class="lnr">69 </span><span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp; <span class="Type">where</span>&nbsp;(ys,zs)&nbsp;<span class="Statement">=</span>&nbsp;spanEq&nbsp;as<br />
<span class="lnr">70 </span><span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spanEq&nbsp;[]&nbsp;&nbsp;&nbsp;&nbsp; <span class="Statement">=</span>&nbsp;([],&nbsp;[])<br />
<span class="lnr">71 </span><span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spanEq&nbsp;(x<span class="Statement">:</span>xs)<br />
<span class="lnr">72 </span><span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Statement">|</span>&nbsp;a&nbsp;<span class="Statement">==</span>&nbsp;x&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">=</span>&nbsp;<span class="Statement">let</span>&nbsp;(ps,qs)&nbsp;<span class="Statement">=</span>&nbsp;spanEq&nbsp;xs&nbsp;<br />
<span class="lnr">73 </span><span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">in</span>&nbsp;(x<span class="Statement">:</span>ps,qs)<br />
<span class="lnr">74 </span><span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Statement">|</span>&nbsp;<span class="Identifier">otherwise</span>&nbsp;<span class="Statement">=</span>&nbsp;([],&nbsp;x<span class="Statement">:</span>xs)<br />
<span class="lnr">75 </span><br />
<br /></blockquote></p>
<p>I think if I were asked to define this having never seen it, the first thing I would think of would be something using <code>foldl1</code>, which wouldn&#8217;t work.</p>
<p><em><strong>EDIT</strong>:</em> see also <a href="http://coder.bsimmons.name/blog/2010/02/an-alternative-definition-for-datalistgroupby/">an alternative definition for Data.List.groupBy</a></p>
]]></content:encoded>
			<wfw:commentRss>http://coder.bsimmons.name/blog/2010/02/the-definition-of-datalistgroup/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cracking a Lock in Haskell with the De Bruijn sequence, pt. 2</title>
		<link>http://coder.bsimmons.name/blog/2009/09/cracking-a-lock-in-haskell-with-the-de-bruijn-sequence-pt-2/</link>
		<comments>http://coder.bsimmons.name/blog/2009/09/cracking-a-lock-in-haskell-with-the-de-bruijn-sequence-pt-2/#comments</comments>
		<pubDate>Tue, 29 Sep 2009 22:10:58 +0000</pubDate>
		<dc:creator>jberryman</dc:creator>
				<category><![CDATA[haskell]]></category>
		<category><![CDATA[algorithm]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[monads]]></category>
		<category><![CDATA[sequences]]></category>
		<category><![CDATA[Tree]]></category>

		<guid isPermaLink="false">http://coder.bsimmons.name/blog/?p=221</guid>
		<description><![CDATA[<p>For this post I will rework the <a href="http://coder.bsimmons.name/blog/2009/09/cracking-a-lock-in-haskell-with-the-de-bruijn-sequence-pt-1/">Prefer One algorithm from<br />
the previous post</a> so that it is much more efficient. We will<br />
add words to a <a href="http://en.wikipedia.org/wiki/Patricia_tree">Patricia Tree</a>-like dictionary as we see them,<br />
passing&#8230; <a href="http://coder.bsimmons.name/blog/2009/09/cracking-a-lock-in-haskell-with-the-de-bruijn-sequence-pt-2/" class="read_more">   [ R E A D &#124; M O R E ]</a></p>]]></description>
			<content:encoded><![CDATA[<p>For this post I will rework the <a href="http://coder.bsimmons.name/blog/2009/09/cracking-a-lock-in-haskell-with-the-de-bruijn-sequence-pt-1/">Prefer One algorithm from<br />
the previous post</a> so that it is much more efficient. We will<br />
add words to a <a href="http://en.wikipedia.org/wiki/Patricia_tree">Patricia Tree</a>-like dictionary as we see them,<br />
passing the tree along in the State monad; to check if a new<br />
word has been seen we simply check in the tree, rather than<br />
in the array.</p>
<p>First, a little boilerplate&#8230;</p>
<p><div class="vimblock"><br>
<span class="Comment">&gt;</span>&nbsp;<span class="Type">module</span>&nbsp;Main<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp; <span class="Type">where</span><br>
<span class="Comment">&gt;</span><br>
<span class="Comment">&gt;</span>&nbsp;<span class="PreProc">import</span>&nbsp;Data.Array<br>
<span class="Comment">&gt;</span>&nbsp;<span class="PreProc">import</span>&nbsp;Data.List(isInfixOf, tails)<br>
<span class="Comment">&gt;</span><br>
<span class="Comment">&gt;</span>&nbsp;<span class="PreProc">import</span>&nbsp;Control.Monad.State<br>
<span class="Comment">&gt;</span>&nbsp;<span class="PreProc">import</span>&nbsp;Control.Arrow<br>
<br></div></p>
<h3>NEW IMPLEMENTATION:</h3>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>In the previous implementation, to check if the word formed<br />
by adding a one has been seen, we had to iterate through each<br />
of the previous bits in the array, checking words.</p>
<p>For example for words of length 3, finding the 7th bit (?)<br />
by checking if 111 has already been seen:</p>
<pre>
        /-----\  ==>  111
0 0 0 1 1 1 (1)...
\----/         000 == 111  No
  \----/       001 == 111  No
    \----/     011 == 111  No
      \----/   111 == 111  Yes, so this bit must be (0)
</pre>
<p>This is extremely inefficient. What we want is to be able to<br />
store all the previous words that we&#8217;ve encountered in an easily-<br />
searchable data structure. </p>
<p>In the example above, we would like the three words that we&#8217;ve<br />
seen to be stored in what might be called a Trie, so that our<br />
search instead looks like the following:</p>
<pre>
       /\
      0  1         1 - in tree, go right
     / \  \
    0   1  1       1 - in tree, go right
   / \   \  \
  0   1   1  1     1 - in tree, we've already seen 111,
                       so the last bit must be 0
</pre>
<p>Our new data structure will look like this:</p>
<p><div class="vimblock"><br>
<span class="Comment">&gt;</span>&nbsp;<span class="Type">data</span>&nbsp;Tree&nbsp;<span class="Statement">=</span>&nbsp;Bs&nbsp;Tree&nbsp;Tree&nbsp;&nbsp;<span class="Comment">-- Bs (zero_bit) (one_bit)</span><br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Statement">|</span>&nbsp;X&nbsp;<span class="Comment">-- incomplete word</span><br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Statement">|</span>&nbsp;B&nbsp;<span class="Comment">-- final bit of word</span><br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Type">deriving</span>&nbsp;<span class="Type">Show</span><br>
<br></div></p>
<p>We&#8217;ll need to build a new tree from a list of bits, appending<br />
a final bit (1, except for the initial tree):</p>
<p><div class="vimblock"><br>
<span class="Comment">&gt;</span>&nbsp;treeWithFinal1&nbsp;<span class="Statement">=</span>&nbsp;mkTree&nbsp;<span class="Constant">True</span><br>
<span class="Comment">&gt;</span>&nbsp;treeWithFinal0&nbsp;<span class="Statement">=</span>&nbsp;mkTree&nbsp;<span class="Constant">False</span><br>
<span class="Comment">&gt;</span><br>
<span class="Comment">&gt;</span><br>
<span class="Comment">&gt;</span>&nbsp;mkTree&nbsp;<span class="Statement">::</span>&nbsp;Bit&nbsp;<span class="Statement">-&gt;</span>&nbsp;[Bit]&nbsp;<span class="Statement">-&gt;</span>&nbsp;Tree<br>
<span class="Comment">&gt;</span>&nbsp;mkTree&nbsp;p&nbsp;<span class="Statement">=</span>&nbsp;<span class="Identifier">foldr</span>&nbsp;mkBranch&nbsp;(<span class="Statement">if</span>&nbsp;p&nbsp;<span class="Statement">then</span>&nbsp;Bs&nbsp;X&nbsp;B&nbsp;<span class="Statement">else</span>&nbsp;Bs&nbsp;B&nbsp;X)&nbsp;&nbsp; <br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp; <span class="Type">where</span>&nbsp;mkBranch&nbsp;b&nbsp;<span class="Statement">|</span>&nbsp;b&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Statement">=</span>&nbsp;Bs&nbsp;X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="Comment">--1</span><br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">|</span>&nbsp;<span class="Identifier">otherwise</span>&nbsp;<span class="Statement">=</span>&nbsp;<span class="Identifier">flip</span>&nbsp;Bs&nbsp;X&nbsp;<span class="Comment">--0</span><br>
<br>
<br></div></p>
<p>Finally, here is our new algorithm. The tree is passed in the<br />
State monad, through the use of mapM. The state monad is a little<br />
tricky sometimes:</p>
<p><div class="vimblock"><br>
<span class="Comment">&gt;</span>&nbsp;preferOneV2&nbsp;<span class="Statement">::</span>&nbsp;<span class="Type">Int</span>&nbsp;<span class="Statement">-&gt;</span>&nbsp;[&nbsp;Bit&nbsp;]<br>
<span class="Comment">&gt;</span>&nbsp;preferOneV2&nbsp;n&nbsp;<span class="Statement">=</span>&nbsp;<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp; <span class="Statement">let</span>&nbsp;upB&nbsp;<span class="Statement">=</span>&nbsp;<span class="Constant">2</span><span class="Statement">^</span>n<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Comment">-- the whole bit sequence (one period):</span><br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bs&nbsp;<span class="Statement">=</span>&nbsp;&nbsp;<span class="Identifier">take</span>&nbsp;upB&nbsp;(<span class="Identifier">replicate</span>&nbsp;n&nbsp;<span class="Constant">False</span>&nbsp;<span class="Statement">++</span>&nbsp;bs')<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (wp0<span class="Statement">:</span>wordPrefixes)&nbsp;<span class="Statement">=</span>&nbsp;[&nbsp;<span class="Identifier">take</span>&nbsp;(n<span class="Statement">-</span><span class="Constant">1</span>)&nbsp;w&nbsp;<span class="Statement">|</span>&nbsp;w&nbsp;<span class="Statement">&lt;-</span>&nbsp;tails&nbsp;bs&nbsp;]<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Comment">-- pass our Tree around in the State monad</span><br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; state0&nbsp;<span class="Statement">=</span>&nbsp;treeWithFinal0&nbsp;wp0<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Comment">-- thisBit is partially applied, after which we wrap the</span><br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Comment">-- function in a State constructor to make our :: m a</span><br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bsM'&nbsp;&nbsp;<span class="Statement">=</span>&nbsp;<span class="Identifier">mapM</span>&nbsp;(State&nbsp;<span class="Statement">.</span>&nbsp;thisBit)&nbsp;wordPrefixes<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (bs',tree)&nbsp;<span class="Statement">=</span>&nbsp;runState&nbsp;bsM' state0<br>
<span class="Comment">&gt;</span><br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Comment">-- an infinite stream is returned... because I can:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">in</span>&nbsp;<span class="Identifier">cycle</span>&nbsp;bs<br>
<br>
<br></div></p>
<p>With the following function, after we apply it to the word we&#8217;re searching<br />
for, it becomes a function :: state -> (val,state), suitable for the<br />
State monad:</p>
<p>Takes a list of the last n-1 Bits (Bools) and traverses a Tree which we&#8217;ve<br />
been using to keep track of the words we&#8217;ve already seen. We fold the Bit<br />
list into the tree. When we get to the endo of the list, we look for a One.<br />
We return the new bit as well as the new Tree:</p>
<p><div class="vimblock"><br>
<span class="Comment">&gt;</span>&nbsp;thisBit&nbsp;<span class="Statement">::</span>&nbsp;[&nbsp;Bit&nbsp;]&nbsp;<span class="Statement">-&gt;</span>&nbsp;Tree&nbsp;<span class="Statement">-&gt;</span>&nbsp;(Bit,&nbsp;Tree)<br>
<br></div></p>
<p>We&#8217;re at a Zero bit,</p>
<p><div class="vimblock"><br>
<span class="Comment">&gt;</span>&nbsp;thisBit&nbsp;(<span class="Constant">False</span><span class="Statement">:</span>bs)&nbsp;(Bs&nbsp;X&nbsp;o)&nbsp;<span class="Statement">=</span>&nbsp;(<span class="Constant">True</span>,&nbsp;Bs&nbsp;(treeWithFinal1&nbsp;bs)&nbsp;o)&nbsp;<span class="Comment">-- last bit must be 1</span><br>
<span class="Comment">&gt;</span>&nbsp;thisBit&nbsp;(<span class="Constant">False</span><span class="Statement">:</span>bs)&nbsp;(Bs&nbsp;z&nbsp;o)&nbsp;<span class="Statement">=</span>&nbsp;(<span class="Identifier">id</span>&nbsp;<span class="Statement">***</span>&nbsp;<span class="Identifier">flip</span>&nbsp;Bs&nbsp;o)&nbsp;(thisBit&nbsp;bs&nbsp;z)<br>
<br></div></p>
<p>&#8230;a One bit,</p>
<p><div class="vimblock"><br>
<span class="Comment">&gt;</span>&nbsp;thisBit&nbsp;(<span class="Constant">True</span><span class="Statement">:</span>bs)&nbsp;(Bs&nbsp;z&nbsp;X)&nbsp;<span class="Statement">=</span>&nbsp;(<span class="Constant">True</span>,&nbsp;Bs&nbsp;z&nbsp;(treeWithFinal1&nbsp;bs))&nbsp;<br>
<span class="Comment">&gt;</span>&nbsp;thisBit&nbsp;(<span class="Constant">True</span><span class="Statement">:</span>bs)&nbsp;(Bs&nbsp;z&nbsp;o)&nbsp;<span class="Statement">=</span>&nbsp;(<span class="Identifier">id</span>&nbsp;<span class="Statement">***</span>&nbsp;Bs&nbsp;z)&nbsp;(thisBit&nbsp;bs&nbsp;o)<br>
<br></div></p>
<p>&#8230;or else propose a One for the last bit:</p>
<p><div class="vimblock"><br>
<span class="Comment">&gt;</span>&nbsp;thisBit&nbsp;[]&nbsp;(Bs&nbsp;_&nbsp;o)&nbsp;<span class="Statement">=</span>&nbsp;(b&nbsp;,&nbsp;(Bs&nbsp;z&nbsp;B))&nbsp;<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp; <span class="Comment">-- we know that if the One bit has been seen (B) then we must</span><br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp; <span class="Comment">-- place a zero. we assume then that the Zero bit is (X):</span><br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp; <span class="Type">where</span>&nbsp;(b,&nbsp;z)&nbsp;<span class="Statement">=</span>&nbsp;<span class="Statement">case</span>&nbsp;o&nbsp;<span class="Statement">of</span>&nbsp;<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Comment">-- this bit = 1, Zero branch = nil</span><br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; X&nbsp;<span class="Statement">-&gt;</span>&nbsp;(<span class="Constant">True</span>,&nbsp;&nbsp;X)&nbsp;<span class="Comment">-- 1</span><br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Comment">-- this bit = 0, Zero branch = last word bit</span><br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _&nbsp;<span class="Statement">-&gt;</span>&nbsp;(<span class="Constant">False</span>,&nbsp;B)&nbsp;<span class="Comment">-- 0</span><br>
<br>
<br></div></p>
<h3>TEST FUNCTIONS:</h3>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>This code is copied from the previous post:</p>
<p>We use Bool for bits, where False ==> 0, True ==> 1:</p>
<p><div class="vimblock"><br>
<span class="Comment">&gt;</span>&nbsp;<span class="Type">type</span>&nbsp;Bit&nbsp;<span class="Statement">=</span>&nbsp;<span class="Type">Bool</span><br>
<br></div></p>
<p>Our garage-door lock model for testing the function:</p>
<p><div class="vimblock"><br>
<span class="Comment">&gt;</span>&nbsp;<span class="Type">type</span>&nbsp;Combo&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">=</span>&nbsp;[&nbsp;Bit&nbsp;]<br>
<span class="Comment">&gt;</span>&nbsp;<span class="Type">type</span>&nbsp;Receiver&nbsp;<span class="Statement">=</span>&nbsp;Combo&nbsp;<span class="Statement">-&gt;</span>&nbsp;<span class="Type">Bool</span><br>
<br></div></p>
<p>True means access granted:</p>
<p><div class="vimblock"><br>
<span class="Comment">&gt;</span>&nbsp;programReceiver&nbsp;<span class="Statement">::</span>&nbsp;Combo&nbsp;<span class="Statement">-&gt;</span>&nbsp;Receiver<br>
<span class="Comment">&gt;</span>&nbsp;programReceiver&nbsp;<span class="Statement">=</span>&nbsp;isInfixOf&nbsp;<br>
<br></div></p>
<p>Test out our function:</p>
<p><div class="vimblock"><br>
<span class="Comment">&gt;</span>&nbsp;main&nbsp;<span class="Statement">=</span>&nbsp;&nbsp;<span class="Statement">let</span>&nbsp;secretCode&nbsp;<span class="Statement">=</span>&nbsp;[<span class="Constant">True</span>,<span class="Constant">True</span>,<span class="Constant">False</span>,<span class="Constant">False</span>,<span class="Constant">True</span>,<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Constant">False</span>,<span class="Constant">True</span>,<span class="Constant">False</span>,<span class="Constant">True</span>,<span class="Constant">True</span>]<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; receiver&nbsp;<span class="Statement">=</span>&nbsp;programReceiver&nbsp;secretCode<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; crackingStream&nbsp;<span class="Statement">=</span>&nbsp;preferOneV2&nbsp;<span class="Constant">10</span><br>
<span class="Comment">&gt;</span><br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">in</span>&nbsp;<span class="Statement">if</span>&nbsp;receiver&nbsp;crackingStream<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Statement">then</span>&nbsp;<span class="Identifier">print</span>&nbsp;<span class="Constant">&quot;WE'RE IN!&quot;</span><br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Statement">else</span>&nbsp;<span class="Identifier">print</span>&nbsp;<span class="Constant">&quot;...bugs&quot;</span><br>
<span class="Comment">&gt;</span><br>
<br></div></p>
<p>Stay tuned for one more post on these algorithms.</p>
]]></content:encoded>
			<wfw:commentRss>http://coder.bsimmons.name/blog/2009/09/cracking-a-lock-in-haskell-with-the-de-bruijn-sequence-pt-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Proposed modification to &#8216;array&#8217; function in Data.Array</title>
		<link>http://coder.bsimmons.name/blog/2009/09/proposed-modification-to-array-function-in-dataarray/</link>
		<comments>http://coder.bsimmons.name/blog/2009/09/proposed-modification-to-array-function-in-dataarray/#comments</comments>
		<pubDate>Tue, 22 Sep 2009 03:09:33 +0000</pubDate>
		<dc:creator>jberryman</dc:creator>
				<category><![CDATA[haskell]]></category>
		<category><![CDATA[Array]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[library]]></category>

		<guid isPermaLink="false">http://coder.bsimmons.name/blog/?p=211</guid>
		<description><![CDATA[<p>In Data.Array the function <code>array :: (IArray a e, Ix i) => (i, i) -> [(i, e)] -> a i e</code> takes the array bounds and an association list, and it produces an <code>Array</code>. The function allows you to build&#8230; <a href="http://coder.bsimmons.name/blog/2009/09/proposed-modification-to-array-function-in-dataarray/" class="read_more">   [ R E A D &#124; M O R E ]</a></p>]]></description>
			<content:encoded><![CDATA[<p>In Data.Array the function <code>array :: (IArray a e, Ix i) => (i, i) -> [(i, e)] -> a i e</code> takes the array bounds and an association list, and it produces an <code>Array</code>. The function allows you to build an Array by providing the elements in whatever order you choose, rather than from the first index to the last.</p>
<p>The function <code>listArray</code> is similar except that it assumes that the list is already ordered by index so there is no need to provide tuples of (index, value). Becase <code>listArray</code> actually uses <code>zip</code> internally to produce the tupled list, so the programmer can pass a list to <code>listArray</code> which <em>exceeds the declared bounds of the array</em> and the function will quietly drop the extra list tail:</p>
<blockquote><p>
<strong>Prelude Data.Array></strong> listArray (1,3) ['a','b','c',undefined]<br />
array (1,3) [(1,'a'),(2,'b'),(3,'c')]</p></blockquote>
<p>But when a list that exceeds the specified bound is passed to <code>array</code>, it dies a horrible death:</p>
<blockquote><p>
<strong>Prelude Data.Array></strong> array (1,3) [(1,'a'),(2,'b'),(3,'c'),(4,'d')]<br />
array *** Exception: Error in array index</p></blockquote>
<p>I think the <code>array</code> function should be modified by adding a simple <code>take</code> to automatically drop any excess list elements:</p>
<p><blockquote class="vimblock"><br>
array&nbsp;(l,u)&nbsp;ies<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">=</span>&nbsp;<span class="Statement">let</span>&nbsp;n&nbsp;<span class="Statement">=</span>&nbsp;safeRangeSize&nbsp;(l,u)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">in</span>&nbsp;unsafeArray&nbsp;(l,u)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [(safeIndex&nbsp;(l,u)&nbsp;n&nbsp;i,&nbsp;e)&nbsp;<span class="Statement">|</span>&nbsp;(i,&nbsp;e)&nbsp;<span class="Statement">&lt;-</span>&nbsp;<span class="Identifier">take</span>&nbsp;n&nbsp;ies]<br>
<br></blockquote></p>
<p>This change would bring the function into better alignment with other prelude functions which expect infinite lists and drop tails as needed. It can be argued that the programmer might want to know that he is passing too long a list to his function, in which case I think the <code>safeRangeSize</code> function, etc. should be eliminated.</p>
]]></content:encoded>
			<wfw:commentRss>http://coder.bsimmons.name/blog/2009/09/proposed-modification-to-array-function-in-dataarray/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fun with Lazy Arrays: the LZ77 Algorithm</title>
		<link>http://coder.bsimmons.name/blog/2009/06/fun-with-lazy-arrays-the-lz77-algorithm/</link>
		<comments>http://coder.bsimmons.name/blog/2009/06/fun-with-lazy-arrays-the-lz77-algorithm/#comments</comments>
		<pubDate>Thu, 18 Jun 2009 17:30:29 +0000</pubDate>
		<dc:creator>jberryman</dc:creator>
				<category><![CDATA[haskell]]></category>
		<category><![CDATA[algorithm]]></category>
		<category><![CDATA[Array]]></category>
		<category><![CDATA[compression]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[recursion]]></category>

		<guid isPermaLink="false">http://coder.bsimmons.name/blog/?p=187</guid>
		<description><![CDATA[<p><em>This is my third post investigating compression techniques related to the DEFLATE algorithm: the first on <a href="http://coder.bsimmons.name/blog/2009/05/run-length-encoding/">run-length encoding</a>, and the second on simple <a href="http://coder.bsimmons.name/blog/2009/05/huffman-coding/">Huffman Coding</a>. This post models the <a href="http://www.zlib.net/feldspar.html">LZ77 algorithm, the second of the two compression</a></em>&#8230; <a href="http://coder.bsimmons.name/blog/2009/06/fun-with-lazy-arrays-the-lz77-algorithm/" class="read_more">   [ R E A D &#124; M O R E ]</a></p>]]></description>
			<content:encoded><![CDATA[<p><em>This is my third post investigating compression techniques related to the DEFLATE algorithm: the first on <a href="http://coder.bsimmons.name/blog/2009/05/run-length-encoding/">run-length encoding</a>, and the second on simple <a href="http://coder.bsimmons.name/blog/2009/05/huffman-coding/">Huffman Coding</a>. This post models the <a href="http://www.zlib.net/feldspar.html">LZ77 algorithm, the second of the two compression strategies used by DEFLATE</a>, and in the process explores some interesting properties of Haskell&#8217;s basic Arrays.</em></p>
<h5>IMPLEMENTATION:</h5>
<p><div class="vimblock"><br>
<span class="Comment">&gt;</span>&nbsp;<span class="Type">module</span>&nbsp;LZ77<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp; <span class="Type">where</span><br>
<br>
we will use GHC's &quot;basic non-strict arrays&quot; for this <br>
experiment:<br>
<br>
<span class="Comment">&gt;</span>&nbsp;<span class="PreProc">import</span>&nbsp;Data.Array<br>
<br>
<br>
and use Ints to store the length of the entire decoded<br>
message (needed to create our array):<br>
<br>
<span class="Comment">&gt;</span>&nbsp;<span class="Type">type</span>&nbsp;Length&nbsp;<span class="Statement">=</span>&nbsp;<span class="Type">Int</span><br>
<span class="Comment">&gt;</span>&nbsp;<span class="Type">type</span>&nbsp;Offset&nbsp;<span class="Statement">=</span>&nbsp;<span class="Type">Int</span><br>
<br>
in place of the length in the standard length-offset pair<br>
I've decided to use an Int representing the index of the <br>
last element in the span relative to the element at<br>
offset. Thus the pair encoding a span of only one element,<br>
two elements back would be (0,2), rather than the more <br>
traditional (1,2). <br>
<br>
This simply makes more sense to me, especially since I want<br>
to be able to encoded reversed sequences, as you will see.<br>
<br>
<span class="Comment">&gt;</span>&nbsp;<span class="Type">type</span>&nbsp;Index&nbsp;<span class="Statement">=</span>&nbsp;<span class="Type">Int</span><br>
<br>
and a few simple dataypes for our uncompressed and <br>
compressed data respectively:<br>
<br>
<span class="Comment">&gt;</span>&nbsp;<span class="Type">type</span>&nbsp;Decoded&nbsp;a&nbsp;<span class="Statement">=</span>&nbsp;Array&nbsp;Index&nbsp;a<br>
<span class="Comment">&gt;</span><br>
<span class="Comment">&gt;</span>&nbsp;<span class="Type">data</span>&nbsp;Encoded&nbsp;a&nbsp;<span class="Statement">=</span>&nbsp;<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp; Enc&nbsp;Length&nbsp;[&nbsp;<span class="Type">Either</span>&nbsp;a&nbsp;(Index,Offset)&nbsp;]&nbsp;<br>
<br>
<br>
The decompress function works by traversing the encoded message,<br>
keeping track of our array index position (since offsets are <br>
relative to the current position), and building an Array lazily<br>
from a list which we generate, in part by referencing elements<br>
from the partially generated array itself. <br>
<br>
So when we see a Right value we look up in the Array the elements <br>
referenced by the length-offset, concat-ing that list with the<br>
result of processing the rest of the encoded message.<br>
<br>
If we hit [] in 'dec' we call an error because the stored value <br>
for the length of the uncompressed message in the Encoded type<br>
was longer than what the 'decompress' function could produce.<br>
<br>
It's diffficult to describe, but I hope the code is clear:<br>
<br>
<span class="Comment">&gt;</span>&nbsp;decompress&nbsp;<span class="Statement">::</span>&nbsp;Encoded&nbsp;a&nbsp;<span class="Statement">-&gt;</span>&nbsp;Decoded&nbsp;a<br>
<span class="Comment">&gt;</span>&nbsp;decompress&nbsp;(Enc&nbsp;el&nbsp;es)&nbsp;<span class="Statement">=</span>&nbsp;decoded<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp; <span class="Type">where</span>&nbsp;decoded&nbsp;<span class="Statement">=</span>&nbsp;listArray&nbsp;(<span class="Constant">0</span>,el&nbsp;<span class="Statement">-</span>&nbsp;<span class="Constant">1</span>)&nbsp;<span class="Statement">$</span>&nbsp;dec&nbsp;<span class="Constant">0</span>&nbsp;es<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dec&nbsp;&nbsp;_&nbsp;&nbsp;&nbsp;&nbsp; []&nbsp;<span class="Statement">=</span>&nbsp;<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Identifier">error</span>&nbsp;<span class="Constant">&quot;message is shorter than it should be&quot;</span>&nbsp;<br>
<span class="Comment">&gt;</span><br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dec&nbsp;n&nbsp;(<span class="Constant">Left</span>&nbsp;x&nbsp;<span class="Statement">:</span>&nbsp;xs)&nbsp;<span class="Statement">=</span>&nbsp;<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x&nbsp;<span class="Statement">:</span>&nbsp;dec&nbsp;(n<span class="Statement">+</span><span class="Constant">1</span>)&nbsp;xs<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dec&nbsp;n&nbsp;(<span class="Constant">Right</span>&nbsp;(iRel,off)&nbsp;<span class="Statement">:</span>&nbsp;xs)&nbsp;<span class="Statement">=</span><br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Statement">let</span>&nbsp;i1&nbsp;<span class="Statement">=</span>&nbsp;n&nbsp;&nbsp;<span class="Statement">-</span>&nbsp;off<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i2&nbsp;<span class="Statement">=</span>&nbsp;(<span class="Statement">if</span>&nbsp;iN&nbsp;<span class="Statement">&gt;</span>&nbsp;i1&nbsp;<span class="Statement">then</span>&nbsp;<span class="Identifier">succ</span>&nbsp;<span class="Statement">else</span>&nbsp;<span class="Identifier">pred</span>)&nbsp;i1&nbsp;<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iN&nbsp;<span class="Statement">=</span>&nbsp;i1&nbsp;<span class="Statement">+</span>&nbsp;iRel<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">in</span>&nbsp;[&nbsp;decoded<span class="Statement">!</span>i&nbsp;<span class="Statement">|</span>&nbsp;i&nbsp;<span class="Statement">&lt;-</span>&nbsp;[i1,&nbsp;i2&nbsp;<span class="Statement">..</span>&nbsp;iN]&nbsp;]&nbsp;<span class="Statement">++</span>&nbsp;<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dec&nbsp;(n&nbsp;<span class="Statement">+</span>&nbsp;<span class="Constant">1</span>&nbsp;<span class="Statement">+</span>&nbsp;<span class="Identifier">abs</span>&nbsp;iRel)&nbsp;xs<br>
<br>
<br>
Some interesting things about the code above:<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;1) we create an array from a list, which we build,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; in part, by looking up elements from the array<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; we are in the process of building. <br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;2) we can compress a sequence of symbols which were<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; seen previously but in reverse order, simply by <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; storing a negative relative index in the <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (relative_index,offset) tuple. So, the string... <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;her racecar returns to race&quot; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; might compress to: <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{her race(-5,2)turns to(4,19)}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; I'm not sure if this is useful in real compression,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; especially when it comes down to the binary encoding.<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;3) even more interesting, we can use this same decoder<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; function to decompress data that matches a sequence<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; in parts of the array we haven't built yet! We simply <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; use a negative offset in our tuple. <br>
<br></div></p>
<h5>EXAMPLES AND CONCLUSION:</h5>
<p><div class="vimblock"><br>
point (3) may or may not be something like the LZ78 algorithm, <br>
which apparently works by encoding future data, but it is <br>
defintely a cool thing to be able to do with arrays:<br>
<br>
<span class="Comment">&gt;</span>&nbsp;coolArray&nbsp;<span class="Statement">=</span>&nbsp;listArray&nbsp;(<span class="Constant">0</span>,<span class="Constant">4</span>)&nbsp;<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[<span class="Constant">0</span>,&nbsp;&nbsp;coolArray<span class="Statement">!</span><span class="Constant">4</span>&nbsp;<span class="Statement">-</span>&nbsp;<span class="Constant">3</span>,&nbsp;&nbsp;<span class="Constant">2</span>,&nbsp;&nbsp;coolArray<span class="Statement">!</span><span class="Constant">1</span>&nbsp;<span class="Statement">+</span>&nbsp;<span class="Constant">2</span>,&nbsp;&nbsp;<span class="Constant">4</span>]<br>
<br>
<br>
Here's an example with great compression where the relative <br>
index exceeds the offset:<br>
<br>
<span class="Comment">&gt;</span>&nbsp;exceedsOffset&nbsp;<span class="Statement">=</span>&nbsp;elems&nbsp;<span class="Statement">$</span>&nbsp;decompress&nbsp;<span class="Statement">$</span><br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Enc&nbsp;<span class="Constant">25</span>&nbsp;[<span class="Constant">Left</span>&nbsp;<span class="Constant">'B'</span>,&nbsp;<span class="Constant">Left</span>&nbsp;<span class="Constant">'l'</span>,&nbsp;<span class="Constant">Left</span>&nbsp;<span class="Constant">'a'</span>,&nbsp;<span class="Constant">Left</span>&nbsp;<span class="Constant">'h'</span>,&nbsp;<span class="Constant">Left</span>&nbsp;<span class="Constant">' '</span>,<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Constant">Left</span>&nbsp;<span class="Constant">'b'</span>,&nbsp;<span class="Constant">Right</span>&nbsp;(<span class="Constant">17</span>,<span class="Constant">5</span>),&nbsp;<span class="Constant">Left</span>&nbsp;<span class="Constant">'!'</span>]<br>
<br>
<br>
...and a code example for (2) above:<br>
<br>
<span class="Comment">&gt;</span>&nbsp;reverseReference&nbsp;<span class="Statement">=</span>&nbsp;elems&nbsp;<span class="Statement">$</span>&nbsp;decompress&nbsp;<span class="Statement">$</span><br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Enc&nbsp;<span class="Constant">27</span>&nbsp;[<span class="Constant">Left</span>&nbsp;<span class="Constant">'h'</span>,<span class="Constant">Left</span>&nbsp;<span class="Constant">'e'</span>,<span class="Constant">Left</span>&nbsp;<span class="Constant">'r'</span>,<span class="Constant">Left</span>&nbsp;<span class="Constant">' '</span>,<span class="Constant">Left</span>&nbsp;<span class="Constant">'r'</span>,<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Constant">Left</span>&nbsp;<span class="Constant">'a'</span>,<span class="Constant">Left</span>&nbsp;<span class="Constant">'c'</span>,<span class="Constant">Left</span>&nbsp;<span class="Constant">'e'</span>,<span class="Constant">Right</span>(<span class="Statement">-</span><span class="Constant">5</span>,<span class="Constant">2</span>),<span class="Constant">Left</span>&nbsp;<span class="Constant">'t'</span>,<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Constant">Left</span>&nbsp;<span class="Constant">'u'</span>,<span class="Constant">Left</span>&nbsp;<span class="Constant">'r'</span>,<span class="Constant">Left</span>&nbsp;<span class="Constant">'n'</span>,<span class="Constant">Left</span>&nbsp;<span class="Constant">'s'</span>,<span class="Constant">Left</span>&nbsp;<span class="Constant">' '</span>,<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Constant">Left</span>&nbsp;<span class="Constant">'t'</span>,<span class="Constant">Left</span>&nbsp;<span class="Constant">'o'</span>,<span class="Constant">Right</span>(<span class="Constant">4</span>,<span class="Constant">19</span>)]<br>
<br>
...and finally an example combining (2) and (3):<br>
<br>
<span class="Comment">&gt;</span>&nbsp;reverseLookAhead&nbsp;<span class="Statement">=</span>&nbsp;elems&nbsp;<span class="Statement">$</span>&nbsp;decompress&nbsp;<span class="Statement">$</span>&nbsp;<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Enc&nbsp;<span class="Constant">5</span>&nbsp;[<span class="Constant">Left</span>&nbsp;<span class="Constant">1</span>,&nbsp;<span class="Constant">Right</span>&nbsp;(<span class="Statement">-</span><span class="Constant">1</span>,<span class="Statement">-</span><span class="Constant">3</span>),&nbsp;<span class="Constant">Left</span>&nbsp;<span class="Constant">3</span>,&nbsp;<span class="Constant">Left</span>&nbsp;<span class="Constant">4</span>]<br>
<br>
<br>
I was surprised to discover these properties in Haskell's lazy<br>
Arrays. hope they came as a surprise to a few others.<br>
<br></div></p>
]]></content:encoded>
			<wfw:commentRss>http://coder.bsimmons.name/blog/2009/06/fun-with-lazy-arrays-the-lz77-algorithm/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
