Haskell 创建函数的解释器 eval

Haskell interpreter eval to create functions

我正在尝试对函数表达式执行 eval 以便能够在我的解释器上创建函数。到目前为止我有这个:

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)

在给定类型上效果很好。但是,当我尝试将其转换为能够处理以下采用表达式和参数列表的类型时:

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

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)

在如下情况下工作

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

我遇到语法错误。在 foldr 表达式中:

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)

并在插入表达式中:

(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)

我正在尝试使用 foldr 评估我当前环境的所有参数列表,然后将值插入我的函数环境,然后评估函数结果。任何建议表示赞赏。谢谢。

我已经解决了。基本上我必须以更好的方式处理我的类型流。

首先我检查给定的表达式是否形成闭包,这对于能够评估函数应用程序很重要。

然后,如果表达式是一个有效的闭包,我形成闭包并评估所有函数参数(它们是表达式,在评估时成为值),然后将参数与结果值匹配以添加它们到新环境(现在是函数的环境)并使用这个新环境评估函数的主体。这基本上是当您将一些参数传递给函数时发生的情况,在函数内部形成临时变量并在此新函数环境的上下文中完成计算以 return 一个值。

A​​ppExp则变成如下:

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


我希望这对其他人有帮助。抱歉格式化。干杯!