<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/stylesheets/rss.css" type="text/css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Tom Moertel's Weblog: Tag haskell</title>
    <link>http://blog.moertel.com/articles/tag/haskell?tag=haskell</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Quality rants on programming theory and stuff geeks like</description>
    <item>
      <title>PXSL Tools now on Hackage and GitHub</title>
      <description>&lt;p&gt;I finally got around to releasing &lt;a href="http://hackage.haskell.org/cgi-bin/hackage-scripts/package/pxsl-tools"&gt;&lt;span class="caps"&gt;PXSL&lt;/span&gt; Tools on Hackage&lt;/a&gt;.  The package contains &lt;em&gt;pxslcc&lt;/em&gt;, a preprocessor that converts &lt;a href="http://community.moertel.com/ss/space/PXSL"&gt;Parsimonious &lt;span class="caps"&gt;XML&lt;/span&gt; Shorthand Language&lt;/a&gt; into &lt;span class="caps"&gt;XML&lt;/span&gt;, and supporting documentation.&lt;/p&gt;


	&lt;p&gt;If you want to hack on the Haskell sources, I&amp;#8217;ve put the project on GitHub, too.  See the &lt;a href="https://github.com/tmoertel/pxsl-tools/tree"&gt;pxsl-tools project page&lt;/a&gt; to browse the code, or just clone the repo and hack away:&lt;/p&gt;


&lt;pre&gt;$ git clone git://github.com/tmoertel/pxsl-tools.git
&lt;/pre&gt;</description>
      <pubDate>Sun, 24 Aug 2008 22:56:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:888e0d81-d509-4041-a75b-ee91ce921b4d</guid>
      <author>Tom Moertel</author>
      <link>http://blog.moertel.com/articles/2008/08/24/pxsl-tools-now-on-hackage-and-github</link>
      <category>haskell</category>
      <category>git</category>
      <category>pxsl</category>
      <trackback:ping>http://blog.moertel.com/articles/trackback/808</trackback:ping>
    </item>
    <item>
      <title>Thinking algebraically: a functional-programming dividend that pays during your imperative-programming day job</title>
      <description>&lt;p&gt;Although at work I code mostly in Python &amp;#8211; a language from which
&lt;a href="http://www.artima.com/weblogs/viewpost.jsp?thread=98196"&gt;&lt;em&gt;lambda&lt;/em&gt; and &lt;em&gt;map&lt;/em&gt; were nearly removed&lt;/a&gt; &amp;#8211; I still find that functional-programming experience
has its benefits.  One of the
&amp;#8220;functional-programming dividends&amp;#8221; I notice most often is insight
gained from considering problems from an algebraic perspective.&lt;/p&gt;


	&lt;p&gt;Recently, for example, I had a small parsing problem.  I had to
write code that, given a simple grammar specification as input, emits
a regular expression that matches the language generated by the
grammar.&lt;/p&gt;


	&lt;p&gt;Here&amp;#8217;s a simplified version of the problem.  A grammar specification
is limited to a series of one or more &lt;em&gt;atoms&lt;/em&gt;.  For example, &amp;#8220;a b c&amp;#8221; 
represents the atom &amp;#8220;a&amp;#8221;, followed by the atom &amp;#8220;b&amp;#8221;, followed by the
atom &amp;#8220;c&amp;#8221;.  To generate the grammar, the series of atoms is interpreted
such that each atom (except the last) generates a production rule of
the following form:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;atom_rule ::=
  &amp;lt;the literal atom&amp;gt; (SPACE &amp;lt;the next rule&amp;gt; | NOTHING)
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;(SPACE represents literal white space and &lt;span class="caps"&gt;NOTHING&lt;/span&gt; represents an
empty string.)  The grammar as a whole is rooted in the first atom&amp;#8217;s
rule.&lt;/p&gt;


	&lt;p&gt;Thus the specification &amp;#8220;a b c&amp;#8221; represents the following grammar:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;grammar ::= a_rule
a_rule  ::= "a" (SPACE b_rule | NOTHING)
b_rule  ::= "b" (SPACE c_rule | NOTHING)
c_rule  ::= "c" 
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Note that the final atom&amp;#8217;s production matches only the literal atom
itself: it has no following rule on which to chain.&lt;/p&gt;


	&lt;p&gt;The grammar, in turn, generates the following language:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;a
a b
a b c
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Thus, given the grammar specification &amp;#8220;a b c&amp;#8221;, my code had to produce
a regular expression that would match &amp;#8220;a&amp;#8221;, &amp;#8220;a b&amp;#8221;, or &amp;#8220;a b c&amp;#8221;.&lt;/p&gt;


	&lt;p&gt;At this point, please stop for a moment and think about this little
programming exercise.  Do any solutions leap to mind?  How would you
approach the problem?  Form your opinions now, because I&amp;#8217;m going to
ask you about them later. (If you&amp;#8217;re feeling especially caffeinated, try
coding a solution before reading on.)&lt;/p&gt;&lt;p&gt;For me, the insight that made the exercise easy was seeing that the
grammar is given by folding a (suitably defined) right-associative
binary operator through the series of atoms.  The relationship might
be easier to see if you substitute away the intermediate production
rules from the grammar above:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;grammar ::= "a" (SPACE "b" (SPACE "c" | NOTHING) | NOTHING)
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;If you squint past the &lt;span class="caps"&gt;SPACE&lt;/span&gt; and &lt;span class="caps"&gt;NOTHING&lt;/span&gt; terms, you&amp;#8217;ll see that the
grammar has the form&lt;/p&gt;


&lt;p&gt;(&lt;em&gt;a&lt;/em&gt; + (&lt;em&gt;b&lt;/em&gt; + (&lt;em&gt;c&lt;/em&gt;)))&lt;/p&gt;

	&lt;p&gt;The + is a binary operator that generates the parts we squinted away.
Once you see what&amp;#8217;s going on structurally, the operator is easy to
define:&lt;/p&gt;


&lt;p&gt;&lt;em&gt;x&lt;/em&gt; + &lt;em&gt;y&lt;/em&gt;  =  &lt;em&gt;x&lt;/em&gt; (SPACE &lt;em&gt;y&lt;/em&gt; | &lt;span class="caps"&gt;NOTHING&lt;/span&gt;)&lt;/p&gt;

&lt;p&gt;Compare the operator&amp;#8217;s definition with that of the
&lt;code&gt;atom_rule&lt;/code&gt; I presented at the beginning of the article.
They&amp;#8217;re structurally the same: the operator&amp;#8217;s &lt;em&gt;x&lt;/em&gt; and
&lt;em&gt;y&lt;/em&gt; are the atom rule&amp;#8217;s &lt;code&gt;&amp;lt;the literal atom&amp;gt;&lt;/code&gt; and
&lt;code&gt;&amp;lt;the next rule&amp;gt;&lt;/code&gt;.&lt;/p&gt;

	&lt;p&gt;Now all that remains is to generalize the &amp;#8220;a b c&amp;#8221; formula into a
general formula that works for arbitrary grammar specifications.
Fortunately, this work has already been done for us.  The generalized
formula is nothing more than a &lt;a href="http://www.haskell.org/haskellwiki/Fold"&gt;right fold&lt;/a&gt;.  In Haskell, the
particular right-fold flavor we want is called &lt;em&gt;foldr1&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;Given a list of atoms, we can use &lt;em&gt;foldr1&lt;/em&gt; to construct its grammar as
follows:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;mk_grammar atoms = foldr1 (+) atoms
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;But Python, our implementation language, does not offer a &lt;em&gt;foldr1&lt;/em&gt;
function.  This wrinkle, however, is another thing we can iron out by
thinking algebraically.  Python doesn&amp;#8217;t have &lt;em&gt;foldr1&lt;/em&gt;, but it does
have a &lt;em&gt;reduce&lt;/em&gt; function, which represents a left fold, equivalent to
Haskell&amp;#8217;s &lt;em&gt;foldl&amp;#8217;&lt;/em&gt; or &lt;em&gt;foldl1&amp;#8217;&lt;/em&gt;.  Because our + operator is strict and
our list of atoms is finite, we can take advantage of the following
identity:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;foldr1 (+) xs == foldl1 (flip (+)) (reverse xs)
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;That is, we can convert a right fold into a left fold by flipping the
arguments of the operator and operating on the list in reverse.  Thus
we can implement the fold we &lt;em&gt;want&lt;/em&gt; in terms of the fold we &lt;em&gt;have&lt;/em&gt;:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;# Python code

def foldr1(f, xs):
    return reduce(flip(f), reversed(xs))

def flip(f):
    def g(x, y):
        return f(y, x)
    return g
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Now writing a Python-based solution is straightforward:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;def grammar_spec_to_re(spec):
    atoms = grammar_spec_to_atoms(spec)
    atom_res = map(atom_to_re, atoms)
    grammar_re = r'\A%s\Z' % foldr1(op, atom_res)
    return grammar_re

def op(x, y):
    # x + y = x (SPACE y | NOTHING)
    return r'%s(\s+%s)?' % (x, y)

def grammar_spec_to_atoms(spec):
    return spec.split()

def atom_to_re(atom):
    return re.escape(atom)
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Using our solution, let&amp;#8217;s compile the &amp;#8220;a b c&amp;#8221; grammar specification
into its corresponding regular expression:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; print grammar_spec_to_re('a b c')
\Aa(\s+b(\s+c)?)?\Z
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;And that&amp;#8217;s basically how I solved the problem.&lt;/p&gt;


	&lt;p&gt;To play around with the solution, here&amp;#8217;s a small helper class that compiles a grammar specification into a regular expression and then tests strings for matching the regexp:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;class GrammarMatcher(object):
    def __init__(self, spec):
        self.re = re.compile(grammar_spec_to_re(spec))
    def __call__(self, s):
        return not not self.re.match(s)
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Now, let&amp;#8217;s try out the regular expression generated for the grammar specification &amp;#8220;a b c&amp;#8221; :&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; matcher = GrammarMatcher('a b c')
&amp;gt;&amp;gt;&amp;gt; matcher('')
False
&amp;gt;&amp;gt;&amp;gt; matcher('a')
True
&amp;gt;&amp;gt;&amp;gt; matcher('ab')
False
&amp;gt;&amp;gt;&amp;gt; matcher('a b')
True
&amp;gt;&amp;gt;&amp;gt; matcher('a  b')
True
&amp;gt;&amp;gt;&amp;gt; matcher('a b c')
True
&amp;gt;&amp;gt;&amp;gt; matcher('a b c d')
False
&amp;gt;&amp;gt;&amp;gt; matcher('a c')
False
&amp;gt;&amp;gt;&amp;gt; matcher('b')
False
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Now, those questions I promised.  If you&amp;#8217;re a functional programmer,
did a fold-based solution leap out at you?  (Did you think of the
&lt;em&gt;problem&lt;/em&gt; in terms of folds?)  If you&amp;#8217;re not a functional programmer,
how did you see the problem?  Did the solution above seem twisted,
confusing, or overly clever?&lt;/p&gt;


	&lt;p&gt;(There are no right or wrong answers.  I&amp;#8217;m just curious about how
people with different backgrounds view the problem.)&lt;/p&gt;


&lt;div class="update"&gt;
&lt;strong&gt;Update:&lt;/strong&gt; Edited to clarify that the problem is to convert a grammar specification into a regular expression, not just test whether a string matches a specified grammar.
&lt;/div&gt;</description>
      <pubDate>Wed, 20 Aug 2008 21:50:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:a80d7a49-0278-48b0-badb-ffe38a216762</guid>
      <author>Tom Moertel</author>
      <link>http://blog.moertel.com/articles/2008/08/20/thinking-algebraically-a-functional-programming-dividend-that-pays-during-your-imperative-programming-day-job</link>
      <category>functional programming</category>
      <category>haskell</category>
      <category>fp</category>
      <category>python</category>
      <category>folds</category>
      <trackback:ping>http://blog.moertel.com/articles/trackback/766</trackback:ping>
    </item>
    <item>
      <title>PXSL Tools 1.0: Your ticket out of XML Hell</title>
      <description>&lt;p&gt;&lt;span class="caps"&gt;XML&lt;/span&gt; is fine for representing document-like things, but when it&amp;#8217;s
