一个Haskell迷你语言

时间:2014-10-05 19:32:23

标签: haskell evaluator mini-language

我试图为语言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)

1 个答案:

答案 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...