data Expr
= C Float
| Expr :+ Expr
| Expr :- Expr
| Expr :* Expr
| Expr :/ Expr
| Let Var Expr Expr
| V Var
type Var = String
type VarList = [(Var, Float)]
evaluate :: Expr -> Float
evaluate = eval []
eval :: VarList -> Expr -> Float
eval vars (C x) = x
eval vars (e1 :+ e2) = eval vars e1 + eval vars e2
eval vars (e1 :- e2) = eval vars e1 - eval vars e2
eval vars (e1 :* e2) = eval vars e1 * eval vars e2
eval vars (e1 :/ e2) = eval vars e1 / eval vars e2
eval vars (V var) = getVariable vars var
eval vars (Let var e1 e2) = eval vars' e2
where vars' = setVariable vars var (eval vars e1)
getVariable :: VarList -> Var -> Float
getVariable [] varName = error ("Undefine variable: " ++ varName)
getVariable ((name,value):vs) varName
| name == varName = value
| otherwise = getVariable vs varName
setVariable :: VarList -> Var -> Float -> VarList
setVariable vars varName varValue = (varName, varValue) : vars
----- some tests -----
result1 = evaluate (Let "x" (C 5) (V "x" :+ V "x"))
{-
The way definied getVariable/setVariable will respect variable's scope!
Let's try something more complex to see it:
let x=10 in x+(let x=(x*2) in (let y=4 in y-x)*2) ===> -22.0
-}
result2 = evaluate
(
Let "x" (C 10)
( V "x" :+
Let "x" (V "x" :* (C 2))
((Let "y" (C 4) (V "y" :- V "x")) :* (C 2))
)
)
main = do
putStrLn $ show $ result1
putStrLn $ show $ result2
putStrLn $ show $ evaluate ( V "y" ) -- error
This entry was posted
on Wednesday, May 23rd, 2007 at 7:21 pm and is filed under Haskell - SOE.
You can follow any responses to this entry through the RSS 2.0 feed.
You can leave a response, or trackback from your own site.