0
votes

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)

1
The last three equations in where must be indented exactly in the same way. Also, turn on warnings: you are discarding acc, which should be reported as a warning.chi
I have fixed all the syntax issues but still can not perform the pattern matching. Can not really understand why.DENIZHAN KARA
Your last WhereExp pattern should cover all cases except for WhereExp e1 []), so I can't see what's wrong.chi
I think it's better to ask a new, followup question, including the latest code and link to this question for background. one question at a time. :)Will Ness

1 Answers

1
votes

I will assume where bindings can not be recursive, like your let ones.

So, we have WhereExp e1 bindings where bindings :: [(String, Exp)]. We can proceed as follows.

  • First, we recursively evaluate all the Exps in that list. We can use map ... bindings for that, where the ... function calls eval suitably. This produces a list of evaluated bindings [(String, Val)].
  • Then, we have to insert these values in env. That is, from the list [(str1, val1), (str2, val2), ...] we want to compute insert str1 val1 (insert str2 val2 .... env).
  • Finally, using the modified environment, we can evaluate e1.