I'm writing a simple interpreter in Haskell. I have 3 possible variable types: bool, int and string. To avoid repetition in evaluating comparisons, I've written a function that takes 2 expressions and an operator:
data Value = IntVal Integer
| StringVal String
| BoolVal Bool
| ...
evalComparison :: Ord a => Exp -> (a -> a -> Bool) -> Exp -> Result Value
evalComparison expr1 op expr2 = do
val1 <- evalExp expr1
val2 <- evalExp expr2
return $ BoolVal $
case (val1, val2) of
(IntVal i1, IntVal i2) -> op i1 i2 (*)
(StringVal s1, StringVal s2) -> op s1 s2 (**)
(BoolVal b1, BoolVal b2) -> op b1 b2 (***)
otherwise -> error "Expected values of the same type!"
It's intended usage is, for example:
evalExp :: Exp -> Result Value
...
evalExp (ELessThen e1 e2) = evalComparison e1 (<) e2
(And so on for other comparison operators).
The problem is - it doesn't work. GHC says it couldn't match type Integer with [Char] in line (**) and similarly Integer with Bool in line (***).
I think I know where the problem lies: once the a from the operator's type is determined as Integer in line (*), it cannot be changed. So my question is twofold:
Why does this problem arise, provided that the result type (
Bool) is always the same regardless of the operator's arguments' types?What can be done to make this work?