I am trying to define an evaluator for the E language and be frank. I'm completely at a loss as to how to fix all the errors I keep getting with the eval type definition. I spent several hours reading translators, monads and trying to find something similar to give me a foundation, but I didn't get it. This is homework, so naturally there are no direct answers. My big problems right now is that there are no instance declarations for Num E or Integral E, and when I tried to use fromInt and fromNum to fix this, I was met with additional errors. I've also tried changing the definitions in all sorts of ways, the main problem is that the Int doesn't match the type E. I feel like I'm missing something pretty simple, but I haven't been able to narrow it down at all. I will be happy to answer any other questions,if I do not understand any specific points. If there are any sources that would be good additional information, I would love the links.
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)
source to share
Monads have nothing to do with this. Since you are mixing the two types together, ints and bools, you either need to use type specific hackers (GADT) or define eval with the type:
eval :: E a -> a
or define a new type called
data Value = IntValue Int | BoolValue Bool | TypeError
eval :: E -> Value
Inside eval, you need to match the results of your expressions like this:
eval (Plus e1 e2) = case eval e1 of (IntValue v1) -> case eval e2 of (IntValue v2) -> IntValue (v1+v2) _ -> TypeError _ -> TypeError
It's tedious but simple. :) Of course you don't want to repeat yourself many times, so save a lot of work by defining a helper function:
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
and now it's simple:
eval (Plus e1 e2) = evalMathBinOp (+) e1 e2 eval (Minus e1 e2) = evalMathBinOp (-) e1 e2 -- and so on...
source to share