twisted to represent build recipes, configuration files, and little
programming languages, it opens the gates to &lt;em&gt;&lt;span class="caps"&gt;XML&lt;/span&gt; Hell&lt;/em&gt;.  Once the
gates are opened, the demons of cargo-cult thinking are loosed upon
the world, where they are free to trick innocent programmers into
working with grotesquely twisted &lt;span class="caps"&gt;XML&lt;/span&gt; documents &amp;#8211; something no human
mind was designed to comprehend.  Ensnared, these programmers are
slowly drawn into the depths of &lt;span class="caps"&gt;XML&lt;/span&gt; Hell, from which their
&lt;a href="http://www.google.com/search?q=%22xml+hell%22"&gt;lamentations echo across the
universe&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;When the demons of cargo-cult thinking come for you, don&amp;#8217;t be
ensnared!  Instead, be prepared &amp;#8211; with &lt;span class="caps"&gt;PXSL&lt;/span&gt; &amp;#8211; the &lt;a href="http://community.moertel.com/ss/space/pxsl"&gt;Parsimonious &lt;span class="caps"&gt;XML&lt;/span&gt;
Shorthand Language&lt;/a&gt;
(pronounced &amp;#8220;pixel&amp;#8221;).&lt;/p&gt;


	&lt;p&gt;What&amp;#8217;s &lt;span class="caps"&gt;PXSL&lt;/span&gt;?  It&amp;#8217;s a luxurious, thermonuclear smoking jacket that you
can slip on using a convenient preprocessor.  Use it whenever you see
grotesque &lt;span class="caps"&gt;XML&lt;/span&gt; on the horizon.  Within &lt;span class="caps"&gt;PXSL&lt;/span&gt;&amp;#8217;s plush (and stylish)
protection, you can create all the nasty, twisted &lt;span class="caps"&gt;XML&lt;/span&gt; that may be
demanded of you, but you need not descend into &lt;span class="caps"&gt;XML&lt;/span&gt; Hell to do it.
Instead, you can work from the comfort of a well-stocked lounge, where
clarity and conciseness are always on tap.&lt;/p&gt;


	&lt;p&gt;For example, here&amp;#8217;s a snippet from an &lt;span class="caps"&gt;XSLT&lt;/span&gt; stylesheet, in the
original &lt;span class="caps"&gt;XML&lt;/span&gt;:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;&amp;lt;xsl:template match="/"&amp;gt;
  &amp;lt;xsl:for-each select="//*/@src|//*/@href"&amp;gt;
    &amp;lt;xsl:value-of select="."/&amp;gt;
    &amp;lt;xsl:text&amp;gt;&amp;amp;#10;&amp;lt;/xsl:text&amp;gt;
  &amp;lt;/xsl:for-each&amp;gt;
&amp;lt;/xsl:template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;And here&amp;#8217;s the same snippet, written in &lt;span class="caps"&gt;PXSL&lt;/span&gt;:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;template /
  for-each //*/@src|//*/@href
    value-of .
    text &amp;lt;&amp;lt;&amp;amp;#10;&amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Isn&amp;#8217;t that refreshing?&lt;/p&gt;


	&lt;h3&gt;Why &lt;span class="caps"&gt;PXSL&lt;/span&gt;?&lt;/h3&gt;


	&lt;p&gt;There are lots of &lt;span class="caps"&gt;XML&lt;/span&gt; shorthands available.  (The &lt;a href="http://community.moertel.com/ss/space/PXSL/FAQs"&gt;&lt;span class="caps"&gt;PXSL FAQ&lt;/span&gt;&lt;/a&gt; lists about ten of them.)  So why choose
&lt;span class="caps"&gt;PXSL&lt;/span&gt;?  Here&amp;#8217;s why:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;PXSL&lt;/span&gt; lets you intermix &lt;span class="caps"&gt;PXSL&lt;/span&gt; and &lt;span class="caps"&gt;XML&lt;/span&gt; syntax&lt;/strong&gt; in one document. Feel free to use whichever syntax works best for each portion of your documents.  (See &lt;a href="http://community.moertel.com/pxsl/#xml-quoting-lt-lt-gt-gt-delimiters"&gt;the &lt;span class="caps"&gt;PXSL&lt;/span&gt; documentation&lt;/a&gt; for some examples.)&lt;/li&gt;
		&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;PXSL&lt;/span&gt; is customizable&lt;/strong&gt; with application-specific shortcuts.  (The &lt;span class="caps"&gt;PXSL&lt;/span&gt; snippet above, for example, uses &lt;span class="caps"&gt;XSLT&lt;/span&gt; shortcuts. Again, &lt;a href="http://community.moertel.com/pxsl/#element-defaults-provide-convenient-customizable-shortcuts"&gt;the &lt;span class="caps"&gt;PXSL&lt;/span&gt; documentation&lt;/a&gt; has examples.)&lt;/li&gt;
		&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;PXSL&lt;/span&gt; has a powerful macro system&lt;/strong&gt; that lets you build complicated document structures safely and conveniently.  (Read about &lt;a href="http://community.moertel.com/pxsl/#macro-facility"&gt;macros in the &lt;span class="caps"&gt;PXSL&lt;/span&gt; documentation&lt;/a&gt;.  For an advanced example of what you can do with &lt;span class="caps"&gt;PXSL&lt;/span&gt; macros, see this &lt;a href="http://www.kuro5hin.org/story/2003/6/4/12434/75716"&gt;article on refactoring &lt;span class="caps"&gt;XSLT&lt;/span&gt; one-offs into clean, maintainable code&lt;/a&gt;.)&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Also, &lt;span class="caps"&gt;PXSL&lt;/span&gt; is battle tested.  It was first released in 2003 and has
been saving people from &lt;span class="caps"&gt;XML&lt;/span&gt; Hell since.  People who try it seem to like it:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;em&gt;I think &lt;span class="caps"&gt;PXSL&lt;/span&gt; could do wonders for soothing my irrational hatred for all things &lt;span class="caps"&gt;XML&lt;/span&gt;.&lt;/em&gt; &amp;#8212;&lt;a href="http://koweynlg.blogspot.com/2006/03/mmax-encore-encore-yay-pxsl.html"&gt;kowey&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;em&gt;Impressive&amp;#8230; I converted some of my files from &lt;span class="caps"&gt;XML&lt;/span&gt; to &lt;span class="caps"&gt;PXSL&lt;/span&gt; and the readability was much improved.&lt;/em&gt; &amp;#8212;&lt;a href="http://community.moertel.com/ss/comments/PXSL+Ask-a-Question#comment-PXSL%20Ask-a-Question-6"&gt;chris&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;em&gt;Quite aside from the fact that &lt;span class="caps"&gt;XSLT&lt;/span&gt; is finally somewhat readable, the fact that you&amp;#8217;ve added a serious macro system means that some serious scripting of &lt;span class="caps"&gt;XML&lt;/span&gt; can occur. I&amp;#8217;m very impressed.&lt;/em&gt; &amp;#8212;&lt;a href="http://community.moertel.com/ss/comments/PXSL+Ask-a-Question#comment-PXSL%20Ask-a-Question-4"&gt;invisible&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;The next time you&amp;#8217;re headed for &lt;span class="caps"&gt;XML&lt;/span&gt; Hell, why not &lt;a href="http://community.moertel.com/pxsl/#getting-or-building-the-pxsl-tools"&gt;give the venerable &lt;span class="caps"&gt;PXSL&lt;/span&gt; a try&lt;/a&gt;?  You might just find that you like it, too.&lt;/p&gt;


&lt;hr/&gt;

	&lt;p&gt;This public service announcement was brought to you in celebration of
the 1.0 release of the &lt;strong&gt;pxsl-tools&lt;/strong&gt; package.  The &lt;span class="caps"&gt;PXSL&lt;/span&gt;-to-XML compiler
&lt;em&gt;pxslcc&lt;/em&gt; is written in &lt;a href="http://haskell.org/"&gt;Haskell&lt;/a&gt; and uses the
cross-platform &lt;a href="http://www.haskell.org/cabal/"&gt;Haskell Cabal&lt;/a&gt;
build/package system to let you use &lt;span class="caps"&gt;PXSL&lt;/span&gt; just about anywhere.&lt;/p&gt;</description>
      <pubDate>Mon, 17 Dec 2007 22:33:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:fd34e396-beca-406a-9f9e-46a1dd5fe7ce</guid>
      <author>Tom Moertel</author>
      <link>http://blog.moertel.com/articles/2007/12/17/pxsl-tools-1-0-your-ticket-out-of-xml-hell</link>
      <category>programming</category>
      <category>haskell</category>
      <category>xml</category>
      <category>pxsl</category>
      <category>xslt</category>
      <trackback:ping>http://blog.moertel.com/articles/trackback/672</trackback:ping>
    </item>
    <item>
      <title>How I stopped missing Darcs and started loving Git</title>
      <description>&lt;p&gt;About three years ago, I &lt;a href="http://blog.moertel.com/articles/2005/02/12/source-code-management-with-darcs-a-first-look"&gt;switched to
Darcs&lt;/a&gt;
as my primary source-code management system.  It was simple,
intuitive, and powerful, and it made managing my projects more fun and
less frustrating than any centralized &lt;span class="caps"&gt;VCS&lt;/span&gt; ever had.  That it was
written in Haskell, one of my favorite programming languages, made
it even better.  I was hooked.&lt;/p&gt;


	&lt;p&gt;Since then, the distributed &lt;span class="caps"&gt;SCM&lt;/span&gt; landscape has changed.  Darcs hasn&amp;#8217;t
improved much, but its competitors have made long strides, especially
&lt;a href="http://git.or.cz/"&gt;Git&lt;/a&gt; and
&lt;a href="http://www.selenic.com/mercurial/"&gt;Mercurial&lt;/a&gt;.  Both
are crazy fast, vigorously developed, and widely used on large, highly
active real-world projects, such as the Linux kernel and Mozilla 2.
In comparison, Darcs has
stagnated.&lt;/p&gt;


	&lt;p&gt;When I started working for a new company recently, I had to consider
whether to advocate Darcs or something else.  In the end, I decided
that Darcs would be a hard sell.  Nobody else at the company uses
Haskell, and having to explain how to &lt;a href="http://wiki.darcs.net/DarcsWiki/ConflictsFAQ#head-476c7079246558936930568621a39f83295b3846"&gt;avoid the occasional corner
case&lt;/a&gt;
seemed liked a losing proposition.&lt;/p&gt;


	&lt;p&gt;After researching and playing around with Git and Mercurial, I settled
on Git.  I like Git&amp;#8217;s underlying hashed-blobs model better than
Mercurial&amp;#8217;s revlogs, and Git seems to have slightly more development
momentum.  Still, it was a close call.  Either choice would have been
completely reasonable.&lt;/p&gt;


	&lt;h3&gt;Missing Darcs&lt;/h3&gt;


	&lt;p&gt;When I started using Git on real projects, the one thing I &lt;em&gt;really&lt;/em&gt;
missed was the ability to easily amend earlier patches, something
Darcs made trivial.  Let me
explain.  The typical development workflow goes something like this:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Checkout copy of upstream code base.&lt;/li&gt;
		&lt;li&gt;Implement feature X.&lt;/li&gt;
		&lt;li&gt;Commit.&lt;/li&gt;
		&lt;li&gt;Implement independent feature Y.&lt;/li&gt;
		&lt;li&gt;Commit.&lt;/li&gt;
		&lt;li&gt;Implement independent feature Z.&lt;/li&gt;
		&lt;li&gt;Commit.&lt;/li&gt;
		&lt;li&gt;Push new features back upstream.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Now, what really happens is that when I&amp;#8217;m implementing Y or Z,
I&amp;#8217;ll realize that I made a mistake in X.  The trick is then
fixing X so that my fix is part of the changeset/patch for X that
ultimately gets pushed upstream in the last step.  That way, the
upstream folks will see only a single, clean patch for feature X &amp;#8211; not
a mishmash of patches that together represent X.&lt;/p&gt;


	&lt;p&gt;In Darcs, amending the original patch is easy because its patch theory
lets me tweak the patch for X independently of the other patches.
Darcs will simply ask me which patch I want to amend, and I&amp;#8217;ll select
the orignal patch for X:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;$ emacs               # fix X
$ darcs amend-record  # amend original patch for X

Mon Dec 10 14:43:13 EST 2007  Tom Moertel &amp;lt;tom@moertel.com&amp;gt;
  * Implemented Z
Shall I amend this patch? [yNvpq], or ? for help: n

Mon Dec 10 14:42:12 EST 2007  Tom Moertel &amp;lt;tom@moertel.com&amp;gt;
  * Implemented Y
Shall I amend this patch? [yNvpq], or ? for help: n

Mon Dec 10 14:41:46 EST 2007  Tom Moertel &amp;lt;tom@moertel.com&amp;gt;
  * Implemented X
Shall I amend this patch? [yNvpq], or ? for help: y
hunk ./x 1
-X1
+X2
Shall I add this change? (1/?)  [ynWsfqadjkc], or ? for help: y
Finished amending patch:
Mon Dec 10 14:43:25 EST 2007  Tom Moertel &amp;lt;tom@moertel.com&amp;gt;
  * Implemented X
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;That&amp;#8217;s it.  The exact same process will work regardless of when I
realize I need to fix X: before I start Y, while I&amp;#8217;m implementing Y,
after I&amp;#8217;ve committed Y, while I&amp;#8217;m working on Z, or after I&amp;#8217;ve committed
Z.&lt;/p&gt;


	&lt;h3&gt; Learning to love Git&lt;/h3&gt;


	&lt;p&gt;With Git, however, I can amend a commit only if I haven&amp;#8217;t committed anything else before making my fix. In Git&amp;#8217;s mind, Y depends on X, and Z
depends on Y, even if they really are independent of one another.&lt;/p&gt;


	&lt;p&gt;So if I commit the original patch for X and then immediately realize I
need to make a fix, before I start working on Y or Z, it&amp;#8217;s easy:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;$ emacs               # implement X
$ git commit -m 'Implemented X'

# discover problem in X

$ emacs               # fix X
$ git commit --amend  # amend original patch
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;More typically, it&amp;#8217;s only while I&amp;#8217;m working on Y that I&amp;#8217;ll
realize I need to fix X.  Then it&amp;#8217;s more complicated
to amend the original commit:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;$ emacs               # implement X
$ git commit -m 'Implemented X'
$ emacs               # start working on Y

# discover problem in X

$ git stash           # stash away half-completed work on Y
$ emacs               # fix X
$ git commit --amend  # amend original patch for X
$ git stash apply     # restore work on Y
$ emacs               # continue working on Y
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;While not as convenient as Darcs&amp;#8217;s workflow, it&amp;#8217;s perfectly workable.&lt;/p&gt;


Now let&amp;#8217;s consider another fairly typical case:  I commit X and Y and
then start working on Z before I notice the problem in X.  I used to
think that Git couldn&amp;#8217;t handle this  case, but it can, thanks to
&lt;code&gt;git rebase --interactive&lt;/code&gt;:

&lt;pre&gt;&lt;code&gt;$ emacs               # implement X
$ git commit -m 'Implemented X'
$ emacs               # implement Y
$ git commit -m 'Implemented Y'
$ emacs               # start working on Z

# discover problem in X

$ git stash           # stash away half-completed work on Z
$ emacs               # fix X
$ git commit -m 'Fixed X'
$ git rebase --interactive HEAD~3  # see comments below
$ git stash apply     # restore work on Z
$ emacs               # continue working on Z
&lt;/code&gt;&lt;/pre&gt;

The &lt;code&gt;git rebase --interactive&lt;/code&gt; command is &lt;em&gt;powerful&lt;/em&gt;.  What the
command does, as called in the snippet above, is invoke my editor of
choice on a text file describing the last 3 commits (that&amp;#8217;s the
&lt;code&gt;HEAD~3&lt;/code&gt; part):

&lt;pre&gt;&lt;code&gt;# Rebasing 3ad99a7..b9a8405 onto 3ad99a7
#
# Commands:
#  pick = use commit
#  edit = use commit, but stop for amending
#  squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
pick 0885540 Implemented X
pick 320b115 Implemented Y
pick b9a8405 Fixed X
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;I can then edit the file to reorder, merge (squash), and/or remove
the commits.  In this example, I want to merge the fix for X into
the original commit that implemented X.  So I edit the file like so:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;pick 0885540 Implemented X
squash b9a8405 Fixed X
pick 320b115 Implemented Y
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Then I save the file, at which point Git takes over and makes the
requested changes, merging the fix for X into the
original commit for X.  Now the log shows the original implementation
and fix as one commit:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;$ git log
commit f387d650976246c0854d028b040cca40e542be56
Author: Tom Moertel &amp;lt;tom@moertel.com&amp;gt;
Date:   Mon Dec 10 15:11:26 2007 -0500

    Implemented Y

commit 82a1c849ffd1bd688d5bc9d99be0e63548a89c4c
Author: Tom Moertel &amp;lt;tom@moertel.com&amp;gt;
Date:   Mon Dec 10 15:13:03 2007 -0500

    Implemented X

    Fixed X

commit 3ad99a7ef537b7ae99e435e0d2b4b0d03de92c65
Author: Tom Moertel &amp;lt;tom@moertel.com&amp;gt;
Date:   Mon Dec 10 15:11:14 2007 -0500

    Initial checkin
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Once I figured out how to use &lt;code&gt;git rebase --interactive&lt;/code&gt;, I stopped
missing Darcs and started loving Git.&lt;/p&gt;</description>
      <pubDate>Mon, 10 Dec 2007 16:52:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:65f0fc3e-71c6-4f9e-9100-3d1333b7967a</guid>
      <author>Tom Moertel</author>
      <link>http://blog.moertel.com/articles/2007/12/10/how-i-stopped-missing-darcs-and-started-loving-git</link>
      <category>programming</category>
      <category>haskell</category>
      <category>scm</category>
      <category>darcs</category>
      <category>git</category>
      <category>dvcs</category>
      <trackback:ping>http://blog.moertel.com/articles/trackback/655</trackback:ping>
    </item>
    <item>
      <title>TMR 9!</title>
      <description>&lt;p&gt;Issue 9 of &lt;a href="http://www.haskell.org/haskellwiki/The_Monad.Reader"&gt;The Monad.Reader&lt;/a&gt; is hot off the presses! The issue focuses on three Google-Summer-of-Code projects for Haskell: Cabal configurations, Darcs&amp;#8217;s Patch Theory, and the typechecker-framework TaiChi. Good stuff.&lt;/p&gt;


	&lt;p&gt;I know what I&amp;#8217;ll be reading for lunch today.&lt;/p&gt;</description>
      <pubDate>Mon, 19 Nov 2007 13:07:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:44cef717-1f47-47b6-b50e-7e6bfec9817b</guid>
      <author>Tom Moertel</author>
      <link>http://blog.moertel.com/articles/2007/11/19/tmr-9</link>
      <category>haskell</category>
      <category>haskell</category>
      <category>tmr</category>
      <trackback:ping>http://blog.moertel.com/articles/trackback/625</trackback:ping>
    </item>
    <item>
      <title>Updated cabal2rpm helps you make RPM packages from Haskell Cabal packages</title>
      <description>&lt;p&gt;I just released an updated version of &lt;a href="http://community.moertel.com/ss/space/Cabal2rpm"&gt;cabal2rpm&lt;/a&gt;, a small program (written in Perl) that creates &lt;span class="caps"&gt;RPM&lt;/span&gt; spec files from &lt;a href="http://www.haskell.org/cabal/"&gt;Cabal&lt;/a&gt; package descriptions. &lt;span class="caps"&gt;RPM&lt;/span&gt; is the software-packaging format used by several popular Linux distributions, including Red Hat and Fedora. Cabal is the packaging format used by the Haskell community to distribute software written in Haskell.&lt;/p&gt;


	&lt;p&gt;Bryan O&amp;#8217;Sullivan&amp;#8217;s &lt;a href="http://www.serpentine.com/blog/software/cabal-rpm/"&gt;cabal-rpm&lt;/a&gt; also creates spec files from Cabal packages. Unlike cabal2rpm, it is written in Haskell and directly interfaces with the Cabal libraries. Long term, it is the way to go. For now, however, cabal2rpm may be more convenient because it works out of the box. (To use cabal-rpm, you&amp;#8217;ll first need to install the just-tagged Cabal 1.2.0 library, not yet in wide distribution.)&lt;/p&gt;</description>
      <pubDate>Fri, 07 Sep 2007 20:19:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:26d35c03-c90c-452f-92b4-0d432f43c6a6</guid>
      <author>Tom Moertel</author>
      <link>http://blog.moertel.com/articles/2007/09/07/updated-cabal2rpm-helps-you-make-rpm-packages-from-haskell-cabal-packages</link>
      <category>haskell</category>
      <category>haskell</category>
      <category>cabal</category>
      <category>cabal2rpm</category>
      <trackback:ping>http://blog.moertel.com/articles/trackback/570</trackback:ping>
    </item>
    <item>
      <title>ClusterBy: a handy little function for the toolbox</title>
      <description>&lt;p&gt;Via Reddit I found &lt;a href="http://marknelson.us/2007/04/01/puzzling/"&gt;Mark Nelson&amp;#8217;s post about a recent word puzzle&lt;/a&gt; from &lt;span class="caps"&gt;NPR&lt;/span&gt;&amp;#8217;s
Weekend Edition:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;Take the names of two U.S. States, mix them all together, then rearrange the letters to form the names of two other U.S. States. What states are these?&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;The puzzle is fairly straightforward to solve by hand (think about
it), but let&amp;#8217;s write a program to solve it. That will give us a convenient
excuse to discuss a super-handy function I use all the time:
&lt;em&gt;clusterBy&lt;/em&gt;.  In Haskell, it looks like this:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='keyword'&gt;import&lt;/span&gt; &lt;span class='conid'&gt;Control&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='conid'&gt;Arrow&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varop'&gt;&amp;amp;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;span class='keyword'&gt;import&lt;/span&gt; &lt;span class='varid'&gt;qualified&lt;/span&gt; &lt;span class='conid'&gt;Data&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='conid'&gt;Map&lt;/span&gt; &lt;span class='keyword'&gt;as&lt;/span&gt; &lt;span class='conid'&gt;M&lt;/span&gt;

&lt;span class='varid'&gt;clusterBy&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;Ord&lt;/span&gt; &lt;span class='varid'&gt;b&lt;/span&gt; &lt;span class='keyglyph'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;a&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;b&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='varid'&gt;a&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='varid'&gt;a&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;span class='varid'&gt;clusterBy&lt;/span&gt; &lt;span class='varid'&gt;f&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;M&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;elems&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='conid'&gt;M&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;map&lt;/span&gt; &lt;span class='varid'&gt;reverse&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='conid'&gt;M&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;fromListWith&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varop'&gt;++&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
            &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;map&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;f&lt;/span&gt; &lt;span class='varop'&gt;&amp;amp;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class='varid'&gt;return&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;What &lt;em&gt;clusterBy&lt;/em&gt; does is group a list of values by their signatures,
as computed by a given signature function &lt;em&gt;f&lt;/em&gt;, and returns
the groups in order of ascending signature.  For example, we
can cluster the words &amp;#8220;the tan ant gets some fat&amp;#8221; by length, by
first letter, or by last letter just by changing the
signature function we give to &lt;em&gt;clusterBy&lt;/em&gt;:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varop'&gt;*&lt;/span&gt;&lt;span class='conid'&gt;Main&lt;/span&gt;&lt;span class='varop'&gt;&amp;gt;&lt;/span&gt; &lt;span class='keyword'&gt;let&lt;/span&gt; &lt;span class='varid'&gt;antwords&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;words&lt;/span&gt; &lt;span class='str'&gt;"the tan ant gets some fat"&lt;/span&gt;

&lt;span class='varop'&gt;*&lt;/span&gt;&lt;span class='conid'&gt;Main&lt;/span&gt;&lt;span class='varop'&gt;&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;clusterBy&lt;/span&gt; &lt;span class='varid'&gt;length&lt;/span&gt; &lt;span class='varid'&gt;antwords&lt;/span&gt;
&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='str'&gt;"the"&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='str'&gt;"tan"&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='str'&gt;"ant"&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='str'&gt;"fat"&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='str'&gt;"gets"&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='str'&gt;"some"&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;

&lt;span class='varop'&gt;*&lt;/span&gt;&lt;span class='conid'&gt;Main&lt;/span&gt;&lt;span class='varop'&gt;&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;clusterBy&lt;/span&gt; &lt;span class='varid'&gt;head&lt;/span&gt; &lt;span class='varid'&gt;antwords&lt;/span&gt;
&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='str'&gt;"ant"&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='str'&gt;"fat"&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='str'&gt;"gets"&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='str'&gt;"some"&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='str'&gt;"the"&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='str'&gt;"tan"&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;

&lt;span class='varop'&gt;*&lt;/span&gt;&lt;span class='conid'&gt;Main&lt;/span&gt;&lt;span class='varop'&gt;&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;clusterBy&lt;/span&gt; &lt;span class='varid'&gt;last&lt;/span&gt; &lt;span class='varid'&gt;antwords&lt;/span&gt;
&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='str'&gt;"the"&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='str'&gt;"some"&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='str'&gt;"tan"&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='str'&gt;"gets"&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='str'&gt;"ant"&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='str'&gt;"fat"&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;If we use &lt;em&gt;sort&lt;/em&gt; as the signature function, we can find anagrams:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varop'&gt;*&lt;/span&gt;&lt;span class='conid'&gt;Main&lt;/span&gt;&lt;span class='varop'&gt;&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;clusterBy&lt;/span&gt; &lt;span class='varid'&gt;sort&lt;/span&gt; &lt;span class='varid'&gt;antwords&lt;/span&gt;
&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='str'&gt;"fat"&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='str'&gt;"tan"&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='str'&gt;"ant"&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='str'&gt;"gets"&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='str'&gt;"the"&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='str'&gt;"some"&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;And that brings us back to the original puzzle.  To find the solution,
we must consider each unique pair of state names to form a &amp;#8220;word&amp;#8221; and
find the anagrams among a list of such &amp;#8220;words.&amp;#8221;&lt;/p&gt;


	&lt;p&gt;Assuming we are given
a list of state names on standard input, one state per line, we can
write the shell of our solution as follows:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;main&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;mapM_&lt;/span&gt; &lt;span class='varid'&gt;print&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;solve&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;lines&lt;/span&gt; &lt;span class='varop'&gt;=&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class='varid'&gt;getContents&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;The shell delegates the real work to &lt;em&gt;solve&lt;/em&gt;.  It&amp;#8217;s job is to
compute the unique, 2-state combinations from the original
list of states, and then find the anagrams among these combinations.
As before, finding the anagrams is simply a matter of calling
&lt;em&gt;clusterBy&lt;/em&gt; with the right signature function.  We also filter
out the trivial results, which are not valid solutions:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;solve&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;filter&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varop'&gt;&amp;gt;&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;length&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;clusterBy&lt;/span&gt; &lt;span class='varid'&gt;signature&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;ucombos&lt;/span&gt;
&lt;span class='varid'&gt;ucombos&lt;/span&gt; &lt;span class='varid'&gt;xs&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='varid'&gt;x&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='varid'&gt;y&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt; &lt;span class='keyglyph'&gt;|&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;xs&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;y&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;xs&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='varop'&gt;&amp;lt;&lt;/span&gt; &lt;span class='varid'&gt;y&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;span class='varid'&gt;signature&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;sort&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;filter&lt;/span&gt; &lt;span class='varid'&gt;isAlpha&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;concat&lt;/span&gt;   &lt;span class='comment'&gt;-- sort letters&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;That&amp;#8217;s it.  Now we can solve the puzzle by feeding our program a list of states:&lt;/p&gt;


&lt;div class="typedin"&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;$ runhaskell anagrams2.hs &amp;lt; states.txt&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;[[&amp;quot;NORTH CAROLINA&amp;quot;,&amp;quot;SOUTH DAKOTA&amp;quot;],
 [&amp;quot;NORTH DAKOTA&amp;quot;,&amp;quot;SOUTH CAROLINA&amp;quot;]]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;What a handy little function, that &lt;em&gt;clusterBy&lt;/em&gt;.&lt;/p&gt;


&lt;div class="update"&gt;

	&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; made clear that &lt;em&gt;clusterBy&lt;/em&gt; returns clusters in order
of ascending signature.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Update 2007-10-31:&lt;/strong&gt;  For more interesting discussion of &lt;em&gt;clusterBy&lt;/em&gt;
and the original puzzle from &lt;span class="caps"&gt;NPR&lt;/span&gt;, see Anders Pearson&amp;#8217;s blog: &lt;a href="http://thraxil.org/users/anders/posts/2007/10/30/A-Simple-Programming-Puzzle-Seen-Through-Three-Different-Lenses/"&gt;A Simple Programming Puzzle Seen Through Three Different Lenses&lt;/a&gt;.&lt;/p&gt;


&lt;/div&gt;</description>
      <pubDate>Sat, 01 Sep 2007 15:39:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:46727e92-f04a-4fab-90d8-7cefc6caee77</guid>
      <author>Tom Moertel</author>
      <link>http://blog.moertel.com/articles/2007/09/01/clusterby-a-handy-little-function-for-the-toolbox</link>
      <category>programming</category>
      <category>haskell</category>
      <category>puzzles</category>
      <category>clusterby</category>
      <category>hof</category>
      <category>functions</category>
      <trackback:ping>http://blog.moertel.com/articles/trackback/562</trackback:ping>
    </item>
    <item>
      <title>Directory-tree printing in Haskell, part three: lazy I/O</title>
      <description>&lt;p&gt;This article is part three in a series on introductory Haskell
programming.  In &lt;a href="http://blog.moertel.com/articles/2007/02/22/a-simple-directory-tree-printer-in-haskell"&gt;the first
article&lt;/a&gt;,
we wrote a small program to recursively scan file-system directories
and print their contents as &lt;span class="caps"&gt;ASCII&lt;/span&gt;-art trees.  In the &lt;a href="http://blog.moertel.com/articles/2007/03/07/directory-tree-printing-in-haskell-part-two-refactoring"&gt;second
article&lt;/a&gt;,
we refactored the program to make its logic more reusable by separating
the directory-scanning logic from the tree-printing logic.  In this
article, we will address a shortcoming of the refactored version: It
must scan directory hierarchies completely before printing their
trees, i.e., it must scan and &lt;em&gt;then&lt;/em&gt; print,
when doing both simultaneously is both more efficient and
more user friendly.&lt;/p&gt;


	&lt;p&gt;Recall from the previous article that our directory-printing program
is factored into three pieces of logic:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;&lt;em&gt;fsTraverse&lt;/em&gt;, which traverses a file-system hierarchy and returns a tree data structure;&lt;/li&gt;
		&lt;li&gt;&lt;em&gt;showTree&lt;/em&gt;, which converts a tree into lovingly crafted &lt;span class="caps"&gt;ASCII&lt;/span&gt; art; and&lt;/li&gt;
		&lt;li&gt;&lt;em&gt;traverseAndPrint&lt;/em&gt;, which prints the tree for a file-system hierarchy by
using the first two pieces of logic.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;The types of the functions are as follows:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;fsTraverse&lt;/span&gt;       &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;Path&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;DentName&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;IO&lt;/span&gt; &lt;span class='conid'&gt;DirTree&lt;/span&gt;
&lt;span class='varid'&gt;showTree&lt;/span&gt;         &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;Tree&lt;/span&gt; &lt;span class='conid'&gt;String&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;String&lt;/span&gt;
&lt;span class='varid'&gt;traverseAndPrint&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;Path&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;IO&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Note that &lt;em&gt;showTree&lt;/em&gt; is a pure function, but the other two return
&lt;em&gt;IO&lt;/em&gt; actions that may have side effects.&lt;/p&gt;


	&lt;p&gt;Within &lt;em&gt;traverseAndPrint&lt;/em&gt;, &lt;em&gt;fsTraverse&lt;/em&gt; and &lt;em&gt;showTree&lt;/em&gt; are combined
into a composite &lt;em&gt;IO&lt;/em&gt; action by the &lt;code&gt;=&amp;lt;&amp;lt;&lt;/code&gt; combinator:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;putStr&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;showTree&lt;/span&gt; &lt;span class='varop'&gt;=&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class='varid'&gt;fsTraverse&lt;/span&gt; &lt;span class='varid'&gt;root&lt;/span&gt; &lt;span class='varid'&gt;path&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;The sequencing semantics of Haskell&amp;#8217;s &lt;em&gt;IO&lt;/em&gt; monad forces all of the
effects of &lt;em&gt;fsTraverse&lt;/em&gt; to complete before any following
effects can begin.  To better understand these sequencing semantics,
let&amp;#8217;s consider a simple example.&lt;/p&gt;


	&lt;p&gt;The &lt;em&gt;IO&lt;/em&gt;-monad code,&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;a&lt;/span&gt; &lt;span class='varop'&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;can loosely be interpreted as running the action &lt;em&gt;a&lt;/em&gt;, which forces
its side effects to occur, and then running the action &lt;em&gt;b&lt;/em&gt;, which forces
its side effects to occur.&lt;/p&gt;


	&lt;p&gt;In reality, &lt;em&gt;a&lt;/em&gt; and &lt;em&gt;b&lt;/em&gt; are not actions.  They are
functions.  Like all Haskell functions, they are pure and have no side
effects.  It&amp;#8217;s just that &lt;em&gt;a&lt;/em&gt; and &lt;em&gt;b&lt;/em&gt; return values that
represent actions, and those actions may have side effects, and the
semantics of the &lt;em&gt;IO&lt;/em&gt; monad guarantee the ordering of those effects
(should the actions end up being connected to the runtime&amp;#8217;s
top-level &lt;em&gt;IO&lt;/em&gt; action and executed).  If you think that&amp;#8217;s weird, hold
that thought.  For now, all that&amp;#8217;s important is that, if the composite
action represented by the expression
(&lt;em&gt;a&lt;/em&gt;&amp;#160;&lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;&amp;#160;&lt;em&gt;b&lt;/em&gt;) is executed, the
effects of &lt;em&gt;a&lt;/em&gt;, regardless of how complex, will be executed
before the effects of &lt;em&gt;b&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;Thus if &lt;em&gt;a&lt;/em&gt; represents building a tree by recursively scanning
a file-system hierarchy, the &lt;em&gt;entire&lt;/em&gt; tree must be built before
&lt;em&gt;b&lt;/em&gt; ever gets a chance to do its thing.  For our particular
application, however, that particular sequencing is suboptimal.  We
know from our earlier, monolithic implementation that the 
file-system hierarchy can be scanned and printed simultaneously, which
is more efficient.  Ideally, then, our refactored
implementation should be just as efficient.&lt;/p&gt;


	&lt;p&gt;In this article, we will look at one way to maintain the clean,
logical separation of the &lt;em&gt;a&lt;/em&gt; part from the &lt;em&gt;b&lt;/em&gt; part
while allowing the parts&amp;#8217; effects to be interleaved for efficiency.
We will use an extension to the Haskell language to make the
directory-scanning action lazy so that it builds the tree as the tree
is consumed.&lt;/p&gt;


	&lt;p&gt;Ready?  Let&amp;#8217;s dive in.&lt;/p&gt;&lt;h3&gt; Lazy I/O&lt;/h3&gt;


	&lt;p&gt;I&amp;#8217;ll be up front: we are going to be naughty.  We are going to break
the effect-ordering guarantees of the &lt;em&gt;IO&lt;/em&gt; monad, but, if we are
careful, we can get away with it.  In fact, if you have used Haskell&amp;#8217;s
&lt;em&gt;getContents&lt;/em&gt; or &lt;em&gt;readFile&lt;/em&gt; functions, you have already used the
fruits of this very naughtiness.&lt;/p&gt;


	&lt;p&gt;Before we go down the dark path, however, let&amp;#8217;s spend a moment
understanding why we might want to be naughty.  Currently, our
tree-building code builds the entire tree for a file-system hierarchy
as one large &lt;em&gt;IO&lt;/em&gt; action.  If the hierarchy turns out to be large, the
tree could gobble up lots of memory before the printing process has
the chance to consume it.  Further, if the underlying file-system
operations are expensive, we could wait a long time before seeing any
output from our program.&lt;/p&gt;


	&lt;p&gt;If we could produce the tree lazily, both of these problems would go
away.  As we built the tree, our tree-printing process would consume
it, keeping the overall memory footprint low and keeping us informed
of progress with timely output.&lt;/p&gt;


	&lt;p&gt;To better visualize our tree-building code&amp;#8217;s laziness or lack
thereof, let&amp;#8217;s artificially raise the cost of visiting a file-system
node.  We will introduce &lt;em&gt;fsVisit&lt;/em&gt; to simulate a costly file-system
operation that takes 0.1 second to complete:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;fsVisit&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;DirNode&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;IO&lt;/span&gt; &lt;span class='conid'&gt;DentName&lt;/span&gt;
&lt;span class='varid'&gt;fsVisit&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='keyword'&gt;_&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;name&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='varid'&gt;usleep&lt;/span&gt; &lt;span class='num'&gt;100000&lt;/span&gt;
    &lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='varid'&gt;name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Now let&amp;#8217;s work &lt;em&gt;fsVisit&lt;/em&gt; into each step of our file-system-traversal
logic by revising &lt;em&gt;fsTraverseStep&lt;/em&gt;:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;fsTraverseStep&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;DirNode&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;IO&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;DentName&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='conid'&gt;DirNode&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;span class='varid'&gt;fsTraverseStep&lt;/span&gt; &lt;span class='varid'&gt;dnode&lt;/span&gt;&lt;span class='keyglyph'&gt;@&lt;/span&gt;&lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;path&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;node&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='varid'&gt;name&lt;/span&gt;     &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;fsVisit&lt;/span&gt; &lt;span class='varid'&gt;dnode&lt;/span&gt;
    &lt;span class='varid'&gt;children&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;fsGetChildren&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;path&lt;/span&gt; &lt;span class='varop'&gt;++&lt;/span&gt; &lt;span class='str'&gt;"/"&lt;/span&gt; &lt;span class='varop'&gt;++&lt;/span&gt; &lt;span class='varid'&gt;node&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
    &lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;name&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;children&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Now have a slow version of our original
&lt;strong&gt;tlist&lt;/strong&gt; program.  I recommend that you
&lt;a href="http://community.moertel.com/~thor/directory-printing/tlist-slow.hs"&gt;download the source code&lt;/a&gt; and compile it so that you can
run the program locally and experience the timing of its output.&lt;/p&gt;


	&lt;p&gt;If you run the program on a directory that contains a handful of
files, it will pause for a second or two while it performs our
artificially expensive directory scan.  Finally, the scan completed,
the program will print the directory tree all at once.&lt;/p&gt;


	&lt;p&gt;Now let&amp;#8217;s make the tree-building process lazy.  For this, we need the
&lt;em&gt;unsafeInterleaveIO&lt;/em&gt; combinator, an extension to Haskell 98.  (We will
examine why it is &amp;#8220;unsafe&amp;#8221; later.) Here is its type signature:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;unsafeInterleaveIO&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;IO&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;IO&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;What the combinator does is convert an action into a promise to
perform the action later, should its result be needed.  It takes an
&lt;em&gt;IO&lt;/em&gt; action, which might take a long time to carry out, and returns
a substitute action that produces a value immediately.  That value, however, is
a placeholder: when you try to consume it, you will be made to wait
while the real value is computed by performing the original action.&lt;/p&gt;


	&lt;p&gt;This ability to defer work via promises is exactly what we need to
make our directory scans lazy.  We can return each node of the tree as
a pair of promises, one to compute the node&amp;#8217;s root, and one to compute
the node&amp;#8217;s children.  Let&amp;#8217;s modify &lt;em&gt;fsTraverseStep&lt;/em&gt; to do just that:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='keyword'&gt;import&lt;/span&gt; &lt;span class='conid'&gt;System&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='conid'&gt;IO&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='conid'&gt;Unsafe&lt;/span&gt; &lt;span class='comment'&gt;-- add to imports at top of code&lt;/span&gt;

&lt;span class='varid'&gt;fsTraverseStep&lt;/span&gt; &lt;span class='varid'&gt;dnode&lt;/span&gt;&lt;span class='keyglyph'&gt;@&lt;/span&gt;&lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;path&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;node&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='varid'&gt;name&lt;/span&gt;     &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;unsafeInterleaveIO&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='varid'&gt;fsVisit&lt;/span&gt; &lt;span class='varid'&gt;dnode&lt;/span&gt;
    &lt;span class='varid'&gt;children&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;unsafeInterleaveIO&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt;
                &lt;span class='varid'&gt;fsGetChildren&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;path&lt;/span&gt; &lt;span class='varop'&gt;++&lt;/span&gt; &lt;span class='str'&gt;"/"&lt;/span&gt; &lt;span class='varop'&gt;++&lt;/span&gt; &lt;span class='varid'&gt;node&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
    &lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;name&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;children&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Now run this modified version of the program.  (For convenience, you
can &lt;a href="http://community.moertel.com/~thor/directory-printing/tlist-slow-lazy.hs"&gt;download this version of the source
code&lt;/a&gt;.)
Notice how each line of the directory tree is printed as it is visited
in the file-system scan.  We have made our tree-building process lazy!&lt;/p&gt;


	&lt;p&gt;Or have we?  Let&amp;#8217;s modify &lt;em&gt;fsGetChildren&lt;/em&gt; to print the list of
visible children as they are discovered:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;fsGetChildren&lt;/span&gt; &lt;span class='varid'&gt;path&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='varid'&gt;contents&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;getDirectoryContents&lt;/span&gt; &lt;span class='varid'&gt;path&lt;/span&gt; &lt;span class='varop'&gt;`catch`&lt;/span&gt; &lt;span class='varid'&gt;const&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
    &lt;span class='keyword'&gt;let&lt;/span&gt; &lt;span class='varid'&gt;visibles&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;sort&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;filter&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varop'&gt;`notElem`&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='str'&gt;"."&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='str'&gt;".."&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='varid'&gt;contents&lt;/span&gt;
    &lt;span class='varid'&gt;print&lt;/span&gt; &lt;span class='varid'&gt;visibles&lt;/span&gt;  &lt;span class='comment'&gt;-- &amp;lt;--- add this line&lt;/span&gt;
    &lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;map&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varid'&gt;path&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varid'&gt;visibles&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Recompiling and re-running our &amp;#8220;lazy&amp;#8221; program shows that all of the
children are found before any of the printing occurs.  In other words,
even if we are visiting each node lazily, we are still &lt;em&gt;finding&lt;/em&gt; all
of the nodes in the hierarchy before the first node of the resulting
tree is emitted from &lt;em&gt;fsTraverse&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;To see why, let&amp;#8217;s examine the source code for &lt;em&gt;unfoldTreeM&lt;/em&gt;, which is
the library function we used to build the tree using our &lt;em&gt;fsTraverseStep&lt;/em&gt;
function:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;unfoldTreeM&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;b&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;IO&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;a&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='varid'&gt;b&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;b&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;IO&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;Tree&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;span class='varid'&gt;unfoldTreeM&lt;/span&gt; &lt;span class='varid'&gt;step&lt;/span&gt; &lt;span class='varid'&gt;seed&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;root&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;seeds&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;step&lt;/span&gt; &lt;span class='varid'&gt;seed&lt;/span&gt;                &lt;span class='comment'&gt;-- (1)&lt;/span&gt;
    &lt;span class='varid'&gt;children&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;mapM&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;unfoldTreeM&lt;/span&gt; &lt;span class='varid'&gt;step&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varid'&gt;seeds&lt;/span&gt; &lt;span class='comment'&gt;-- (2)&lt;/span&gt;
    &lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;Node&lt;/span&gt; &lt;span class='varid'&gt;root&lt;/span&gt; &lt;span class='varid'&gt;children&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;               &lt;span class='comment'&gt;-- (3)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;When &lt;em&gt;unfoldTreeM&lt;/em&gt; calls our step function in line (1), it gets back a
pair of promises, one for the &lt;em&gt;root&lt;/em&gt; of the tree and another for the
&lt;em&gt;seeds&lt;/em&gt; from which to build the root&amp;#8217;s children.  In line (2), we see
the problem: In order to convert &lt;em&gt;seeds&lt;/em&gt; into a list of child nodes,
&lt;em&gt;unfoldTreeM&lt;/em&gt; calls &lt;em&gt;mapM&lt;/em&gt; to recursively apply itself to &lt;em&gt;seeds&lt;/em&gt;.
The &lt;em&gt;mapM&lt;/em&gt; action is sequenced before the &lt;em&gt;return&lt;/em&gt; in line (3), and
thus the value of &lt;em&gt;seeds&lt;/em&gt; is consumed before the new tree &lt;em&gt;Node&lt;/em&gt; can
be constructed.  In other words, because the &lt;em&gt;mapM&lt;/em&gt; action isn&amp;#8217;t
deferred and because it depends on the value of &lt;em&gt;seeds&lt;/em&gt;, it forces us
to make good on our &lt;em&gt;seeds&lt;/em&gt; promise earlier than we
would like.&lt;/p&gt;


	&lt;p&gt;To get around this problem, we can create a lazy variant
of &lt;em&gt;unfoldTreeM&lt;/em&gt;.  This version defers the &lt;em&gt;mapM&lt;/em&gt; action
until the &lt;em&gt;children&lt;/em&gt; value is consumed:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;lazyUnfoldTreeM&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;b&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;IO&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;a&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='varid'&gt;b&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;b&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;IO&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;Tree&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;span class='varid'&gt;lazyUnfoldTreeM&lt;/span&gt; &lt;span class='varid'&gt;step&lt;/span&gt; &lt;span class='varid'&gt;seed&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;root&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;seeds&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;step&lt;/span&gt; &lt;span class='varid'&gt;seed&lt;/span&gt;
    &lt;span class='varid'&gt;children&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;unsafeInterleaveIO&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt;
                &lt;span class='varid'&gt;mapM&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;lazyUnfoldTreeM&lt;/span&gt; &lt;span class='varid'&gt;step&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varid'&gt;seeds&lt;/span&gt;
    &lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;Node&lt;/span&gt; &lt;span class='varid'&gt;root&lt;/span&gt; &lt;span class='varid'&gt;children&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Then we can use this version in our high-level &lt;em&gt;fsTraverse&lt;/em&gt; function:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;fsTraverse&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;curry&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;lazyUnfoldTreeM&lt;/span&gt; &lt;span class='varid'&gt;fsTraverseStep&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;These changes made, we have a fully lazy version of the
tree-building code.  To see it in action, &lt;a href="http://community.moertel.com/~thor/directory-printing/tlist-slow-lazy2.hs"&gt;download this version of
the whole program&amp;#8217;s source
code&lt;/a&gt;,
compile it, and give it a try.  If you add the &lt;em&gt;print&lt;/em&gt; line to
&lt;em&gt;fsGetChildren&lt;/em&gt; like we did earlier, you&amp;#8217;ll see that this version
expands each directory only when its contents are needed.  Now
our lazy directory-tree-building code works as we would expect.&lt;/p&gt;


	&lt;p&gt;Mission accomplished.&lt;/p&gt;


	&lt;h3&gt;Optional: Hiding the plumbing&lt;/h3&gt;


	&lt;p&gt;[&lt;strong&gt;Note:&lt;/strong&gt; &lt;em&gt;The technique described in this section is hacky.  I&amp;#8217;m
including it because it&amp;#8217;s fun, not because I think it&amp;#8217;s good
Haskell-programming practice.&lt;/em&gt;]&lt;/p&gt;


	&lt;p&gt;It&amp;#8217;s unfortunate that we had to create our own version of the library
function &lt;em&gt;unfoldTreeM&lt;/em&gt;.  With its introduction, we lost some of our
code&amp;#8217;s tidiness.  Can we get our clean code back?&lt;/p&gt;


	&lt;p&gt;Maybe we can.  Recall that &lt;em&gt;unfoldTreeM&lt;/em&gt; works for any monad.  What if
we created a &lt;em&gt;LazyIO&lt;/em&gt; monad that was just like &lt;em&gt;IO&lt;/em&gt; except that each
action within it was performed only when its value was consumed?  With
this monad, we could eliminate the need for a special, lazy version of
&lt;em&gt;unfoldTreeM&lt;/em&gt;: the normal version would &amp;#8220;do the right thing,&amp;#8221; using our
monad.&lt;/p&gt;


	&lt;p&gt;Let&amp;#8217;s create our &lt;em&gt;LazyIO&lt;/em&gt; monad.  First, we&amp;#8217;ll need a new module,&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='keyword'&gt;module&lt;/span&gt; &lt;span class='conid'&gt;LazyIO&lt;/span&gt;
 &lt;span class='layout'&gt;(&lt;/span&gt; &lt;span class='conid'&gt;LazyIO&lt;/span&gt;&lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;runLazy&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;deferIO&lt;/span&gt; &lt;span class='layout'&gt;)&lt;/span&gt;
&lt;span class='keyword'&gt;where&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;and, of course, we&amp;#8217;ll need to import &lt;em&gt;unsafeInterleaveIO&lt;/em&gt;:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='keyword'&gt;import&lt;/span&gt; &lt;span class='conid'&gt;System&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='conid'&gt;IO&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='conid'&gt;Unsafe&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;unsafeInterleaveIO&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;We will define &lt;em&gt;LazyIO&lt;/em&gt; to be a type wrapper around the regular &lt;em&gt;IO&lt;/em&gt;
type:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='keyword'&gt;newtype&lt;/span&gt; &lt;span class='conid'&gt;LazyIO&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;LazyIO&lt;/span&gt; &lt;span class='layout'&gt;{&lt;/span&gt; &lt;span class='varid'&gt;unLazyIO&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;IO&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt; &lt;span class='layout'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Note that our module definition, above, does not export the &lt;em&gt;LazyIO&lt;/em&gt;
type&amp;#8217;s data constructor.  The only way, then, to construct and
destruct values will be through our interface.&lt;/p&gt;


	&lt;p&gt;To construct a value, we will provide &lt;em&gt;deferIO&lt;/em&gt;, which converts a normal
&lt;em&gt;IO&lt;/em&gt; action into a &lt;em&gt;LazyIO&lt;/em&gt; action:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;deferIO&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;IO&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;LazyIO&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt;
&lt;span class='varid'&gt;deferIO&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;LazyIO&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;To get a regular &lt;em&gt;IO&lt;/em&gt; action &amp;#8220;out&amp;#8221; of our monad, we will provide &lt;em&gt;runLazy&lt;/em&gt;
which converts a &lt;em&gt;LazyIO&lt;/em&gt; action into an &lt;em&gt;IO&lt;/em&gt; action that is deferred
until it is consumed:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;runLazy&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;LazyIO&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;IO&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt;
&lt;span class='varid'&gt;runLazy&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;unsafeInterleaveIO&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;unLazyIO&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;The key to our monad is that the only way to get an &lt;em&gt;IO&lt;/em&gt; action
out of &lt;em&gt;LazyIO&lt;/em&gt; is through &lt;em&gt;runLazy&lt;/em&gt; and thus through
&lt;em&gt;unsafeInterleaveIO&lt;/em&gt;.  In fact, injecting an &lt;em&gt;IO&lt;/em&gt; action into our
monad and then immediately pulling it out again is identical to deferring
it with &lt;em&gt;unsafeInterleaveIO&lt;/em&gt;:&lt;/p&gt;


&lt;p style="text-align:center"&gt;
(&lt;em&gt;runLazy&lt;/em&gt;&amp;#160;.&amp;#160;&lt;em&gt;deferIO&lt;/em&gt;)&amp;#160;=&amp;#160;&lt;em&gt;unsafeInterleaveIO&lt;/em&gt;
&lt;/p&gt;

	&lt;p&gt;But what makes a monad interesting are its &lt;em&gt;return&lt;/em&gt; and &lt;em&gt;bind&lt;/em&gt;
definitions.  Here are ours:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='keyword'&gt;instance&lt;/span&gt; &lt;span class='conid'&gt;Monad&lt;/span&gt; &lt;span class='conid'&gt;LazyIO&lt;/span&gt; &lt;span class='keyword'&gt;where&lt;/span&gt;
    &lt;span class='varid'&gt;return&lt;/span&gt;     &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;LazyIO&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;return&lt;/span&gt;
    &lt;span class='varid'&gt;ma&lt;/span&gt; &lt;span class='varop'&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class='varid'&gt;fmb&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;LazyIO&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='varid'&gt;runLazy&lt;/span&gt; &lt;span class='varid'&gt;ma&lt;/span&gt; &lt;span class='varop'&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class='varid'&gt;unLazyIO&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;fmb&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Our &lt;em&gt;return&lt;/em&gt; simply returns the given value in the underlying &lt;em&gt;IO&lt;/em&gt;
monad and wraps the resulting action with the &lt;em&gt;LazyIO&lt;/em&gt; constructor.
The implication is that the only way to unwrap the action is via
&lt;em&gt;runLazy&lt;/em&gt;, which will defer it.&lt;/p&gt;


	&lt;p&gt;Likewise, our &lt;em&gt;bind&lt;/em&gt; (&lt;code&gt;&amp;gt;&amp;gt;=&lt;/code&gt;) creates a composite &lt;em&gt;LazyIO&lt;/em&gt;
action from another &lt;em&gt;LazyIO&lt;/em&gt; action and a function that produces
a &lt;em&gt;LazyIO&lt;/em&gt; action given the result of the first action.  The
composite action and the first action are deferred.  (Deferring
the action produced by &lt;em&gt;fmb&lt;/em&gt; would be redundant because the
value it produces is the value of the composite action, which
is already deferred.)&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Exercise:&lt;/strong&gt;  Is &lt;em&gt;LazyIO&lt;/em&gt; really a monad?  Prove (or disprove) that
it satisfies the monad laws.&lt;/p&gt;


	&lt;p&gt;To see the effect of our monad, let&amp;#8217;s apply its definitions to the
following simple lazy IO action.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;runLazy&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='num'&gt;5&lt;/span&gt;
    &lt;span class='varid'&gt;deferIO&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;print&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;With a little expansion, application, and simplification (try
it), we arrive at the following:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;unsafeInterleaveIO&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;unsafeInterleaveIO&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='num'&gt;5&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
    &lt;span class='varid'&gt;print&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Note that the entire, composite IO action is deferred, as are the
actions upon which it depends, which is exactly what we want.&lt;/p&gt;


	&lt;p&gt;Now we can return to housecleaning.  With our new monad, we can banish
both &lt;em&gt;unsafeInterleaveIO&lt;/em&gt; and our custom, lazy version of
&lt;em&gt;unfoldTreeM&lt;/em&gt; from our otherwise uncluttered code.&lt;/p&gt;


	&lt;p&gt;Step one of the housecleaning is to modify &lt;em&gt;fsTraverseStep&lt;/em&gt; to use the
&lt;em&gt;LazyIO&lt;/em&gt; monad instead of explicit calls to &lt;em&gt;unsafeInterleaveIO&lt;/em&gt;:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='keyword'&gt;import&lt;/span&gt; &lt;span class='conid'&gt;LazyIO&lt;/span&gt;   &lt;span class='comment'&gt;-- add to module imports at top of code&lt;/span&gt;

&lt;span class='varid'&gt;fsTraverseStep&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;DirNode&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;LazyIO&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;DentName&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='conid'&gt;DirNode&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;span class='varid'&gt;fsTraverseStep&lt;/span&gt; &lt;span class='varid'&gt;dnode&lt;/span&gt;&lt;span class='keyglyph'&gt;@&lt;/span&gt;&lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;path&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;node&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='varid'&gt;name&lt;/span&gt;     &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;deferIO&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;fsVisit&lt;/span&gt; &lt;span class='varid'&gt;dnode&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
    &lt;span class='varid'&gt;children&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;deferIO&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;fsGetChildren&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;path&lt;/span&gt; &lt;span class='varop'&gt;++&lt;/span&gt; &lt;span class='str'&gt;"/"&lt;/span&gt; &lt;span class='varop'&gt;++&lt;/span&gt; &lt;span class='varid'&gt;node&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
    &lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;name&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;children&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Step two is to rewrite &lt;em&gt;fsTraverse&lt;/em&gt; in terms of &lt;em&gt;runLazy&lt;/em&gt; and the
plain-old &lt;em&gt;unfoldTreeM&lt;/em&gt; provided by the &lt;em&gt;Data.Tree&lt;/em&gt; library:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;fsTraverse&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;Path&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;DentName&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;IO&lt;/span&gt; &lt;span class='conid'&gt;DirTree&lt;/span&gt;
&lt;span class='varid'&gt;fsTraverse&lt;/span&gt; &lt;span class='varid'&gt;p&lt;/span&gt; &lt;span class='varid'&gt;n&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;runLazy&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;unfoldTreeM&lt;/span&gt; &lt;span class='varid'&gt;fsTraverseStep&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;p&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='varid'&gt;n&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Step three is to remove &lt;em&gt;lazyUnfoldTreeM&lt;/em&gt; from our code: &lt;em&gt;Snip&lt;/em&gt;!&lt;/p&gt;


	&lt;p&gt;And we&amp;#8217;re done.  The code:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://community.moertel.com/~thor/directory-printing/tlist-slow-lazy-final.hs"&gt;tlist-slow-lazy-final.hs&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://community.moertel.com/~thor/directory-printing/LazyIO.hs"&gt;LazyIO.hs&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;To compile, here&amp;#8217;s the command to use:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;ghc -O2 -o tlist-slow-lazy-final --make tlist-slow-lazy-final.hs
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Give the program a test run and convince yourself that it works as
advertised.&lt;/p&gt;


	&lt;h3&gt;Why unsafeInterleaveIO is &amp;#8220;unsafe&amp;#8221;&lt;/h3&gt;


	&lt;p&gt;Now let&amp;#8217;s get back to the &amp;#8220;unsafe&amp;#8221; part of &lt;em&gt;unsafeInterleaveIO&lt;/em&gt;.
What&amp;#8217;s that about?&lt;/p&gt;


	&lt;p&gt;Haskell programmers label as &amp;#8220;unsafe&amp;#8221; those functions that allow you
to circumvent Haskell&amp;#8217;s safety guarantees.  It&amp;#8217;s a blunt way of
letting you know that, if you use one of these functions, you can
shoot yourself in the foot if your aim is bad.  Thus, by using an
&amp;#8220;unsafe&amp;#8221; function, you place the burden of proving that your code is
safe upon yourself.&lt;/p&gt;


	&lt;p&gt;As we have already seen, we can use &lt;em&gt;unsafeInterleaveIO&lt;/em&gt; to get around
the side-effect ordering guarantees that Haskell&amp;#8217;s &lt;em&gt;IO&lt;/em&gt; monad normally
provides.  If we&amp;#8217;re not careful, this could come back to bite us.&lt;/p&gt;


	&lt;p&gt;Using &lt;em&gt;unsafeInterleaveIO&lt;/em&gt; on an action effectively removes the action
from the normal world of &lt;em&gt;IO&lt;/em&gt; actions and places it into its own
parallel world, where it can run on its own schedule.  Creating these
parallel worlds is safe as long as we don&amp;#8217;t attempt to do anything
that depends upon the ordering of effects across worlds.&lt;/p&gt;


	&lt;p&gt;For example, take a look at this small Haskell program that
will let us compare the output of a simple test under normal
and unsafe-interleaved I/O sequencing:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='comment'&gt;{- file: unsafe-demo.hs -}&lt;/span&gt;

&lt;span class='keyword'&gt;module&lt;/span&gt; &lt;span class='conid'&gt;Main&lt;/span&gt; &lt;span class='keyword'&gt;where&lt;/span&gt;

&lt;span class='keyword'&gt;import&lt;/span&gt; &lt;span class='conid'&gt;System&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='conid'&gt;Environment&lt;/span&gt;
&lt;span class='keyword'&gt;import&lt;/span&gt; &lt;span class='conid'&gt;System&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='conid'&gt;IO&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='conid'&gt;Unsafe&lt;/span&gt;

&lt;span class='varid'&gt;main&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='varid'&gt;args&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;getArgs&lt;/span&gt;
    &lt;span class='keyword'&gt;if&lt;/span&gt; &lt;span class='varid'&gt;args&lt;/span&gt; &lt;span class='varop'&gt;==&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='str'&gt;"lazy"&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
        &lt;span class='keyword'&gt;then&lt;/span&gt; &lt;span class='varid'&gt;doTest&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;unsafeInterleaveIO&lt;/span&gt; &lt;span class='varid'&gt;getLine&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
        &lt;span class='keyword'&gt;else&lt;/span&gt; &lt;span class='varid'&gt;doTest&lt;/span&gt; &lt;span class='varid'&gt;getLine&lt;/span&gt;

&lt;span class='varid'&gt;doTest&lt;/span&gt; &lt;span class='varid'&gt;myGetLine&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='varid'&gt;line1&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;myGetLine&lt;/span&gt;    &lt;span class='comment'&gt;-- (1)&lt;/span&gt;
    &lt;span class='varid'&gt;line2&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;myGetLine&lt;/span&gt;    &lt;span class='comment'&gt;-- (2)&lt;/span&gt;
    &lt;span class='varid'&gt;putStrLn&lt;/span&gt; &lt;span class='varid'&gt;line2&lt;/span&gt;
    &lt;span class='varid'&gt;putStrLn&lt;/span&gt; &lt;span class='varid'&gt;line1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;The &lt;em&gt;main&lt;/em&gt; function checks the command line to see if we have passed
the &amp;#8220;lazy&amp;#8221; argument.  If so, it passes (&lt;em&gt;unsafeInterleaveIO&lt;/em&gt; &lt;em&gt;getLine&lt;/em&gt;)
to &lt;em&gt;doTest&lt;/em&gt;; otherwise, it passes the straight &lt;em&gt;getLine&lt;/em&gt; function.&lt;/p&gt;


	&lt;p&gt;The &lt;em&gt;doTest&lt;/em&gt; function, in turn, constructs an &lt;em&gt;IO&lt;/em&gt; action that reads
two lines from the standard input using whichever version of &lt;em&gt;getLine&lt;/em&gt;
we have provided.  First it reads &lt;em&gt;line1&lt;/em&gt;, then &lt;em&gt;line2&lt;/em&gt;.  Finally, it
prints the lines in the opposite order: first &lt;em&gt;line2&lt;/em&gt;, then &lt;em&gt;line1&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;Let&amp;#8217;s test this program on the following two-line file:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;$ cat onetwo.txt
one
two
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Ready?  First, let&amp;#8217;s run the straight-&lt;em&gt;IO&lt;/em&gt; version:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;$ runhaskell unsafe-demo.hs &amp;lt; onetwo.txt
two
one
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;As we would expect, the program read the lines from the file and printed
them in reverse order.&lt;/p&gt;


	&lt;p&gt;Now, let&amp;#8217;s pass the &amp;#8220;lazy&amp;#8221; flag, which wraps the &lt;em&gt;getLine&lt;/em&gt; calls
with &lt;em&gt;unsafeInterleaveIO&lt;/em&gt;:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;$ runhaskell unsafe-demo.hs lazy &amp;lt; onetwo.txt
one
two
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;For some reason, when we printed &lt;em&gt;line2&lt;/em&gt; we got the first
line of the file, not the second.  Likewise, when we printed &lt;em&gt;line1&lt;/em&gt;,
we got the second line.  What happened?&lt;/p&gt;


	&lt;p&gt;What happened is that in lines (1) and (2) of the code, &lt;em&gt;myGetLine&lt;/em&gt;
evaluated to (&lt;em&gt;unsafeInterleaveIO&lt;/em&gt; &lt;em&gt;getLine&lt;/em&gt;).  Thus &lt;em&gt;line1&lt;/em&gt; and
&lt;em&gt;line2&lt;/em&gt; were bound to placeholder values that were connected to
deferred &lt;em&gt;getLine&lt;/em&gt; actions, each existing in its own parallel
world and utterly unconnected to each other or to the main, normal
&lt;em&gt;IO&lt;/em&gt; world.  The &lt;em&gt;only&lt;/em&gt; thing, then, that could determine the order in
which the two actions were performed was the order in which their
values were consumed.  And, because we printed &lt;em&gt;line2&lt;/em&gt; first, its
deferred &lt;em&gt;getLine&lt;/em&gt; action was the first to be performed, and so it
read the &lt;em&gt;first&lt;/em&gt; line of the input from the file.  By the time we
printed &lt;em&gt;line1&lt;/em&gt;, causing its deferred &lt;em&gt;getLine&lt;/em&gt; action to be
performed, the first line of the file had already been consumed, and
so the second line was returned.&lt;/p&gt;


	&lt;p&gt;Oops.&lt;/p&gt;


	&lt;p&gt;After this demonstration, we might wonder whether our lazy
tree-building code is safe.  After all, we&amp;#8217;re using
&lt;em&gt;unsafeInterleaveIO&lt;/em&gt; like crazy behind the scenes.  Let&amp;#8217;s
think about it.&lt;/p&gt;


	&lt;p&gt;Recall that, once detached from the main &lt;em&gt;IO&lt;/em&gt; world, the only
thing that determines when a deferred action is performed is
when its value is consumed.  That knowledge gives us the key
to unlock the safety argument for our tree-building code.&lt;/p&gt;


	&lt;p&gt;Recall the type of &lt;em&gt;fsTraverse&lt;/em&gt;:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;fsTraverse&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;Path&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;DentName&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;IO&lt;/span&gt; &lt;span class='conid'&gt;DirTree&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;The action that &lt;em&gt;fsTraverse&lt;/em&gt; produces returns a &lt;em&gt;DirTree&lt;/em&gt; value,
which is a type synonym for a &lt;em&gt;Tree&lt;/em&gt; of &lt;em&gt;DentName&lt;/em&gt; values (file
names).  The &lt;em&gt;Tree&lt;/em&gt; data type has only one constructor:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='keyword'&gt;data&lt;/span&gt; &lt;span class='conid'&gt;Tree&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;Node&lt;/span&gt; &lt;span class='layout'&gt;{&lt;/span&gt; &lt;span class='varid'&gt;rootLabel&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;
                     &lt;span class='varid'&gt;subForest&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='conid'&gt;Tree&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt; &lt;span class='layout'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Each &lt;em&gt;Node&lt;/em&gt; represents a tree: a root label and a sub-forest of
children trees.  Because of this representation, we cannot visit a
node in a tree without first having visited all of its ancestors.  In
order to get to a child node in the tree, for example, we must go
through the &lt;em&gt;subForest&lt;/em&gt; value of its parent.  Attempting to consume that
value will force the attached, deferred action to be performed.  That
action, in turn, will fetch the contents of the parent&amp;#8217;s directory and
package each item, including the child we&amp;#8217;re trying to get, into its
own &lt;em&gt;Node&lt;/em&gt;, the &lt;em&gt;root&lt;/em&gt; and &lt;em&gt;subForest&lt;/em&gt; of which will contain deferred
actions for scanning further into the file-system hierarchy.  Thus a
top-down sequencing will be imposed on the deferred &lt;em&gt;IO&lt;/em&gt; actions
attached to those nodes.  Fortunately, we &lt;em&gt;want&lt;/em&gt; a top-down traversal
because that&amp;#8217;s the way we must descend directory hierarchies in the
file system.  Therefore, we have good reason to be assured of the
safety of using &lt;em&gt;unsafeInterleaveIO&lt;/em&gt; for this particular application.&lt;/p&gt;


	&lt;p&gt;For other applications, however, we must repeat this safety analysis
anew, lest we allow the parallel words of our deferred actions to
collide in unpleasant ways.  &lt;em&gt;Caveat coder.&lt;/em&gt;&lt;/p&gt;


	&lt;h3&gt; Review and next time&lt;/h3&gt;


	&lt;p&gt;In this installment of our ever-lengthening series of articles on
directory printing, we revised our refactored directory-printing code
to restore the efficiency of our original, monolithic implementation.
In doing so, we experimented with lazy I/O and deferring &lt;em&gt;IO&lt;/em&gt; actions
by using the &lt;em&gt;unsafeInterleaveIO&lt;/em&gt; function.&lt;/p&gt;


	&lt;p&gt;At first we inserted a customized version of the library function
&lt;em&gt;unfoldTreeM&lt;/em&gt; into our code to effect the desired laziness, but a
little monad hacking allowed us to get rid of this intrusion.  When we
were done, we not only had a lean, lazy directory printer but also a
new (and potentially unsafe) &lt;em&gt;LazyIO&lt;/em&gt; library, which might prove
useful in the future.&lt;/p&gt;


	&lt;p&gt;We also looked at the kind of problems that &lt;em&gt;unsafeInterleaveIO&lt;/em&gt; can
cause if we are not careful.  Nevertheless, we were able to argue
that our particular use of this function is safe: the &lt;em&gt;Tree&lt;/em&gt; data
structure ensures that we must consume tree nodes in the top-down
order in which our directory-scanning must occur.&lt;/p&gt;


	&lt;p&gt;Still, our directory-printing code has problems.  We haven&amp;#8217;t yet
improved its lackluster error-handling policy.  Nor have we made the
directory-scanning code amenable to uses beyond our immediate needs
for directory printing.  Next time, we will solve both of these
problems.&lt;/p&gt;</description>
      <pubDate>Wed, 28 Mar 2007 15:40:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:ebfb6644-c73e-4f86-af5c-c3fe026b515d</guid>
      <author>Tom Moertel</author>
      <link>http://blog.moertel.com/articles/2007/03/28/directory-tree-printing-in-haskell-part-three-lazy-i-o</link>
      <category>haskell</category>
      <category>haskell</category>
      <category>trees</category>
      <category>io</category>
      <category>directory_tree_series</category>
      <category>laziness</category>
      <category>lazy</category>
      <trackback:ping>http://blog.moertel.com/articles/trackback/420</trackback:ping>
    </item>
    <item>
      <title>Directory-tree printing in Haskell, part two: refactoring</title>
      <description>&lt;p&gt;In &lt;a href="http://blog.moertel.com/articles/2007/02/22/a-simple-directory-tree-printer-in-haskell"&gt;my previous article on writing a simple directory-tree printer in
Haskell&lt;/a&gt;,
I wrote a small program to recursively scan file-system
directories and print their contents as &lt;span class="caps"&gt;ASCII&lt;/span&gt;-art trees.  The
program made for an approachable example of how to use Haskell for
&amp;#8220;imperative&amp;#8221; tasks, but it has a few problems.&lt;/p&gt;


	&lt;p&gt;First, the directory-scanning logic and tree-printing logic are
intertwined.  Neither is reusable.  Second, both bits of logic are
rigid, specialized for this particular task.  Even if you could
reuse them, you wouldn&amp;#8217;t &lt;em&gt;want&lt;/em&gt; to.&lt;/p&gt;


	&lt;p&gt;In this article, the second in a series, we will explore ways to make
our original code more reusable.  We will separate the directory
scanning from the tree printing, harness the power of some old
friends from Haskell&amp;#8217;s libraries, and think about the costs
and benefits of our changes.&lt;/p&gt;


	&lt;h3&gt;The plan&lt;/h3&gt;


	&lt;p&gt;Recall our original directory tree&amp;#8211;listing solution, the
core of which I will reprint below:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;tlist&lt;/span&gt; &lt;span class='varid'&gt;path&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt;
    &lt;span class='varid'&gt;visit&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='keyword'&gt;if&lt;/span&gt; &lt;span class='str'&gt;"/"&lt;/span&gt; &lt;span class='varop'&gt;`isPrefixOf`&lt;/span&gt; &lt;span class='varid'&gt;path&lt;/span&gt; &lt;span class='keyword'&gt;then&lt;/span&gt; &lt;span class='str'&gt;""&lt;/span&gt; &lt;span class='keyword'&gt;else&lt;/span&gt; &lt;span class='str'&gt;"."&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='str'&gt;""&lt;/span&gt; &lt;span class='str'&gt;""&lt;/span&gt; &lt;span class='str'&gt;""&lt;/span&gt; &lt;span class='varid'&gt;path&lt;/span&gt;

&lt;span class='varid'&gt;visit&lt;/span&gt; &lt;span class='varid'&gt;path&lt;/span&gt; &lt;span class='varid'&gt;leader&lt;/span&gt; &lt;span class='varid'&gt;tie&lt;/span&gt; &lt;span class='varid'&gt;arm&lt;/span&gt; &lt;span class='varid'&gt;node&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='varid'&gt;putStrLn&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;leader&lt;/span&gt; &lt;span class='varop'&gt;++&lt;/span&gt; &lt;span class='varid'&gt;arm&lt;/span&gt; &lt;span class='varop'&gt;++&lt;/span&gt; &lt;span class='varid'&gt;tie&lt;/span&gt; &lt;span class='varop'&gt;++&lt;/span&gt; &lt;span class='varid'&gt;node&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
    &lt;span class='varid'&gt;visitChildren&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;path&lt;/span&gt; &lt;span class='varop'&gt;++&lt;/span&gt; &lt;span class='str'&gt;"/"&lt;/span&gt; &lt;span class='varop'&gt;++&lt;/span&gt; &lt;span class='varid'&gt;node&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;leader&lt;/span&gt; &lt;span class='varop'&gt;++&lt;/span&gt; &lt;span class='varid'&gt;extension&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
  &lt;span class='keyword'&gt;where&lt;/span&gt;
    &lt;span class='varid'&gt;extension&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;case&lt;/span&gt; &lt;span class='varid'&gt;arm&lt;/span&gt; &lt;span class='keyword'&gt;of&lt;/span&gt; &lt;span class='str'&gt;""&lt;/span&gt;  &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='str'&gt;""&lt;/span&gt;&lt;span class='layout'&gt;;&lt;/span&gt; &lt;span class='str'&gt;"`"&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='str'&gt;"    "&lt;/span&gt;&lt;span class='layout'&gt;;&lt;/span&gt; &lt;span class='keyword'&gt;_&lt;/span&gt;   &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='str'&gt;"|   "&lt;/span&gt;

&lt;span class='varid'&gt;visitChildren&lt;/span&gt; &lt;span class='varid'&gt;path&lt;/span&gt; &lt;span class='varid'&gt;leader&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt;
    &lt;span class='varid'&gt;whenM&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;doesDirectoryExist&lt;/span&gt; &lt;span class='varid'&gt;path&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
        &lt;span class='varid'&gt;contents&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;getDirectoryContents&lt;/span&gt; &lt;span class='varid'&gt;path&lt;/span&gt;
            &lt;span class='varop'&gt;`catch`&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='keyglyph'&gt;\&lt;/span&gt;&lt;span class='varid'&gt;e&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='varid'&gt;show&lt;/span&gt; &lt;span class='varid'&gt;e&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
        &lt;span class='keyword'&gt;let&lt;/span&gt; &lt;span class='varid'&gt;visibles&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;sort&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;filter&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varop'&gt;`notElem`&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='str'&gt;"."&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='str'&gt;".."&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='varid'&gt;contents&lt;/span&gt;
            &lt;span class='varid'&gt;arms&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;replicate&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;length&lt;/span&gt; &lt;span class='varid'&gt;visibles&lt;/span&gt; &lt;span class='comment'&gt;-&lt;/span&gt; &lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='str'&gt;"|"&lt;/span&gt; &lt;span class='varop'&gt;++&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='str'&gt;"`"&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
        &lt;span class='varid'&gt;zipWithM_&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;visit&lt;/span&gt; &lt;span class='varid'&gt;path&lt;/span&gt; &lt;span class='varid'&gt;leader&lt;/span&gt; &lt;span class='str'&gt;"-- "&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varid'&gt;arms&lt;/span&gt; &lt;span class='varid'&gt;visibles&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;The &lt;em&gt;tlist&lt;/em&gt; function kicks off the process for a particular
file-system &lt;em&gt;path&lt;/em&gt;, handing off to &lt;em&gt;visit&lt;/em&gt; which recursively descends the
directory tree from the root node.  The &lt;em&gt;visit&lt;/em&gt; function calls
&lt;em&gt;visitChildren&lt;/em&gt; to expand the subtree, if any, for each node visited.
The &lt;em&gt;visitChildren&lt;/em&gt; function, in turn, calls back to &lt;em&gt;visit&lt;/em&gt; to
repeat the process for each child in the subtree.
In effect, we are traversing the tree rooted at &lt;em&gt;path&lt;/em&gt;, printing each
node in passing.&lt;/p&gt;


	&lt;p&gt;To separate the traversal part from the printing part, we will
introduce a tree data structure.  The file system&amp;#8211;traversal code
will emit a tree, and the tree-showing code will consume a tree.  We
will rewrite our old &lt;em&gt;tlist&lt;/em&gt; function, which we might as well rename to
the more descriptive &lt;em&gt;traverseAndPrint&lt;/em&gt;, to glue the two pieces
together with the tree serving as glue:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;traverseAndPrint&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;Path&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;IO&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;span class='varid'&gt;traverseAndPrint&lt;/span&gt; &lt;span class='varid'&gt;path&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='varid'&gt;tree&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;fsTraverse&lt;/span&gt; &lt;span class='varid'&gt;root&lt;/span&gt; &lt;span class='varid'&gt;path&lt;/span&gt;
    &lt;span class='varid'&gt;putStrLn&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;showTree&lt;/span&gt; &lt;span class='varid'&gt;tree&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
  &lt;span class='keyword'&gt;where&lt;/span&gt;
    &lt;span class='varid'&gt;root&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;if&lt;/span&gt; &lt;span class='str'&gt;"/"&lt;/span&gt; &lt;span class='varop'&gt;`isPrefixOf`&lt;/span&gt; &lt;span class='varid'&gt;path&lt;/span&gt; &lt;span class='keyword'&gt;then&lt;/span&gt; &lt;span class='str'&gt;""&lt;/span&gt; &lt;span class='keyword'&gt;else&lt;/span&gt; &lt;span class='str'&gt;"."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;That&amp;#8217;s the plan.  Now let&amp;#8217;s carry it out.&lt;/p&gt;&lt;h3&gt; Step 1:  Introduce the intermediate tree data structure&lt;/h3&gt;


	&lt;p&gt;To make our desired separation possible, let&amp;#8217;s introduce the tree data
structure.  Conveniently enough, the &lt;code&gt;Data.Tree&lt;/code&gt; library
provides the structure for us:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='keyword'&gt;data&lt;/span&gt; &lt;span class='conid'&gt;Tree&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;Node&lt;/span&gt; &lt;span class='layout'&gt;{&lt;/span&gt;&lt;span class='varid'&gt;rootLabel&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;subForest&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;Forest&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt;&lt;span class='layout'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Let&amp;#8217;s also define some descriptive type synonyms to help us think about
our data:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='keyword'&gt;type&lt;/span&gt; &lt;span class='conid'&gt;Path&lt;/span&gt;       &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;String&lt;/span&gt;           &lt;span class='comment'&gt;-- path&lt;/span&gt;
&lt;span class='keyword'&gt;type&lt;/span&gt; &lt;span class='conid'&gt;DentName&lt;/span&gt;   &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;String&lt;/span&gt;           &lt;span class='comment'&gt;-- directory-entry name&lt;/span&gt;
&lt;span class='keyword'&gt;type&lt;/span&gt; &lt;span class='conid'&gt;DirNode&lt;/span&gt;    &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;Path&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='conid'&gt;DentName&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='comment'&gt;-- directory-path/dentname pair&lt;/span&gt;
&lt;span class='keyword'&gt;type&lt;/span&gt; &lt;span class='conid'&gt;DirTree&lt;/span&gt;    &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;Tree&lt;/span&gt; &lt;span class='conid'&gt;DentName&lt;/span&gt;    &lt;span class='comment'&gt;-- file-system tree&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;(Unlike last time, in this article I&amp;#8217;ll place type annotations
on all top-level declarations to help you see how the data
flows between the pieces of our code.)&lt;/p&gt;


	&lt;p&gt;To give you an idea of what the tree structure looks like,
here&amp;#8217;s an example &lt;em&gt;DirTree&lt;/em&gt; value:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;exampleTree&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;DirTree&lt;/span&gt;
&lt;span class='varid'&gt;exampleTree&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;Node&lt;/span&gt; &lt;span class='str'&gt;"root"&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;
                &lt;span class='conid'&gt;Node&lt;/span&gt; &lt;span class='str'&gt;"subdir1"&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;
                  &lt;span class='conid'&gt;Node&lt;/span&gt; &lt;span class='str'&gt;"file1.1"&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
                &lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='conid'&gt;Node&lt;/span&gt; &lt;span class='str'&gt;"file1.2"&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
                &lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='conid'&gt;Node&lt;/span&gt; &lt;span class='str'&gt;"subdir1.3"&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;
                    &lt;span class='conid'&gt;Node&lt;/span&gt; &lt;span class='str'&gt;"file1.3.1"&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt; &lt;span class='keyglyph'&gt;]&lt;/span&gt; &lt;span class='keyglyph'&gt;]&lt;/span&gt;
              &lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='conid'&gt;Node&lt;/span&gt; &lt;span class='str'&gt;"file1"&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt; &lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Now let&amp;#8217;s revise our old code to show a tree in this structure.&lt;/p&gt;


	&lt;h3&gt; Step 2:  Write the tree-showing code&lt;/h3&gt;


	&lt;p&gt;This step is easy.  We just copy and paste our old code, remove the
I/O related bits, and tweak for clarity:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='comment'&gt;-- Purely functional tree-to-string formatting&lt;/span&gt;

&lt;span class='varid'&gt;showTree&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;Tree&lt;/span&gt; &lt;span class='conid'&gt;String&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;String&lt;/span&gt;
&lt;span class='varid'&gt;showTree&lt;/span&gt; &lt;span class='varid'&gt;t&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;unlines&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;showNode&lt;/span&gt; &lt;span class='str'&gt;""&lt;/span&gt; &lt;span class='str'&gt;""&lt;/span&gt; &lt;span class='str'&gt;""&lt;/span&gt; &lt;span class='varid'&gt;t&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;

&lt;span class='varid'&gt;showNode&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;String&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;String&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;String&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;Tree&lt;/span&gt; &lt;span class='conid'&gt;String&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='conid'&gt;String&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;span class='varid'&gt;showNode&lt;/span&gt; &lt;span class='varid'&gt;leader&lt;/span&gt; &lt;span class='varid'&gt;tie&lt;/span&gt; &lt;span class='varid'&gt;arm&lt;/span&gt; &lt;span class='varid'&gt;node&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='varid'&gt;nodeRep&lt;/span&gt; &lt;span class='conop'&gt;:&lt;/span&gt; &lt;span class='varid'&gt;showChildren&lt;/span&gt; &lt;span class='varid'&gt;node&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;leader&lt;/span&gt; &lt;span class='varop'&gt;++&lt;/span&gt; &lt;span class='varid'&gt;extension&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
  &lt;span class='keyword'&gt;where&lt;/span&gt;
    &lt;span class='varid'&gt;nodeRep&lt;/span&gt;   &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;leader&lt;/span&gt; &lt;span class='varop'&gt;++&lt;/span&gt; &lt;span class='varid'&gt;arm&lt;/span&gt; &lt;span class='varop'&gt;++&lt;/span&gt; &lt;span class='varid'&gt;tie&lt;/span&gt; &lt;span class='varop'&gt;++&lt;/span&gt; &lt;span class='varid'&gt;rootLabel&lt;/span&gt; &lt;span class='varid'&gt;node&lt;/span&gt;
    &lt;span class='varid'&gt;extension&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;case&lt;/span&gt; &lt;span class='varid'&gt;arm&lt;/span&gt; &lt;span class='keyword'&gt;of&lt;/span&gt; &lt;span class='str'&gt;""&lt;/span&gt;  &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='str'&gt;""&lt;/span&gt;&lt;span class='layout'&gt;;&lt;/span&gt; &lt;span class='str'&gt;"`"&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='str'&gt;"    "&lt;/span&gt;&lt;span class='layout'&gt;;&lt;/span&gt; &lt;span class='keyword'&gt;_&lt;/span&gt;   &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='str'&gt;"|   "&lt;/span&gt;

&lt;span class='varid'&gt;showChildren&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;Tree&lt;/span&gt; &lt;span class='conid'&gt;String&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;String&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='conid'&gt;String&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;span class='varid'&gt;showChildren&lt;/span&gt; &lt;span class='varid'&gt;node&lt;/span&gt; &lt;span class='varid'&gt;leader&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt;
    &lt;span class='keyword'&gt;let&lt;/span&gt; &lt;span class='varid'&gt;children&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;subForest&lt;/span&gt; &lt;span class='varid'&gt;node&lt;/span&gt;
        &lt;span class='varid'&gt;arms&lt;/span&gt;     &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;replicate&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;length&lt;/span&gt; &lt;span class='varid'&gt;children&lt;/span&gt; &lt;span class='comment'&gt;-&lt;/span&gt; &lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='str'&gt;"|"&lt;/span&gt; &lt;span class='varop'&gt;++&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='str'&gt;"`"&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
    &lt;span class='keyword'&gt;in&lt;/span&gt;  &lt;span class='varid'&gt;concat&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;zipWith&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;showNode&lt;/span&gt; &lt;span class='varid'&gt;leader&lt;/span&gt; &lt;span class='str'&gt;"-- "&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varid'&gt;arms&lt;/span&gt; &lt;span class='varid'&gt;children&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;There are two main differences between this code and the old code.
First, instead of processing directory nodes in the file system, we
are processing tree nodes of the &lt;em&gt;Tree&lt;/em&gt; data type.  Second, because
the code is pure, that is, free of side effects, its result is a
&lt;em&gt;String&lt;/em&gt;, not an &lt;em&gt;IO&lt;/em&gt; action.&lt;/p&gt;


	&lt;p&gt;Lets take this code for a spin in GHCi.  We&amp;#8217;ll ask it to show
our example tree from earlier in the article.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;Ok, modules loaded: Main.
*Main&amp;gt; putStr (showTree exampleTree)
root
|-- subdir1
|   |-- file1.1
|   |-- file1.2
|   `-- subdir1.3
|       `-- file1.3.1
`-- file1
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Great.  Let&amp;#8217;s move on.&lt;/p&gt;


	&lt;h3&gt; Step 3:  Write the directory-traversal code&lt;/h3&gt;


	&lt;p&gt;In this step, we want to write the code that recursively scans
(traverses) a directory hierarchy and returns a &lt;em&gt;DirTree&lt;/em&gt; that
represents the hierarchy.  The following code, which does just
that, is a straightforward extraction of our old code&amp;#8217;s
&lt;em&gt;visit&lt;/em&gt; and &lt;em&gt;visitChildren&lt;/em&gt; functions:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='comment'&gt;-- Effectful directory-traversal code that returns a tree&lt;/span&gt;
&lt;span class='comment'&gt;-- representing the directory hierarchy rooted at 'path/node'.&lt;/span&gt;

&lt;span class='varid'&gt;fsTraverse&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;Path&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;DentName&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;IO&lt;/span&gt; &lt;span class='conid'&gt;DirTree&lt;/span&gt;
&lt;span class='varid'&gt;fsTraverse&lt;/span&gt; &lt;span class='varid'&gt;path&lt;/span&gt; &lt;span class='varid'&gt;node&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt;
    &lt;span class='conid'&gt;Node&lt;/span&gt; &lt;span class='varid'&gt;node&lt;/span&gt; &lt;span class='varop'&gt;`liftM`&lt;/span&gt; &lt;span class='varid'&gt;fsTraverseChildren&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;path&lt;/span&gt; &lt;span class='varop'&gt;++&lt;/span&gt; &lt;span class='str'&gt;"/"&lt;/span&gt; &lt;span class='varop'&gt;++&lt;/span&gt; &lt;span class='varid'&gt;node&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;

&lt;span class='varid'&gt;fsTraverseChildren&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;Path&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;IO&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;Forest&lt;/span&gt; &lt;span class='conid'&gt;DentName&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;span class='varid'&gt;fsTraverseChildren&lt;/span&gt; &lt;span class='varid'&gt;path&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt;
    &lt;span class='varid'&gt;mapM&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;uncurry&lt;/span&gt; &lt;span class='varid'&gt;fsTraverse&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varop'&gt;=&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class='varid'&gt;fsGetChildren&lt;/span&gt; &lt;span class='varid'&gt;path&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;The &lt;em&gt;fsTraverse&lt;/em&gt; function takes advantage of &lt;em&gt;liftM&lt;/em&gt; to &amp;#8220;lift&amp;#8221; the
pure function (&lt;em&gt;Node node&lt;/em&gt;) into the &lt;em&gt;IO&lt;/em&gt; monad, where it
is applied to the result of the effectful &lt;em&gt;fsTraverseChildren&lt;/em&gt;
function.  It is shorter and more communicative of
our intent than the following equivalent code:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='keyword'&gt;do&lt;/span&gt; &lt;span class='varid'&gt;childForest&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;fsTraverseChildren&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;path&lt;/span&gt; &lt;span class='varop'&gt;++&lt;/span&gt; &lt;span class='str'&gt;"/"&lt;/span&gt; &lt;span class='varop'&gt;++&lt;/span&gt; &lt;span class='varid'&gt;node&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
   &lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;Node&lt;/span&gt; &lt;span class='varid'&gt;node&lt;/span&gt; &lt;span class='varid'&gt;childForest&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;While extracting these functions from our original code, I took the
liberty of factoring out the code that grabs the contents of a
directory.  This code now lives in its own helper function:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='comment'&gt;-- helper to get traversable directory entries&lt;/span&gt;

&lt;span class='varid'&gt;fsGetChildren&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;Path&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;IO&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='conid'&gt;DirNode&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;span class='varid'&gt;fsGetChildren&lt;/span&gt; &lt;span class='varid'&gt;path&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
    &lt;span class='varid'&gt;contents&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;getDirectoryContents&lt;/span&gt; &lt;span class='varid'&gt;path&lt;/span&gt; &lt;span class='varop'&gt;`catch`&lt;/span&gt; &lt;span class='varid'&gt;const&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
    &lt;span class='keyword'&gt;let&lt;/span&gt; &lt;span class='varid'&gt;visibles&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;sort&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;filter&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varop'&gt;`notElem`&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='str'&gt;"."&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='str'&gt;".."&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varop'&gt;$&lt;/span&gt; &lt;span class='varid'&gt;contents&lt;/span&gt;
    &lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;map&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varid'&gt;path&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varid'&gt;visibles&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;This bit of code differs from the code in the previous article in that
it treats any error encountered when scanning a directory as if the
directory were empty.  That&amp;#8217;s what the&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varop'&gt;...&lt;/span&gt; &lt;span class='varop'&gt;`catch`&lt;/span&gt; &lt;span class='varid'&gt;const&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;addendum does.  It says that any error caught while scanning the
directory will be handled by a constant policy, that of returning an
empty list.&lt;/p&gt;


	&lt;p&gt;This policy tends to be what we want in practice because the two most
common errors we expect to encounter here will be &amp;#8220;oops, that&amp;#8217;s a
file, so it can&amp;#8217;t have children&amp;#8221; and &amp;#8220;oops, you&amp;#8217;re not allowed to scan
that directory.&amp;#8221;  This error-handling policy will, however, throw away
potentially useful information, say, in the rare case that the error
is something like &amp;#8220;oops, your hard drive caught on fire and is about
to explode: start running now.&amp;#8221;  (Maybe we&amp;#8217;ll revisit our policy
later.)&lt;/p&gt;


	&lt;h3&gt; Step 4: Connect the traversal code to the printing code&lt;/h3&gt;


	&lt;p&gt;We can traverse file-system hierarchies to produce trees.  We can
print trees.  To traverse &lt;em&gt;and&lt;/em&gt; print a hierarchy, then, requires
nothing but a little glue.  Conveniently, we have already written
the needed glue, &lt;em&gt;traverseAndPrint&lt;/em&gt;, when we formulated our plan.
Here is a slightly more concise version:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;traverseAndPrint&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;Path&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;IO&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;span class='varid'&gt;traverseAndPrint&lt;/span&gt; &lt;span class='varid'&gt;path&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt;
    &lt;span class='varid'&gt;putStr&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;showTree&lt;/span&gt; &lt;span class='varop'&gt;=&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class='varid'&gt;fsTraverse&lt;/span&gt; &lt;span class='varid'&gt;root&lt;/span&gt; &lt;span class='varid'&gt;path&lt;/span&gt;
  &lt;span class='keyword'&gt;where&lt;/span&gt;
    &lt;span class='varid'&gt;root&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;if&lt;/span&gt; &lt;span class='str'&gt;"/"&lt;/span&gt; &lt;span class='varop'&gt;`isPrefixOf`&lt;/span&gt; &lt;span class='varid'&gt;path&lt;/span&gt; &lt;span class='keywor