Thank you for your interesting reply. I found it enlightening. Compared to that, I'm missing the specification part for your pretty > printer. How's it supposed to lay out?
The specification is in Paulson's book. 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. I played around with the Hughes pretty printer, but it wasn't obvious how to get the output I knew I could from the Paulson pretty printer. I confess I did not spend much time tinkering with the Hughes pretty printer. 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. 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. It also explains why I did not use the sum function in the Prelude, or your map trick when writing the blo function. > What style do to you prefer, a knot-tying or a monad-based style? I > have enclosed the pretty printer. The printing function is the > subject of the controversy. ... a simple difference list ... will do. Hmm. Doesn't the output type (Int, String) -> (Int, String) show the implementation is using the essence of a difference list? Remember, the resulting function prepends something the string it is given in the second element of the pair, and returns that string. Introducing a difference list means to replace the output type > > (Int, String) -> (Int, String) > > of printing by > > Int -> (Int, String -> String) -- difference list > My first attempt at writing the printing function had a type similar to this one. I found myself composing difference lists of type ShowS. The performance was noticabily slow, specially as compared with the implementation displayed in my message. Perhaps the use of Data.DList would repair this performance problem. I don't mean to suggest that ShowS style difference lists cannot be used to make the function easier to understand--all I'm saying is my attempt to do so did not work out well. >> module Pretty(Pretty, pr, blo, str, brk) where > >> data Pretty >> = Str !String >> | Brk !Int -- Int is the number of breakable spaces >> | Blo ![Pretty] !Int !Int -- First int is the indent, second int >> -- is the number of chars and spaces for strings and breaks in block Drop those strictness annotations from !String and ![Pretty], they won't > do any good. The !Int are only useful if they will be unboxed, but I > wouldn't bother right now. I thought that the annotations ensure the first element of the list is evaluated. The Char and Pretty lists are generated with seqrev, so everything gets evaluated before constructor is applied to data. -- A reverse that evaluates the list elements. seqrev :: [a] -> [a] seqrev = foldl (\xs x -> x `seq` xs `seq` (x:xs)) [] The trouble is the constructors are not exported directly, but instead through str, brk, and blo, functions which are not strict. It's the best I could do, as near as I can tell. It seems rather hard to avoid lazyness in the current version of Haskell when it's not wanted. I hope one of the proposals for deep strictness makes it into Haskell prime. 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. I wish I could tell compilers to make it so. John
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe