Pretty-printer for Text

I'm currently working on a pretty-printer for lazy text [1] values, basing the API on the wl-pprint [2] package. [1]: http://hackage.haskell.org/package/text [2]: http://hackage.haskell.org/package/wl-pprint In terms of API decisions, there are a few things I'm not sure of and am wondering what other people would prefer: * Should the SimpleDoc type still be exported? Or should the rendering functions just return a Builder or lazy Text value? * Is the Pretty class wanted/needed? If so, should the individual combinators (int, bool, etc.) be kept or just use "pretty" for everything? * Should String values be catered for or just have everything be Text-based? -- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com IvanMiljenovic.wordpress.com

Hi Ivan You're free to do what you want in your own package, but... Having a Pretty class plus primitive printers int, bool is an advantage. For ints, bools, ... code tends to look neater if you use int or bool rather than pretty. Plus for ints and others you tend to need things like hex printers anyway, so one size via a type class doesn't fit all. As for the class - if I have a reasonably sized syntax tree I'd rather just do
pretty a
... than formulate a naming scheme like:
prettyExpr a
Regards Stephen

On 27 October 2010 18:39, Stephen Tetley
Having a Pretty class plus primitive printers int, bool is an advantage. For ints, bools, ... code tends to look neater if you use int or bool rather than pretty. Plus for ints and others you tend to need things like hex printers anyway, so one size via a type class doesn't fit all.
Definitely agreed.
As for the class - if I have a reasonably sized syntax tree I'd rather just do
pretty a
... than formulate a naming scheme like:
prettyExpr a
What do you mean by "prettyExpr"? My main objection to having a Pretty type class is that when having a "reasonably sized syntax tree", aren't you likely to want to have your own custom printing variants rather than the ones in the pre-defined class? As such, does having a default class make sense if it isn't used? That said, 9 packages [1] do use prettyclass [2]... out of the 168 packages [3] that use pretty itself [4] (some of which implement their own Pretty class). [1]: http://bifunctor.homelinux.net/~roel/cgi-bin/hackage-scripts/revdeps/prettyc... [2]: http://hackage.haskell.org/package/prettyclass [3]: http://bifunctor.homelinux.net/~roel/cgi-bin/hackage-scripts/revdeps/pretty-... [4]: http://hackage.haskell.org/package/pretty -- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com IvanMiljenovic.wordpress.com

On 27 October 2010 08:57, Ivan Lazar Miljenovic
What do you mean by "prettyExpr"?
Without a type class I generally name pretty printers by the pretty 'pretty' then the type they print Expr (expression), Decl (declaration) etc.
My main objection to having a Pretty type class is that when having a "reasonably sized syntax tree", aren't you likely to want to have your own custom printing variants rather than the ones in the pre-defined class? As such, does having a default class make sense if it isn't used?
That said, 9 packages [1] do use prettyclass [2]... out of the 168 packages [3] that use pretty itself [4] (some of which implement their own Pretty class).
For a syntax tree I'd want a class, then I can use pretty at any level. This is helpful in defining the instances as most of the work is delegated to pretty rather than prettyExp, prettyDecl etc. so it keeps the code neat. It is also useful in GHCi where I can just call pretty on something. I can't think that I've ever wanted two different flavours of output for a syntax tree. If I was wanted 'round trip printing' (from parsing to pretty to parsing) I'd have to take a lot of care over white space and layout so I would be needing something more powerful than a pretty printer. As for the prettyclass in HughesPJ, if people found they wanted this I don't know why people didn't switch to wl-pprint. Wl-pprint is nicer in enough ways to make the change sensible.

On 27 October 2010 19:19, Stephen Tetley
On 27 October 2010 08:57, Ivan Lazar Miljenovic
wrote: My main objection to having a Pretty type class is that when having a "reasonably sized syntax tree", aren't you likely to want to have your own custom printing variants rather than the ones in the pre-defined class? As such, does having a default class make sense if it isn't used?
That said, 9 packages [1] do use prettyclass [2]... out of the 168 packages [3] that use pretty itself [4] (some of which implement their own Pretty class).
For a syntax tree I'd want a class, then I can use pretty at any level. This is helpful in defining the instances as most of the work is delegated to pretty rather than prettyExp, prettyDecl etc. so it keeps the code neat. It is also useful in GHCi where I can just call pretty on something.
Why not write your own Pretty class for that project then? Admittedly, some packages might write their own class because they didn't want to use non-ghc/platform libraries or prettyclass didn't exist then. I had to write my own [1] for two reasons: 1) I needed to be able to differentiate between quoted and un-quoted values, and 2) some of the ways values get pretty-printed are different than just "text . show", which is what all the default instances of the Pretty classes are (with the exception of String). It's this second point that I would wonder how many people would use a default Pretty class: just because I want to print String values one way, does that you mean you should print them that way as well? [1]: http://hackage.haskell.org/packages/archive/graphviz/2999.10.0.1/doc/html/Da...
I can't think that I've ever wanted two different flavours of output for a syntax tree. If I was wanted 'round trip printing' (from parsing to pretty to parsing) I'd have to take a lot of care over white space and layout so I would be needing something more powerful than a pretty printer.
Again, it's not a matter of two different types of output; it's a matter of my way of doing output differs from your way of doing output, even for in-built types. Don't forget, instances are imported and exported implicitly. -- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com IvanMiljenovic.wordpress.com

