3

我正在尝试为语言 E 定义一个评估器,坦率地说,我完全不知道如何修复我在定义 eval 类型时遇到的所有错误。我现在花了几个小时阅读解释器,单子并试图找到类似的东西给我一个基础,但我什么也没找到。这是作业,所以自然没有直接的答案。我现在的大问题是没有 Num E 或 Integral E 的实例声明,当我尝试使用 fromInt 和 fromNum 来解决这个问题时,我遇到了额外的错误。我还尝试将定义更改为各种不同的方式,主要问题是 Int 与 E 的类型不匹配。我觉得我错过了一些非常基本的东西,但我没有 根本无法缩小范围。如果我对任何特定点不清楚,我很乐意回答任何其他问题。如果有任何来源可以提供很好的附加信息,我将非常感谢链接。

data E = IntLit Int
   | BoolLit Bool
   | Plus E E
   | Minus E E
   | Multiplies E E
   | Divides E E
   | Equals E E
     deriving (Eq, Show)

eval :: E -> E
--eval = undefined
eval (IntLit a) = IntLit a
eval (BoolLit a) = BoolLit a
eval (Plus a b) = eval a + eval b
eval (Minus a b) = eval a - eval b
eval (Multiplies a b) = eval a * eval b
eval (Divides a b) = eval a `div` eval b
eval (Equals a b) = BoolLit(a == b)
4

1 回答 1

3

单子与此无关。因为您将两种类型混合在一起:int 和 bool,您要么需要使用某种类型的hackery(GADT)并使用类型定义 eval:

eval :: E a -> a

或定义一个新类型,Value如下所示:

data Value = IntValue Int | BoolValue Bool | TypeError

然后有:

eval :: E -> Value

在 eval 中,您需要像这样匹配表达式的结果:

eval (Plus e1 e2) = case eval e1 of
    (IntValue v1) -> case eval e2 of
        (IntValue v2) -> IntValue (v1+v2)
        _ -> TypeError
    _ -> TypeError

这很乏味,但很简单。:) 当然你不想重复自己很多次,所以通过定义一个辅助函数来为自己节省很多工作:

evalMathBinOp :: (Int -> Int -> Int) -> E -> E -> Value
evalMathBinOp f e1 e2 = case eval e1 of
    (IntValue v1) -> case eval e2 of
        (IntValue v2) -> IntValue (f v1 v2)
        _ -> TypeError
    _ -> TypeError

现在只是:

eval (Plus e1 e2) = evalMathBinOp (+) e1 e2
eval (Minus e1 e2) = evalMathBinOp (-) e1 e2
-- and so on...
于 2014-10-05T19:45:49.653 回答