I am trying to add where expression eval to my interpreter. My current data types and eval methods are below.
data Exp = IntExp Integer
| IntOpExp String Exp Exp
| WhereExp Exp [(String, Exp)]
| VarExp String
deriving(Show,Eq)
type Env = [(String, Val)]
data Val = IntVal Integer
| ExnVal String
deriving(Show, Eq)
eval :: Exp -> Env -> Val
eval (IntExp i) _ = IntVal i
eval (IntOpExp op e1 e2) env =
let v1 = eval e1 env
v2 = eval e2 env
Just f = lookup op intOps
in liftIntOp f v1 v2
eval (LetExp var e1 e2) env =
let v1 = eval e1 env
in eval e2 (insert var v1 env)
Currently, I have had the approach of where clause working similar to let clause, but for multiple expressions, thus made this implementation :
--For empty pattern (WhereExp _ []) _ :
eval (WhereExp e1 []) env = eval e1 env
--For single element case
eval (WhereExp e1 [(var, e2)]) env =
let v2 = eval e2 env
in eval e1 (insert var v2 env)
Which works for single-element lists of (var,e2) such as :
ghci> eval (WhereExp (VarExp "x") [("x",(IntExp 0))]) []
(IntVal 0)
ghci> eval (IntOpExp "*" (VarExp "z") (WhereExp (IntOpExp "-" (VarExp "x") (VarExp "y")) [("y",(IntExp 5))])) [("x", (IntVal 12)), ("z", (IntVal (-4)))]
(IntVal (-28))
But does not cover patterns like below :
(WhereExp _ ((_, _):_:_)) _
(WhereExp _ []) _
where multiple (var,e) elements exist in the list. Such a case, for example, is below, which gives non-exhaustive patterns
eval((WhereExp (IntOpExp "+" (VarExp "x") (VarExp "y")) [("x",IntExp 10),("y",IntExp 12)],[]),IntVal 22)
I am kind of lost on how to approach a list of (var,e) pairs to implement this pattern to my where clause. Any help is much appreciated! Thank you.
Edit: Based on the chi's answer, which was very helpful for me to understand what to do, I have made some progress and providing my current state below. I have utilized a helper function for implementing. But I still can not seem to cover the pattern :
(WhereExp _ ((_, _):_:_)) _
Further advices would be appreciated. Thank you !
helperEvaluator :: [(String,Exp)] -> Env -> [(String,Val)]
helperEvaluator xs cur_env = map (\(a,b) -> (a,eval b cur_env)) xs
eval (WhereExp e1 ((var, e2):xs)) env = eval e1 new_env
where
--helperEvaulator xs cur_env = map (\acc (a,b) -> (a,eval b cur_env)) xs
--new_list = helperEvaulator [(var, e2)] env
new_env = foldr ((\(var1,v1) -> (insert var1 v1))) (env) (helperEvaluator ((var, e2):xs) env)
where
must be indented exactly in the same way. Also, turn on warnings: you are discardingacc
, which should be reported as a warning. – chiWhereExp
pattern should cover all cases except forWhereExp e1 [])
, so I can't see what's wrong. – chi