How to pretty print code efficiently

Hi, Currently I'm pretty printing code by building arrays of strings and calling indent. For example: instance JavaPrintableNamed AST.EnumeratedType where javaLinesNamed parentName (AST.EnumeratedType memberDefinitions) = [ "public enum " ++ asJavaId(parentName) , "{" ] ++ memberCodeLines ++ [ "}" , "" ] where memberCodeLines = indent $ javaLines memberDefinitions The indent function takes a list of strings and adds an indent to the beginning of every line. I can imagine this to be very inefficient as it builds many strings and concatenates them. In Ruby, I might do the same thing like this: class EnumeratedType < JavaPrintableNamed def writeTo(writer) writer.print "public enum " writer.puts self.asJavaId writer.puts "{" writer.indent do self.memberDefinitions.writeTo(writer) writer.puts end where above, the writer.indent takes care of the indent, and everything is appended to a stream, which doesn't seem so bad in terms of efficiency. I'm looking for a way to do something similar in Haskell. Anyone can give me a hand? Thanks -John

John Ky
Hi,
Currently I'm pretty printing code by building arrays of strings and calling indent. For example:
instance JavaPrintableNamed AST.EnumeratedType where javaLinesNamed parentName (AST.EnumeratedType memberDefinitions) = [ "public enum " ++ asJavaId(parentName) , "{" ] ++ memberCodeLines ++ [ "}" , "" ] where memberCodeLines = indent $ javaLines memberDefinitions
The indent function takes a list of strings and adds an indent to the beginning of every line.
I can imagine this to be very inefficient as it builds many strings and concatenates them.
Yes and no. When concatenating two lists, only the first one is rebuild, the second one is reused, due to sharing. So if you concatenate short strings to the front of a long string you're quite fine. But then, that isn't the answer you hoped for.
In Ruby, I might do the same thing like this:
class EnumeratedType < JavaPrintableNamed def writeTo(writer) writer.print "public enum " writer.puts self.asJavaId writer.puts "{" writer.indent do self.memberDefinitions.writeTo(writer) writer.puts end
where above, the writer.indent takes care of the indent, and everything is appended to a stream, which doesn't seem so bad in terms of efficiency.
I'm looking for a way to do something similar in Haskell.
Anyone can give me a hand?
As data structure use Data.ByteString.Lazy: concatenating two lazy bytestrings doesn't involve rebuilding the first string byte-by-byte, but constructs a superstructure denoting the concatenation. As for how to express it in code: I'd recommend a combination of a State monad to track the indentation, and the underused[1] Applicative interpretation of lists to concatenate stuff. >>= would function as concatenation of lines, getting the state, while the indent function would first set it to the new level, then execute the passed sub-action, and finally reset it to the old level. You're going to need a way to concatenate two strings without doing a line-break, too, of course. All in all, it's a splendid exercise in how to write custom monads. [1] Lists as ordered collections, not possibilities, that is, see e.g. the typeclassopedia ( http://www.haskell.org/sitewiki/images/8/85/TMR-Issue13.pdf ) -- (c) this sig last receiving data processing entity. Inspect headers for copyright history. All rights reserved. Copying, hiring, renting, performance and/or quoting of this signature prohibited.

Achim Schneider
As for how to express it in code: I'd recommend a combination of a State monad to track the indentation, and the underused[1] Applicative interpretation of lists to concatenate stuff. >>= would function as concatenation of lines, getting the state, while the indent function would first set it to the new level, then execute the passed sub-action, and finally reset it to the old level. You're going to need a way to concatenate two strings without doing a line-break, too, of course.
Make that "Reader Monad" and "execute the passed sub-action with the new level inside a new monad" -- (c) this sig last receiving data processing entity. Inspect headers for copyright history. All rights reserved. Copying, hiring, renting, performance and/or quoting of this signature prohibited.

On Fri, Jul 3, 2009 at 6:45 PM, John Ky
Hi,
Currently I'm pretty printing code by building arrays of strings and calling indent. For example:
instance JavaPrintableNamed AST.EnumeratedType where javaLinesNamed parentName (AST.EnumeratedType memberDefinitions) = [ "public enum " ++ asJavaId(parentName) , "{" ] ++ memberCodeLines ++ [ "}" , "" ] where memberCodeLines = indent $ javaLines memberDefinitions
The indent function takes a list of strings and adds an indent to the beginning of every line.
I can imagine this to be very inefficient as it builds many strings and concatenates them.
In Ruby, I might do the same thing like this:
class EnumeratedType < JavaPrintableNamed def writeTo(writer) writer.print "public enum " writer.puts self.asJavaId writer.puts "{" writer.indent do self.memberDefinitions.writeTo(writer) writer.puts end
where above, the writer.indent takes care of the indent, and everything is appended to a stream, which doesn't seem so bad in terms of efficiency.
I'm looking for a way to do something similar in Haskell.
Anyone can give me a hand?
Thanks
-John
_______________________________________________
You may want to investigate the standard module Text.PrettyPrint.HughesPJ, which contains a number of (I assume fairly efficient) combinators for pretty printing. Alex

On 4 jul 2009, at 05:13, Alexander Dunlap wrote:
On Fri, Jul 3, 2009 at 6:45 PM, John Ky
wrote: Hi,
Currently I'm pretty printing code by building arrays of strings and calling indent. For example:
instance JavaPrintableNamed AST.EnumeratedType where javaLinesNamed parentName (AST.EnumeratedType memberDefinitions) = [ "public enum " ++ asJavaId(parentName) , "{" ] ++ memberCodeLines ++ [ "}" , "" ] where memberCodeLines = indent $ javaLines memberDefinitions
The indent function takes a list of strings and adds an indent to the beginning of every line.
I can imagine this to be very inefficient as it builds many strings and concatenates them.
In Ruby, I might do the same thing like this:
class EnumeratedType < JavaPrintableNamed def writeTo(writer) writer.print "public enum " writer.puts self.asJavaId writer.puts "{" writer.indent do self.memberDefinitions.writeTo(writer) writer.puts end
where above, the writer.indent takes care of the indent, and everything is appended to a stream, which doesn't seem so bad in terms of efficiency.
I'm looking for a way to do something similar in Haskell.
Anyone can give me a hand?
Thanks
-John
_______________________________________________
You may want to investigate the standard module Text.PrettyPrint.HughesPJ, which contains a number of (I assume fairly efficient) combinators for pretty printing.
I second that. Also, there is uulib which has a pretty printing module that's quite similar: http://hackage.haskell.org/packages/archive/uulib/0.9.10/doc/html/UU-PPrint.... I think both packages are based on the paper "The Design of a Pretty- printing Library" which can be found at http://www.cs.chalmers.se/~rjmh/Papers/pretty.ps Not only do they provide abstractions for things like indentation, concatenation in different forms, etc., but they also are more efficient than a naive implementation using lists. -chris -chris

Hi all,
Thanks everyone for the help. The HughesPJ module works well for me.
Cheers,
-John
On Mon, Jul 6, 2009 at 3:49 AM, Chris Eidhof
On 4 jul 2009, at 05:13, Alexander Dunlap wrote:
On Fri, Jul 3, 2009 at 6:45 PM, John Ky
wrote: Hi,
Currently I'm pretty printing code by building arrays of strings and calling indent. For example:
instance JavaPrintableNamed AST.EnumeratedType where javaLinesNamed parentName (AST.EnumeratedType memberDefinitions) = [ "public enum " ++ asJavaId(parentName) , "{" ] ++ memberCodeLines ++ [ "}" , "" ] where memberCodeLines = indent $ javaLines memberDefinitions
The indent function takes a list of strings and adds an indent to the beginning of every line.
I can imagine this to be very inefficient as it builds many strings and concatenates them.
In Ruby, I might do the same thing like this:
class EnumeratedType < JavaPrintableNamed def writeTo(writer) writer.print "public enum " writer.puts self.asJavaId writer.puts "{" writer.indent do self.memberDefinitions.writeTo(writer) writer.puts end
where above, the writer.indent takes care of the indent, and everything is appended to a stream, which doesn't seem so bad in terms of efficiency.
I'm looking for a way to do something similar in Haskell.
Anyone can give me a hand?
Thanks
-John
_______________________________________________
You may want to investigate the standard module Text.PrettyPrint.HughesPJ, which contains a number of (I assume fairly efficient) combinators for pretty printing.
I second that. Also, there is uulib which has a pretty printing module that's quite similar:
http://hackage.haskell.org/packages/archive/uulib/0.9.10/doc/html/UU-PPrint....
I think both packages are based on the paper "The Design of a Pretty-printing Library" which can be found at http://www.cs.chalmers.se/~rjmh/Papers/pretty.pshttp://www.cs.chalmers.se/%7Erjmh/Papers/pretty.ps
Not only do they provide abstractions for things like indentation, concatenation in different forms, etc., but they also are more efficient than a naive implementation using lists.
-chris
-chris
participants (4)
-
Achim Schneider
-
Alexander Dunlap
-
Chris Eidhof
-
John Ky