[project @ 2004-01-14 14:58:57 by ralf]
[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 a (Forest a) -- ^ a value and zero or more child trees.
29 #ifndef __HADDOCK__
30   deriving (Eq, Read, Show)
31 #else /* __HADDOCK__ (which can't figure these out by itself) */
32 instance Eq a => Eq (Tree a)
33 instance Read a => Read (Tree a)
34 instance Show a => Show (Tree a)
35 #endif
36 type Forest a = [Tree a]
37
38 instance Functor Tree where
39   fmap = mapTree
40
41 mapTree              :: (a -> b) -> (Tree a -> Tree b)
42 mapTree f (Node x ts) = Node (f x) (map (mapTree f) ts)
43
44 -- | Neat 2-dimensional drawing of a tree.
45 drawTree :: Tree String -> String
46 drawTree  = unlines . draw
47
48 -- | Neat 2-dimensional drawing of a forest.
49 drawForest :: Forest String -> String
50 drawForest  = unlines . map drawTree
51
52 draw :: Tree String -> [String]
53 draw (Node x ts0) = x : drawSubTrees ts0
54   where drawSubTrees [] = []
55         drawSubTrees [t] =
56                 "|" : shift "`- " "   " (draw t)
57         drawSubTrees (t:ts) =
58                 "|" : shift "+- " "|  " (draw t) ++ drawSubTrees ts
59
60         shift first other = zipWith (++) (first : repeat other)
61
62 -- | The elements of a tree in pre-order.
63 flatten :: Tree a -> [a]
64 flatten t = squish t []
65   where squish (Node x ts) xs = x:foldr squish xs ts
66
67 -- | Lists of nodes at each level of the tree.
68 levels :: Tree a -> [[a]]
69 levels t = map (map root) $ takeWhile (not . null) $ iterate subforest [t]
70   where root (Node x _) = x
71         subforest f     = [t | Node _ ts <- f, t <- ts]