data Expr = C Float
| V String
| Expr :+ Expr
| Expr :- Expr
| Expr :* Expr
| Expr :/ Expr
| Let String Expr Expr
deriving Show
evaluate :: Expr -> [(String, Float)] -> Float
evaluate (C x) _ = x
evaluate (V x) vars = lookup x vars
where lookup i [] = error "Unbound variable"
lookup i ((a,b):vars) = if i == a then b else lookup i vars
evaluate (e1 :+ e2) vars = (evaluate e1 vars) + (evaluate e2 vars)
evaluate (e1 :- e2) vars = (evaluate e1 vars) - (evaluate e2 vars)
evaluate (e1 :* e2) vars = (evaluate e1 vars) * (evaluate e2 vars)
evaluate (e1 :/ e2) vars = (evaluate e1 vars) / (evaluate e2 vars)
evaluate (Let s e1 e2) vars = let es = evaluate e1 vars
in evaluate e2 ((s, es):vars)
3 responses to “Exercise 7.5”
Solution without lists and with late binding :
>data Expr = C Float | Expr :+ Expr | Expr :- Expr
> | Expr :* Expr | Expr :/ Expr | Let String Expr Expr
> | V String
>
>evaluate e=let
> eval (C x) map = x
> eval (e1 :+ e2) map = eval e1 map + eval e2 map
> eval (e1 :- e2) map = eval e1 map – eval e2 map
> eval (e1 :* e2) map = eval e1 map * eval e2 map
> eval (e1 :/ e2) map = eval e1 map / eval e2 map
> eval (V arg) map = eval (map arg) map
> eval (Let arg e1 e2) map = eval e2 (\x->if x==arg then e1 else map x)
> in eval e (\x->error (“no definition for “++x))
>
>test = evaluate (Let “x” (V “y”) (Let “y” (C 6.0) (V “x”)))
>
Let “x” (C 3.0) (Let “y” (V “x”) (Let “x” (C 2.0) (V “y”)))
evalutated to 3 by admin’s definition, but 2 by Wieslaw’s definition.
I think the late binding mechanism should keep its environment, so I suggest
> eval (Let arg e1 e2) map = eval e2 (\x->if x==arg then (C $ eval e1 map) else map x)
I think the book did not want you to change the type of the function. However the solution given has type
> evaluate :: Expr -> [(String, Float)] -> Float
instead of
> evaluate :: Expr -> Float
I would suggest
> evaluate :: Expr -> Float
> evaluate (C x) = x
> evaluate (e1 :+ e2) = evaluate e1 + evaluate e2
> evaluate (e1 :- e2) = evaluate e1 – evaluate e2
> evaluate (e1 :* e2) = evaluate e1 * evaluate e2
> evaluate (e1 :/ e2) = evaluate e1 / evaluate e2
> {- the above are the old definition given in the book -}
> evaluate (Let str val (C x)) = x
> evaluate (Let str val (exp1 :+ exp2)) = (evaluate (Let str val exp1)) + (evaluate (Let str val exp2))
> evaluate (Let str val (exp1 :- exp2)) = (evaluate (Let str val exp1)) – (evaluate (Let str val exp2))
> evaluate (Let str val (exp1 :* exp2)) = (evaluate (Let str val exp1)) * (evaluate (Let str val exp2))
> evaluate (Let str val (exp1 :/ exp2)) = (evaluate (Let str val exp1)) / (evaluate (Let str val exp2))
> evaluate (Let str val (V str2)) | str == str2 = evaluate val
> | otherwise = error (“undefined variable “++str2)