8524935ec277e8e88b55c480e26a2821d9a3add4
[packages/containers.git] / Data / Tree.hs
1 -----------------------------------------------------------------------------
2 -- |
3 -- Module : Data.Tree
4 -- Copyright : (c) The University of Glasgow 2002
5 -- License : BSD-style (see the file libraries/base/LICENSE)
6 --
7 -- Maintainer : libraries@haskell.org
8 -- Stability : experimental
9 -- Portability : portable
10 --
11 -- Multi-way trees (/aka/ rose trees) and forests.
12 --
13 -----------------------------------------------------------------------------
14
15 module Data.Tree(
16 Tree(..), Forest,
17 drawTree, drawForest,
18 flatten, levels,
19 ) where
20
21 -- | Multi-way trees, also known as /rose trees/.
22 data Tree a = Node a (Forest a) -- ^ a value and zero or more child trees.
23 #ifndef __HADDOCK__
24 deriving (Eq, Read, Show)
25 #else /* __HADDOCK__ (which can't figure these out by itself) */
26 instance Eq a => Eq (Tree a)
27 instance Read a => Read (Tree a)
28 instance Show a => Show (Tree a)
29 #endif
30 type Forest a = [Tree a]
31
32 instance Functor Tree where
33 fmap = mapTree
34
35 mapTree :: (a -> b) -> (Tree a -> Tree b)
36 mapTree f (Node x ts) = Node (f x) (map (mapTree f) ts)
37
38 -- | Neat 2-dimensional drawing of a tree.
39 drawTree :: Show a => Tree a -> String
40 drawTree = unlines . draw . mapTree show
41
42 -- | Neat 2-dimensional drawing of a forest.
43 drawForest :: Show a => Forest a -> String
44 drawForest = unlines . map drawTree
45
46 draw :: Tree String -> [String]
47 draw (Node x ts0) = grp this (space (length this)) (stLoop ts0)
48 where this = s1 ++ x ++ " "
49
50 space n = replicate n ' '
51
52 stLoop [] = [""]
53 stLoop [t] = grp s2 " " (draw t)
54 stLoop (t:ts) = grp s3 s4 (draw t) ++ [s4] ++ rsLoop ts
55
56 rsLoop [] = error "rsLoop:Unexpected empty list."
57 rsLoop [t] = grp s5 " " (draw t)
58 rsLoop (t:ts) = grp s6 s4 (draw t) ++ [s4] ++ rsLoop ts
59
60 grp fst0 rst = zipWith (++) (fst0:repeat rst)
61
62 [s1,s2,s3,s4,s5,s6] = ["- ", "--", "-+", " |", " `", " +"]
63
64 -- | The elements of a tree in pre-order.
65 flatten :: Tree a -> [a]
66 flatten t = squish t []
67 where squish (Node x ts) xs = x:foldr squish xs ts
68
69 -- | Lists of nodes at each level of the tree.
70 levels :: Tree a -> [[a]]
71 levels t = map (map root) $ takeWhile (not . null) $ iterate subforest [t]
72 where root (Node x _) = x
73 subforest f = [t | Node _ ts <- f, t <- ts]