2

Is there no standard way to print out values for end-user consumption? Show is clearly more of a debugging convenience than something that would work for this purpose, given the conventions around its use and the constraint that read (show x) == x.

For example, isn't there at least a simple package like

class (Show a) => PShow a where 
    pshow :: a -> String
    pshow = show

pprint :: (PShow a) => a -> IO () 
pprint = putStrLn . pshow

where instances do something like

instance PShow MyType where
    pshow a = someUserFriendlyStringOf a

Note that I'm not asking for something that provides elaborate pretty printing and formatting functionality (I see several packages that do that) just for a simple abstraction that's widely used that allows for pretty printing. Is there something like this?

orome
  • 45,163
  • 57
  • 202
  • 418

2 Answers2

2

Note that I'm not asking for something that provides elaborate pretty printing and formatting functionality (I see several packages that do that)

There's a reason for that. The people who wrote those elaborate libraries did so because they couldn't get the job done with something simple. You've already hinted at some of the complexity by offering two different methods that may our may not do the same thing, with no guidance about which to use when.

On the positive side, I wouldn't worry too much about read. Focus on Show instances that (possibly with GHC extensions) can give you code to cut and paste into your programs.

dfeuer
  • 48,079
  • 5
  • 63
  • 167
  • There's no "job" to do here though other than to allow for common usage of something like `pprint` resulting in the pretty equivalent of `print` (due to type-defined implementations of `pshow`) in parallel with `print`/`show`. What's missing from accomplishing that? (I've cut the bit that I think confused the issue). My point is: it seems like *a lot* of types that produce meaningful end-user display need to implant `pprint`, so why not abstract that simple fact. – orome Sep 11 '15 at 22:38
  • Note that I never said those libraries were elaborate but that *this* "library" was not intended to provide elaborate functionality. It's just glue. – orome Sep 11 '15 at 22:40
  • *"implant" = "implement" (that 5 min rule is silly). – orome Sep 11 '15 at 22:44
  • @raxacoricofallapatorius Many pretty-printing libraries *do* abstract that. [example](http://hackage.haskell.org/package/pretty-1.1.3.2/docs/Text-PrettyPrint-HughesPJClass.html) – Daniel Wagner Sep 12 '15 at 00:23
  • @DanielWagner: Yes, that's part of my point. If there are many different places that the same thing is happening, shouldn't there be one where its shared properties are defined (here, merely the existence of `pprint`, its signature and default behavior) so that all the others, or a user defined alternative, can instantiate? – orome Sep 12 '15 at 00:29
  • @raxacoricofallapatorius It's hard to imagine a more appropriate place for that than in the library that defines the pretty-printing combinators. Outside of that library you don't even have the _types_ needed to specify the class. – Daniel Wagner Sep 12 '15 at 01:01
  • @DanielWagner: Only if there were just one such library and only if those types were in fact always needed to accomplish pretty printing. I think people are confusing rich, class specific presentation, with rich generic formatting functionality. The latter can be used to accomplish the former, but there are (demonstrably) many ways to do that; and the former can be (often simply) accomplished without the latter. – orome Sep 12 '15 at 01:10
  • 1
    @raxacoricofallapatorius, may I suggest you write the library you want, since (you claim that) it's simple, demonstrate its utility with some realistic examples, and make it available on Hackage? This is, ultimately, how all libraries start out. – dfeuer Sep 12 '15 at 02:28
  • @raxacoricofallapatorius A conjecture: when it comes to polished pretty printing for end-users, everyone will want to print things in different ways, due to aesthetic preferences and other arbitrary constraints, and so there is little incentive to generalise... unless the implementation is sophisticated and configurable enough to cater to the needs of most of its potential users. That might explain the lack of *simple* pretty printing libraries that you noticed. – duplode Sep 12 '15 at 02:52
  • @duplode: That's exactly right. And I see now what has confused people (but not why, I think the question is clear enough): That's my point exactly. Everyone will want and need something very different so everyone will need to write (and do write) their own `someUserFriendlyStringOf` (and not necessarily or even commonly using any particular tools or libraries) — *but*, abstractly, those functions all do the same thing, they `pshow` (or "render" of whatever), so an abstraction that conveys that seems in order. And that *is* simple. – orome Sep 12 '15 at 12:09
  • @dfeuer: See previous comment. The code above *is* the library. All I was asking really is (sorry for the confusion) does it already exist? – orome Sep 12 '15 at 12:11
  • A corollary question (for me at least, since it is part of what motived this one) is whether just writing a bunch of functions `MyType -> String` with names like `showMyTypeDetails` or `showEnlighteningViewOnMyType` is idiomatic Haskell practice. I think this question was misunderstood (I hope I've cleared that up) but I may be trying to fit a square peg into a round hole. – orome Sep 12 '15 at 22:37
  • @raxacoricofallapatorius If your `PShow` abstracts this much, the only things in common between different `pshow` implementations will be the name and the type signature. At that point, having a general-purpose type class is not worth the trouble. In general, instances of a Haskell class are expected to be usable everywhere ([this question](http://stackoverflow.com/q/8728596)) discusses the issue in another context) and to have some properties in common that you can rely on (those properties are often expressed as the *laws* of a type class). – duplode Sep 13 '15 at 01:03
  • @duplode: Yes, I think that's really the answer to the question I was asking (which, is in a sense the opposite of the question that was answered): given the idiosyncrasies and variety of demands that would be placed on PShow, that level of abstraction is taking things too far, almost to the point that it would be without meaning (in contrast to Show, which I naively thought of as a parallel), especially since it is (I gather) perfectly idiomatic Haskell to have a collection of `showAViewOfMyArg` functions, as needed. – orome Sep 13 '15 at 01:32
  • @raxacoricofallapatorius That's pretty much it. I will only emphasise a bit more the "general-purpose" qualification in my comment above. It is fine to have an internal `MyPShow` class, with instances tuned to the specific purposes of your application, but you wouldn't want to include it in a public API (unless you are writing something like a [Jupyter kernel](https://github.com/gibiansky/IHaskell/blob/master/src/IHaskell/Types.hs#L63), in which being able to display things according to the arbitrary constraints of an external tool is part of the point). – duplode Sep 13 '15 at 01:51
  • @duplode: Yes. I don't even think I'd bother with `MyPShow`, just several `showPretty...` or `showInformative...` that were `OneOfMyTypes -> String`. (In some cases in fact — perhaps many practical ones — what is most useful to show to users is not even a value of a Type, but, say, the progress of a computation, or several of them collected or sequenced. So I'd need to define a type for that and have it instantiate `MyPShow` for the sole purpose of avoiding giving the function that displays it a different name than the one I use to display something else.) – orome Sep 13 '15 at 12:02
2

I just did a Hoogle search for a -> String and found the Language.Haskell.Pretty module.

The module defines three simple functions:

prettyPrintStyleMode :: Pretty a => Style -> PPHsMode -> a -> String
pretty-print with a given style and mode.

prettyPrintWithMode :: Pretty a => PPHsMode -> a -> String
pretty-print with the default style and a given mode.

prettyPrint :: Pretty a => a -> String
pretty-print with the default style and defaultMode.

The whole typeclass seems to be a bit more complex than what you have asked for, but maybe it helps

Michael
  • 6,451
  • 5
  • 31
  • 53
  • Yes, that's one of the packages I'm referring to. These al demonstrate my point: there are many approaches to the same thing. My emphasis was on *"same thing"*: that there is (as this demonstrates) an abstraction that sits above all these packages, as well as the many (I expect quite common) type-specific cases where `someUserFriendlyStringOf ` needs to be written from scratch. My question was whether that abstraction was already part of the language, or had been implemented in a lightweight package. – orome Sep 12 '15 at 20:33
  • Put another way, all these packages contain a class (here `Pretty`) that is an instance of `Show`, and even taken together, these packages are probably mostly unsuited for custom rendering of arbitrary (rich, structured) values. – orome Sep 12 '15 at 20:33