-1

I am trying to implement eval on function expressions to be able to create functions on my interpreter. So far I have this :

data Exp = FunExp String Exp| AppExp Exp Exp 
data Val = Closure String Exp Env 

eval (FunExp v body) env = Closure v body env

eval (AppExp e1 e2) env =
    let (Closure v body clenv) = eval e1 env
        arg = eval e2 env
    in eval body (insert v arg clenv)

which works well on given types. However, when I try to convert this to be able to work on following types that take list of expressions and arguments:

data Exp = FunExp [String] Exp| AppExp Exp [Exp] 
data Val = Closure [String] Exp Env 

as in

eval (FunExp params body) env = (CloVal params body env)


eval (AppExp e1 args) env = 
    eval body (insert v arg clenv)
    where
        (CloVal v body clenv) = eval e1 env
        arg = (foldr eval env args)

to work in a case like the following

Main> let fun1 = FunExp ["a", "b"] (IntOpExp "+" (VarExp "a") (VarExp "b"))
Main> eval (AppExp fun1 [IntExp 5, IntExp 4]) empty
9

I get sytax errors. In the foldr expression :

arg = (foldr eval env args)

Couldn't match type ‘Val’ with ‘HashMap String Val’
  Expected type: Exp -> Val -> Val
    Actual type: Exp -> Env -> Val
• In the first argument of ‘foldr’, namely ‘eval’
  In the expression: (foldr eval env args)
  In an equation for ‘arg’: arg = (foldr eval env args)

And in the insert expression :

(insert v arg clenv)

Couldn't match type ‘[Char]’ with ‘Char’
  Expected type: Env
    Actual type: HashMap [String] Val
• In the second argument of ‘eval’, namely ‘(insert v arg clenv)’
  In the expression: eval body (insert v arg clenv)

I am trying to evaluate all list of arguments to my current environment using foldr and then insert the values to my functions environment, and then evaluate the function result. Any advice are appreciated. Thank you.

DENIZHAN KARA
  • 29
  • 1
  • 6

1 Answers1

0

I have resolved it. Basically I had to handle my type flow in a better way.

First I check if the given expression forms a closure, this is important in order to be able to evaluate a function application.

Then, if the expression is a valid closure, I form the closure and evaluate all the function arguments(which are expressions, that become values when evaluated), then match the arguments with the resulting values in order to add them to the new environment( which is now the function's environment) and evaluate the body of the function with this new environment. This is basically what happens when you pass some arguments to a function, inside a function temporary variables are formed and computations are done within the context of this new function environment in order to return a value.

The AppExp then becomes as follows:

eval (AppExp e1 args) env = 
    case eval e1 env of
        (CloVal v body clenv) -> eval body (new_map) -- evaluate the function body with the new environment "new map" in order to get the result
        _ -> ExnVal "Apply to non-closure" -- If the expression is not a closure, do not apply function

        where
            (CloVal v body clenv) = eval e1 env -- Form a closure
            arg = map (\x -> eval x env) args   --Evaluate all the args to get a list of vals ->arg
            new_map = union (fromList (zip v arg)) (clenv) -- add the evaluated values to the function environment in order to evaluate body of the function


I hope this helps others. Sorry for the formatting. Cheers!

DENIZHAN KARA
  • 29
  • 1
  • 6