
Hi, I have made the following (very small and basic) interpter: data Code = PUSH Integer | ADD | BRANCH [Code] [Code] | CMP deriving (Show) data StackElement = StackInteger Integer | StackBool Bool deriving (Show) type Stack = [StackElement] eval :: [Code] -> Stack -> Stack eval [] s = s eval (PUSH n:t) s = eval t (StackInteger n:s) eval (ADD:t) (StackInteger x:StackInteger y:s) = eval t (StackInteger (x + y):s) eval (CMP:t) (StackInteger x:StackInteger y:s) = eval t (StackBool (x == y):s) eval (BRANCH c1 c2:t) (StackBool cond:s) = if cond then eval (c1 ++ t) s else eval (c2 ++ t) s Now, I would like to change StackElement to be able to work with any types, that is: data StackElement a b = StackInteger a | StackInteger b deriving (Show) How would I make this change? I thought about using typeclasses, but since type a and type b in StackElement a b clearly are related (the == operation on type a must result in type b), I need to use multi-parameter type classes (and maybe also functional dependecies?). I also thought about introducing a new type Operation: data Operation a b = Operation { cmp :: a -> a -> b, add :: a -> a -> a, (more required functions) } Is any of these solutions the preferred one, or is there another solution that I don't know of (this is very likely, I'm completely new to Haskell)? Thanks for taking your time and reading this lengthy post, Erik