Haskell show instance on list

霸气de小男生 提交于 2019-12-02 06:47:59

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
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!