使用Haskell解释器创建函数

问题描述 投票:-2回答:1

我正在尝试在函数表达式上实现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

我收到语法错误。在文件夹表达式中:

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评估当前环境的所有参数列表,然后将值插入到我的函数环境中,然后评估函数结果。任何建议表示赞赏。谢谢。

haskell functional-programming haskell-stack
1个回答
0
投票

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

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

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

然后,AppExp变为如下:

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


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

© www.soinside.com 2019 - 2024. All rights reserved.