-------------------------------------------------------------------------- -- -- -- Tree and a State monad -- -- -- -- (c) Addison-Wesley, 1996-2010. -- -- -- -------------------------------------------------------------------------- import Prelude hiding (lookup) -------------------------------------------------------------------------- -- Type of trees -- -------------------------------------------------------------------------- data Tree a = Nil | Node a (Tree a) (Tree a) deriving (Eq,Show) -------------------------------------------------------------------------- -- A state monad -- -------------------------------------------------------------------------- data State a b = State (Table a -> (Table a , b)) type Table a = [a] instance Monad (State a) where return x = State (\tab -> (tab,x)) (State st) >>= f = State (\tab -> let (newTab,y) = st tab (State trans) = f y in trans newTab) extract :: State a b -> b extract (State st) = snd (st []) -------------------------------------------------------------------------- -- Assigning unique natural numbers to the members of a tree. -- -------------------------------------------------------------------------- numTree :: Eq a => Tree a -> Tree Int numTree = extract . numberTree numberTree :: Eq a => Tree a -> State a (Tree Int) numberTree Nil = return Nil numberTree (Node x t1 t2) = do num <- numberNode x nt1 <- numberTree t1 nt2 <- numberTree t2 return (Node num nt1 nt2) -------------------------------------------------------------------------- -- Numbering a Node involves a lookup, which in turn will modify -- -- the state in case the value is seen for the first time. -- -------------------------------------------------------------------------- numberNode :: Eq a => a -> State a Int numberNode x = State (\ table -> if elem x table then (table , lookup x table) else (table++[x] , length table) ) lookup :: Eq a => a -> Table a -> Int lookup x table = look x table 0 look :: Eq a => a -> Table a -> Int -> Int look x [] n = error "table lookup" look x (y:ys) n | x==y = n | otherwise = look x ys (n+1) -------------------------------------------------------------------------- -- Examples -- -------------------------------------------------------------------------- example :: Tree Char example = Node 'z' ex1 ex2 ex1 = Node 'f' ex2 ex2 ex2 = Node 'q' (Node 'z' Nil Nil) (Node 'e' Nil Nil) data Children = Ahmet | Dweezil | Moon deriving Eq zapTree :: Tree Children zapTree = Node Moon (Node Ahmet Nil Nil) (Node Dweezil (Node Ahmet Nil Nil) (Node Moon Nil Nil))