我试图为语言E定义一个评估器,并且坦率地说我完全不知道如何修复我在定义eval类型时遇到的所有错误。我现在花了几个小时阅读口译员,monad并试图找到类似的东西来给我一个基础,但我什么也没找到。这是作业,所以自然没有直接的答案请。我现在面临的重大问题是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)
答案 0 :(得分:3)
Monads与此毫无关系。因为您将两种类型混合在一起:int和bools,您需要使用某种类型的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...