我不确定我做错了什么。我被困住了,我不能再进步了。
我在评论中输入了我的代码中的错误消息。 如果时间允许,有人可以检查我的评估功能吗?我想我做的事情非常糟糕。
谢谢。
答案 0 :(得分:4)
您的Let
处理程序需要使用新绑定扩展环境,然后使用该新环境评估表达式。
您的环境是名称Value
对的列表,但Let
包含名称Exp
对的列表,因此您需要转换Exp
进入Value
以扩展环境。请注意,eval
会将Exp
转换为Value
。
但是,由于Let
可以包含多个绑定,因此您需要确定Exp
是并行评估还是顺序评估(let
和{{1之间的差异在lisp中)。绑定是否会影响以下绑定的值?根据该问题的答案,您会发现自己使用let*
或map
来转换列表。
评估foldl
的问题是双重的。首先,您使用的模式只匹配一个元素的列表,但您的基元显然需要不同数量的参数。该模式不应使用列表语法,因为Primitive
构造函数保证在该位置将有一个列表。相反,您应该使用匹配任何内容的模式(如普通Primitive
)。其次,y
函数需要prim
的列表,但Value
构造函数包含Primitive
的列表,因此您需要转换它们(但是,因为对参数的评估不会影响环境,您将使用Exp
)。
让你朝着正确的方向前进:
map
eval e (Primitive x [y]) = prim x [eval e y]
模式只匹配单个元素列表,该元素绑定到[y]
,y
将导致单个元素列表。你想要的是一个匹配整个列表的模式,然后你想通过将[eval e y]
应用于该列表的每个元素来转换该列表。
eval e
的{{1}}也存在问题。条件,then和else都是eval
类型,但是eval应该返回If
,所以你必须转换一些东西。最后,haskell Exp
希望条件为haskell Value
,但您的条件是if
。您需要将Bool
评估为Exp
,然后以某种方式从Exp
中提取一个haskell Value
。您希望Bool
和Value
Number
的行为与您的语言{(1)}一样(例如python),还是只应String
Value
s表现得像Bool
s?
最后,最后,如果您有任何类型错误(例如尝试Bool
Value
到Bool
),或者您为基元提供了错误数量的参数,那么将从Add
函数中获取模式匹配失败(并且可能在您必须编写的代码中从String
条件中提取Number
。这可能是也可能不是你想要的......
答案 1 :(得分:3)
eval :: Env -> Exp -> Value
-- the return type is Value
-- what are you trying to do here ? extract Value from x ...
eval e (Let [x] y) = eval e $ snd x
-- ... or from y ? Both x & y are of Exp type.
eval e (Let [x] y) = eval e y
您的代码中还存在更多类型错误:
eval e (Primitive x [y]) = prim x [y]
-- prim expects 2nd argument of [Value] type so it can be written as
eval e (Primitive x [y]) = prim x [eval e y]
-- dtto, mixing different types is wrong
eval e (If x y z) = if x then y else z
eval e (If x y z) = let Bool x' = eval e x in
if x' then (eval e y) else (eval e z)
最后main期望IO ()
作为返回类型,所以你必须以某种方式反映这一点,比如打印eval结果:
print $ eval [("y", (Number 40))] (Let [("x", (Literal (Number 2)))] (Primitive Add [(Variable "x"), (Variable "y")]))
答案 2 :(得分:1)
你想要像
这样的东西let e' = {- extend env with x -} in eval e' y