Exercise 7.5


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”

  1. 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”)))
    >

  2. 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)

  3. 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)

Leave a Reply

Your email address will not be published. Required fields are marked *