Haskell解析错误

时间:2013-02-02 03:51:14

标签: haskell

我不确定我做错了什么。我被困住了,我不能再进步了。

我在评论中输入了我的代码中的错误消息。 如果时间允许,有人可以检查我的评估功能吗?我想我做的事情非常糟糕。

谢谢。

3 个答案:

答案 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。您希望BoolValue Number的行为与您的语言{(1)}一样(例如python),还是只应String Value s表现得像Bool s?

最后,最后,如果您有任何类型错误(例如尝试Bool ValueBool),或者您为基元提供了错误数量的参数,那么将从Add函数中获取模式匹配失败(并且可能在您必须编写的代码中从String条件中提取Number。这可能是也可能不是你想要的......

答案 1 :(得分:3)

正如Thomas M. DuBuisson所说,你的let表达式语法无效。其次,你必须要知道函数采用什么类型的参数以及它返回的类型。例如,你不能将Exp与Value混合 - 在预期的Exp类型中,你总是传递Exp类型的值等。

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