This page has some examples of trees built using the IBranch
and ILeaf
constructors specified in assignment 5.
{-# LANGUAGE FlexibleContexts #-}
module A05Trees where
import A05Sol hiding (main)
import Control.Monad.RWS
import System.IO
We’ll use this shortcut for a “terminal branch” – one whose left and right children are both empty:
t2 :: ITree Ordering
t2 =
IBranch EQ
(IBranch LT
(iterm GT)
(IBranch LT (iterm EQ) ILeaf))
(iterm GT)
t7 :: ITree Int
t7 =
IBranch 14
(IBranch 13
(IBranch 12
(iterm 10)
(iterm 11))
(IBranch 2
ILeaf
(iterm 5)))
(IBranch 3
(IBranch 6
(iterm 8)
(iterm 7))
(iterm 9))
You don’t necessarily need to look at this section, but I’ll describe what it does in case you’re curious. The function graphviz
takes a tree and converts it into a string in a language called GraphViz that can then be fed to a command-line tool to produce images. All the diagrams of trees on this page were produced from this Haskell program and GraphViz.
graphviz :: Show a => ITree a -> String
graphviz tree = surround $ snd $ execRWS (travel tree) () 0
where
surround s = "digraph {\n" ++ s ++ "}\n"
quote a = "\"" ++ concatMap subst (show a) ++ "\""
subst '"' = "\\\""
subst c = [c]
increment :: MonadState Int m => (Int -> m a) -> m Int
increment f = do
i <- get
put (i+1)
void (f i)
return i
node i = "node" ++ show i
travel ILeaf = increment $ \i ->
tell $ node i ++ " [shape=circle, width=0.2, label=\"\"]\n"
travel (IBranch value left right) = increment $ \i -> do
j <- travel left
k <- travel right
tell $
node i ++ " [shape=rectangle, label=" ++ quote value ++ "]\n" ++
node i ++ " -> " ++ node j ++ "\n" ++
node i ++ " -> " ++ node k ++ "\n"
createGraph :: (String, String) -> IO ()
createGraph (name, dot) =
putStrLn ("Creating " <> filename) >>
withFile filename WriteMode (flip hPutStr dot)
where
filename = "a05" ++ name ++ ".dot"
main :: IO ()
main = mapM_ createGraph
[ ("t1", graphviz t1)
, ("t2", graphviz t2)
, ("t3", graphviz t3)
, ("t4", graphviz t4)
, ("t5", graphviz t5)
, ("t6", graphviz t6)
, ("t7", graphviz t7)
, ("t1sq", graphviz (fmap square t1))
, ("t1flip", graphviz (flipTree t1))
, ("buildints", graphviz (balancedFromList range))
, ("buildwords", graphviz (balancedFromList (words phrase)))
]
A compact string representation of trees:
compactShow :: Show a => ITree a -> String
compactShow ILeaf = "()"
compactShow (IBranch x ILeaf ILeaf) = show x
compactShow (IBranch x l r) =
concat [ "(", show x
, " ", compactShow l
, " ", compactShow r
, ")"
]
Used in some tests: