Text.PrettyPrintprovides combinators for pretty-printing. It's kinda like a super-simplified HTML or TeX: you give it a bunch of boxes and how they relate to one another and it manages output. It's trivial to use.
A common case I have is printing something that's tree-like, where children are indented below their parents. The code for printing a node is straightforward: print this node's content, then map the print function over all its children with a bit more indentation. But the indentation bit is annoying! You have to remember to properly indent every line, and then that complicated wrapping, etc.
Instead, use the pretty-printer. A
Docis basically a box of text.
text "foo"produces a
Docwith that string. Then there are higher-level functions to compose
vcatputs a sequence of docs together, one above the other... and finally
Docto a string.
For my expenses chart I pretty-printed the parsed version of my expenses data.
showDays :: [DayLog] -> String showDays days = render (vcat (map showDay days)) where showDay (DayLog day exps) = text (show day) <+> vcat (map showExp exps) showExp (Expense cost desc tags) = text (show cost) <+> text desc <+> showTags tags showTags tags = text "[" <> hsep (map text tags) <> text "]"
showDaysoutputs a sequence of days by vcatting them together.
showDayshows a single day by writing out the date on the left and then all the day's expenses vertically listed the right.
showTagsjust write out the fields in sequence, more or less.
The output looks like this:
2003-03-15 16 airport food [food] 2003-03-23 10 bart [transport] 9 burger [food] 10 ikea teapot [home] 1 ikea water [drink]All the expenses properly indented over on the right. (I didn't track expenses on my vacation, so there's a gap in the dates there...)