module HW1 where -- -- * A simple arithmetic expression language -- -- | A representation of arithmetic expressions as binary trees where leaves -- are literal integers and internal nodes are either addition or -- multiplaction nodes. Note that this data structure is an "abstract -- syntax tree", which is something we will spend more time talking about -- later in the course. data Expr = Lit Int -- ^ Literal integers | Add Expr Expr -- ^ Addition expressions | Mul Expr Expr -- ^ Multiplication expressions deriving (Eq,Show) fold :: (Int -> a) -> (a -> a -> a) -> (a -> a -> a) -> Expr -> a fold f1 f2 f3 = rec where rec (Lit i) = f1 i rec (Add l r) = f2 (rec l) (rec r) rec (Mul l r) = f3 (rec l) (rec r) instance Num Expr where (+) = Add (*) = Mul fromInteger = Lit . fromInteger -- | The expression: 2 + 3 * 4 e1 :: Expr e1 = Add (Lit 2) (Mul (Lit 3) (Lit 4)) -- | The expression: (7 + 6) * 5 e2 :: Expr e2 = Mul (Add (Lit 7) (Lit 6)) (Lit 5) -- | The expresssion: 3 * 2 + 5 * 4 -- Make sure to take standard operator precedence into account. e3 :: Expr e3 = 3 * 2 + 5 * 4 -- :) -- | The expression: 8 + 7 * 9 + 6 -- Make sure to take standard operator precedence into account. e4 :: Expr e4 = 8 + 7 * 9 + 6 -- :) -- | The leftmost literal in an expression. -- -- >>> leftLit (Lit 3) -- 3 -- -- >>> leftLit e1 -- 2 -- -- >>> leftLit e2 -- 7 -- leftLit :: Expr -> Int leftLit = fold id const const -- | The rightmost literal in an expression. -- -- >>> rightLit (Lit 3) -- 3 -- -- >>> rightLit e3 -- 4 -- -- >>> rightLit e4 -- 6 -- rightLit :: Expr -> Int rightLit = fold id (flip const) (flip const) -- | Get the maximum literal value in an expression. -- -- >>> maxLit (Lit 3) -- 3 -- -- >>> maxLit e1 -- 4 -- -- >>> maxLit e2 -- 7 -- -- >>> maxLit e3 -- 5 -- -- >>> maxLit e4 -- 9 -- maxLit :: Expr -> Int maxLit = fold id max max -- | The integer result of evaluating an expression. -- -- >>> eval (Lit 3) -- 3 -- -- >>> eval e1 -- 14 -- -- >>> eval e2 -- 65 -- -- >>> eval e3 -- 26 -- -- >>> eval e4 -- 77 -- eval :: Expr -> Int eval = fold id (+) (*) -- | Render an expression as a string (called "pretty printing"). -- -- My solution only adds parentheses when strictly necessary, but it's -- easier to add them conservatively (that is, to add more than you need). -- It's OK if your solution adds more parentheses as long as they don't -- change the meaning of the expression--feel free to tweak the tests to -- make them pass. -- -- >>> pretty (Lit 3) -- "3" -- -- >>> pretty e1 -- "2 + 3 * 4" -- -- >>> pretty e2 -- "(7 + 6) * 5" -- -- >>> pretty e3 -- "3 * 2 + 5 * 4" -- -- >>> pretty e4 -- "8 + 7 * 9 + 6" -- -- >>> pretty (Add e1 e2) -- "2 + 3 * 4 + (7 + 6) * 5" -- -- >>> pretty (Mul e1 e2) -- "(2 + 3 * 4) * (7 + 6) * 5" -- pretty :: Expr -> String pretty (Lit n) = show n pretty (Add l r) = pretty l ++ " + " ++ pretty r pretty (Mul l r) = prettyMul l ++ " * " ++ prettyMul r where prettyMul e@Add{} = "(" ++ pretty e ++ ")" prettyMul e = pretty e