On 27 October 2010 09:32, Ivan Lazar Miljenovic
Why not write your own Pretty class for that project then?
Personally I don't like type classes if they're solely for notational convenience. I want them to be a least a convention and its nicer still when they genuinely represent something like Monad, Monoid, Applicative etc. The Pretty class in wl-pprint is a convention. If I'm using HughesPJ for compatibility I'll do without a type class, defining my own is just notational convenience.
Admittedly, some packages might write their own class because they didn't want to use non-ghc/platform libraries or prettyclass didn't exist then.
I had to write my own [1] for two reasons: 1) I needed to be able to differentiate between quoted and un-quoted values, and 2) some of the ways values get pretty-printed are different than just "text . show", which is what all the default instances of the Pretty classes are (with the exception of String). It's this second point that I would wonder how many people would use a default Pretty class: just because I want to print String values one way, does that you mean you should print them that way as well?
If you were specifically working around issues of quoting, maybe there would have been room for an alternative design where an Identifier datatype had two constructors one for simple strings and one for quoted ones. In a nutshell, wl-pprint seems to have got the interface 'right' for my tastes. I like having both named primitive printers and a Pretty class. If I want printers for ShowS types or for Docs that don't need page formatting I always copy Wl-pprint's interface.

On 27 October 2010 20:13, Stephen Tetley
On 27 October 2010 09:32, Ivan Lazar Miljenovic
wrote: I had to write my own [1] for two reasons: 1) I needed to be able to differentiate between quoted and un-quoted values, and 2) some of the ways values get pretty-printed are different than just "text . show", which is what all the default instances of the Pretty classes are (with the exception of String). It's this second point that I would wonder how many people would use a default Pretty class: just because I want to print String values one way, does that you mean you should print them that way as well?
If you were specifically working around issues of quoting, maybe there would have been room for an alternative design where an Identifier datatype had two constructors one for simple strings and one for quoted ones.
Well, in my case it's because Dot attributes need to have their values in quotes when they contain spaces, etc. As such, you have these situations: * ` DotNode 1 [Label $ StrLabel "foo"] ' is printed as ` 1 [label=foo] ' * ` DotNode 2 [Label $ StrLabel "bar baz"] ' is printed as ` 2 [label="bar baz"] ' Now, I _could_ have just quoted everything, but I tried to make the generated Dot code as "correct" as possible.
In a nutshell, wl-pprint seems to have got the interface 'right' for my tastes. I like having both named primitive printers and a Pretty class. If I want printers for ShowS types or for Docs that don't need page formatting I always copy Wl-pprint's interface.
OK, I'll keep the class in as well. What about my other queries (e.g. to keep SimpleDoc or not)? -- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com IvanMiljenovic.wordpress.com

On 27 October 2010 10:27, Ivan Lazar Miljenovic
What about my other queries (e.g. to keep SimpleDoc or not)?
SimpleDoc is fully exposed so you can write your own outputters after the library has done the hard work of width formatting if you need them. Although I can't remember using SimpleDoc myself, except in a composition of renderPretty and displayIO I'd still be tempted to keep it around. It adds utility but can be largely ignored in normal use, so doesn't make the library significantly more complicated.

On Tue, Oct 26, 2010 at 9:50 PM, Ivan Lazar Miljenovic
I'm currently working on a pretty-printer for lazy text [1] values, basing the API on the wl-pprint [2] package.
[1]: http://hackage.haskell.org/package/text [2]: http://hackage.haskell.org/package/wl-pprint
In terms of API decisions, there are a few things I'm not sure of and am wondering what other people would prefer:
* Should the SimpleDoc type still be exported? Or should the rendering functions just return a Builder or lazy Text value?
I'm not really sure what you're asking here, but I find BS Builders pretty convenient to work with. A recent release of 'text' includes a Builder type.
* Is the Pretty class wanted/needed? If so, should the individual combinators (int, bool, etc.) be kept or just use "pretty" for everything?
I frequently write a 'Pretty' class when writing complex ASTs, but I have never found it to be a hardship. I prefer using well-named combinators for primitive types.
* Should String values be catered for or just have everything be Text-based?
The OverloadedStrings language extension solves the most common case for wanting to have string-based pretty-printer functions. Antoine
participants (3)
-
Antoine Latter
-
Ivan Lazar Miljenovic
-
Stephen Tetley