Thank you for your interesting reply.&nbsp; I found it enlightening.<br><br><div class="gmail_quote"><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Compared to that, I&#39;m missing the specification part for your pretty<br>printer. How&#39;s it supposed to lay out?</blockquote><div class="Ih2E3d"><br>The specification is in Paulson&#39;s book.&nbsp; The pretty printer is used with S-Expressions, and the block layout generates compact, indented output that is good when there is much data to be displayed.&nbsp; I played around with the Hughes pretty printer, but it wasn&#39;t obvious how to get the output I knew I could from the Paulson pretty printer.&nbsp; I confess I did not spend much time tinkering with the Hughes pretty printer.
<br><br>I failed to mention in my original note that the code was written so that the Haskell version lines up with the Standard ML version.&nbsp; The close connection between the Haskell and Standard ML versions is part of the reason I was able to quickly generate the code, and be confident in its correctness.&nbsp; It also explains why I did not use the sum function in the Prelude, or your map trick when writing the blo function.
<br><br>&gt; What style do to you prefer, a knot-tying or a monad-based style? &nbsp;I<br>&gt; have enclosed the pretty printer. &nbsp;The printing function is the<br>&gt; subject of the controversy.<br><br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
... a simple difference list ... will do.</blockquote><div><br>Hmm.&nbsp; Doesn&#39;t the output type (Int, String) -&gt; (Int, String) show the implementation is using the essence of a difference list?&nbsp; Remember, the resulting function prepends something the string it is given in the second element of the pair, and returns that string.
<br><br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">Introducing a difference list means to replace the output type<br><br> &nbsp; (Int, String) -&gt; (Int, String)
<br><br>of &nbsp;printing&nbsp; by<br><br> &nbsp; Int -&gt; (Int, String -&gt; String) &nbsp; -- difference list<br></blockquote><div class="Ih2E3d"><br>My first attempt at writing the printing function had a type similar to this one.&nbsp; I found myself composing difference lists of type ShowS.&nbsp; The performance was noticabily slow, specially as compared with the implementation displayed in my message.&nbsp; Perhaps the use of 
Data.DList would repair this performance problem.<br><br>I don&#39;t mean to suggest that ShowS style difference lists cannot be used to make the function easier to understand--all I&#39;m saying is my attempt to do so did not work out well.
<br><br>&gt;&gt; module Pretty(Pretty, pr, blo, str, brk) where<br>&gt;<br>&gt;&gt; data Pretty<br>&gt;&gt; &nbsp; &nbsp; = Str !String<br>&gt;&gt; &nbsp; &nbsp; | Brk !Int &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;-- Int is the number of breakable spaces<br>&gt;&gt; &nbsp; &nbsp; | Blo ![Pretty] !Int !Int -- First int is the indent, second int
<br>&gt;&gt; &nbsp; &nbsp; -- &nbsp;is the number of chars and spaces for strings and breaks in block<br><br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Drop those strictness annotations from !String and ![Pretty], they won&#39;t<br>do any good. The !Int are only useful if they will be unboxed, but I<br>wouldn&#39;t bother right now.</blockquote><div><br>I thought that the annotations ensure the first element of the list is evaluated.&nbsp; The Char and Pretty lists are generated with seqrev, so everything gets evaluated before constructor is applied to data.
<br><br>-- A reverse that evaluates the list elements.<br>seqrev :: [a] -&gt; [a]<br>seqrev = foldl (\xs x -&gt; x `seq` xs `seq` (x:xs)) []<br><br>The trouble is the constructors are not exported directly, but instead through str, brk, and blo, functions which are not strict.&nbsp; It&#39;s the best I could do, as near as I can tell.
<br>&nbsp;<br></div></div>It seems rather hard to avoid lazyness in the current version of Haskell when it&#39;s not wanted.&nbsp; I hope one of the proposals for deep strictness makes it into Haskell prime.&nbsp; In my application, there is one datastructure, such that if every value tracable from an instance of the datastructure is evaluated, I am quite sure my program will be free from memory leaks due to dragging.&nbsp; I wish I could tell compilers to make it so.
<br><br>John<br>