[project @ 2004-01-27 09:52:37 by ross]
[ghc-base.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         -- * Two-dimensional drawing
18         drawTree, drawForest,
19         -- * Extraction
20         flatten, levels,
21     ) where
22
23 #ifdef __HADDOCK__
24 import Prelude
25 #endif
26
27 -- | Multi-way trees, also known as /rose trees/.
28 data Tree a   = Node {
29                 rootLabel :: a,         -- ^ label value
30                 subForest :: Forest a   -- ^ zero or more child trees
31         }
32 #ifndef __HADDOCK__
33   deriving (Eq, Read, Show)
34 #else /* __HADDOCK__ (which can't figure these out by itself) */
35 instance Eq a => Eq (Tree a)
36 instance Read a => Read (Tree a)
37 instance Show a => Show (Tree a)
38 #endif
39 type Forest a = [Tree a]
40
41 instance Functor Tree where
42   fmap = mapTree
43
44 mapTree              :: (a -> b) -> (Tree a -> Tree b)
45 mapTree f (Node x ts) = Node (f x) (map (mapTree f) ts)
46
47 -- | Neat 2-dimensional drawing of a tree.
48 drawTree :: Tree String -> String
49 drawTree  = unlines . draw
50
51 -- | Neat 2-dimensional drawing of a forest.
52 drawForest :: Forest String -> String
53 drawForest  = unlines . map drawTree
54
55 draw :: Tree String -> [String]
56 draw (Node x ts0) = x : drawSubTrees ts0
57   where drawSubTrees [] = []
58         drawSubTrees [t] =
59                 "|" : shift "`- " "   " (draw t)
60         drawSubTrees (t:ts) =
61                 "|" : shift "+- " "|  " (draw t) ++ drawSubTrees ts
62
63         shift first other = zipWith (++) (first : repeat other)
64
65 -- | The elements of a tree in pre-order.
66 flatten :: Tree a -> [a]
67 flatten t = squish t []
68   where squish (Node x ts) xs = x:foldr squish xs ts
69
70 -- | Lists of nodes at each level of the tree.
71 levels :: Tree a -> [[a]]
72 levels t = map (map rootLabel) $
73                 takeWhile (not . null) $
74                 iterate (concatMap subForest) [t]