We're given the following data structure for our assignment:
-- Question 2: Expression tree.
data Expr
= Lit Float
| Add Expr Expr
| Sub Expr Expr
| Mul Expr Expr
| Div Expr Expr
| X
Which represents either a floating-point value, an add/sub/mul/div of two sub-trees, or an X which stands for an unknown variable. We have to write a method that will pretty-print the tree. This is what I have so far:
draw :: Expr -> Int -> String
draw (Lit f) _ = show f
draw (X) _ = "X"
draw (Add a b) lvl = indent lvl ++ "(+) ---" ++ draw a (lvl+1) ++ "\n" ++ indent lvl ++ "|\n" ++ indent lvl ++ "---" ++ draw b (lvl+1)
draw (Sub a b) lvl = indent lvl ++ "(-) ---" ++ draw a (lvl+1) ++ "\n" ++ indent lvl ++ "|\n" ++ indent lvl ++ "---" ++ draw b (lvl+1)
draw (Mul a b) lvl = indent lvl ++ "(*) ---" ++ draw a (lvl+1) ++ "\n" ++ indent lvl ++ "|\n" ++ indent lvl ++ "---" ++ draw b (lvl+1)
draw (Div a b) lvl = indent lvl ++ "(/) ---" ++ draw a (lvl+1) ++ "\n" ++ indent lvl ++ "|\n" ++ indent lvl ++ "---" ++ draw b (lvl+1)
indent :: Int -> [Char]
indent 0 = []
indent n = "\t"++indent (n-1)
This works for simple trees:
myE2 :: Expr
myE2 = Add (Lit 4) (Sub (Lit 4) (Lit 2))
Prints out as:
*Main> putStr(draw myE2 0)
(+) ---4.0
|
--- (-) ---4.0
|
---2.0
Which is what I intended, however, more complicated trees such as:
myExpr :: Expr
myExpr = (Add (Add (Sub (Mul (Lit 4) (X)) (Lit 1)) (Lit 4)) (Lit 6))
Print out as:
*Main> putStr(draw myExpr 0)
(+) --- (+) --- (-) --- (*) ---4.0
|
---X
|
---1.0
|
---4.0
|
---6.0
Can anyone offer advice as to how I may fix this problem?
You can try the following:
data Expr
= Lit Float
| Add Expr Expr
| Sub Expr Expr
| Mul Expr Expr
| Div Expr Expr
| X
draw :: Expr -> Int -> String
draw (Lit f) _ = show f
draw (X) _ = "X"
draw (Add a b) lvl = "(+) ---" ++ draw a (lvl+1) ++ "\n" ++ indent lvl ++ " |\n" ++ indent lvl ++ " ------" ++ draw b (lvl+1)
draw (Sub a b) lvl = "(-) ---" ++ draw a (lvl+1) ++ "\n" ++ indent lvl ++ " |\n" ++ indent lvl ++ " ------" ++ draw b (lvl+1)
draw (Mul a b) lvl = "(*) ---" ++ draw a (lvl+1) ++ "\n" ++ indent lvl ++ " |\n" ++ indent lvl ++ " ------" ++ draw b (lvl+1)
draw (Div a b) lvl = "(/) ---" ++ draw a (lvl+1) ++ "\n" ++ indent lvl ++ " |\n" ++ indent lvl ++ " ------" ++ draw b (lvl+1)
indent :: Int -> [Char]
indent 0 = []
indent n = " " ++ indent (n-1)
myE2 = Add (Lit 4) (Sub (Lit 4) (Lit 2))
myE3 = Add (Add (Lit 4) (Lit 3)) (Sub (Lit 4) (Lit 2))
myE4 = Add (Add (Lit 4) (Add (Lit 4) (Sub (Lit 4) (Lit 2)))) (Sub (Lit 4) (Lit 2))
myExpr = (Add (Add (Sub (Mul (Lit 4) (X)) (Lit 1)) (Lit 4)) (Lit 6))
It worked for me for the different conditions that I used. Main change: 1. I changed the "\t" to spcaes. 2. I removed the first indent.
[ghci] putStrLn $ draw myExpr 0
(+) ---(+) ---(-) ---(*) ---4.0
|
------X
|
------1.0
|
------4.0
|
------6.0
[ghci] putStrLn $ draw myE4 0
(+) ---(+) ---4.0
|
------(+) ---4.0
|
------(-) ---4.0
|
------2.0
|
------(-) ---4.0
|
------2.0
[ghci] putStrLn $ draw myE3 0
(+) ---(+) ---4.0
|
------3.0
|
------(-) ---4.0
|
------2.0