Im having issues with adding a show instance to my data structure, wich is:
data Structure = Structure String [Structure]
and I would like to have this output:
strct
strct1
strct2
strct3
I've been trying this
instance Show Structure where
show (Structure a (xs)) = show a ++ "\n" ++ " " ++ show xs
But its output is
"strct"
["strct1"
[], "strct2"
[]]
So, I would need no brackets, no commas and no quotation marks. Any ideas? Thanks
I'm sure there are better library routines for this, but wouldn't this work?
unlines $ a : [" " ++ show x | x <- xs]
However, that covers only one level. You probably want to define a different function than show to maintain the indentation, or you'd have to keep splitting sub-shows with lines
to find where to inject indentation.
A rough draft of such an indentation insertion function is:
prefix p s = unlines [p ++ l | l <- lines s]
Again, I'm sure there's something better in a library. Even these short snippets have gone through a few steps of refinement (foldl1 (++)
-> concat
-> unlines
, then join the first line as head with :
).
Basically there only one bookkeeping to do, i.e. keep tract of the indentation level. An accumulative counter definitely helps:
pretty' :: Int -> Structure -> [String]
pretty' level (Structure s list) = ((concat $ replicate level " ") ++ s) :
(list >>= (pretty' (level + 1)))
This function defines an accumulator of your pretty printer. The remaining part is to wrap it:
pretty = pretty' 0
prettyShow = unlines . pretty
It definitely works
Prelude> putStrLn $ prettyShow (Structure "a" [Structure "b" [Structure "c" []], Structure "d" []])
a
b
c
d
I would suggest using the Data.Tree
module that comes with base
. It is a generic (rose) tree with a structure identical to yours, except that the list goes by a type synonym:
data Tree a = Node {rootLabel :: a, subForest :: Forest a}
type Forest a = [Tree a]
It also comes with the drawTree
and drawForest
functions which are roughly what you were trying to write yourself.
> :m + Data.Tree
> let t = Node "strct" [Node "strct1" [], Node "strct2" [], Node "strct3" []]
> putStr . drawTree $ t
strct
|
+- strct1
|
+- strct2
|
`- strct3