Reputation: 430
If have a data type
data Arith = Con Int
| Add Arith Arith
| Sub Arith Arith
| Mul Arith Arith
| Div Arith Arith
an instance:
instance Show Arith where
show (Con i) = show i
show (Add e1 e2) = "(" ++ show e1 ++ " + " ++ show e2 ++ ")"
show (Sub e1 e2) = "(" ++ show e1 ++ " - " ++ show e2 ++ ")"
show (Mul e1 e2) = "(" ++ show e1 ++ " * " ++ show e2 ++ ")"
show (Div e1 e2) = "(" ++ show e1 ++ " / " ++ show e2 ++ ")"
and a function evaluate which is expected behave like:
ghci> eval (Mul (Con 5) (Div (Con 6) (Con 2) ))
15
this is what I've come up with that's not working when I try anything more complex then the basic case.
eval :: ArithExp -> Int
eval (Con e1) = e1
eval (Add (Con e1) (Con e2)) = e1 + e2
eval (Sub (Con e1) (Con e2)) = e1 - e2
eval (Div (Con e1) (Con e2)) = e1 `div` e2
eval (Mul (Con e1) (Con e2)) = e1 * e2
When I try anything that isn't in this case, of course I get an error about exhaustive patterns.
So my question is, how do I catch all of the patterns without doing it the naive way?
I did notice that Add is defined as Add Arith Arith, Sub Arith Arith so how would I take advantage of that in my eval function? I tried doing:
eval (Add Arith Arith) = Arith + Arith
But that didn't work either, (not in scope error).
You don't need to give me a full working code example or anything, I'm just trying to get pointed in the right direction. Still new at haskell.
Thanks.
Upvotes: 1
Views: 191
Reputation: 13677
Here is a little refactoring to reduce duplication:
data OpT = Add | Sub | Mul | Div
data Arith = Con Int
| Op OpT Arith Arith
eval :: Arith -> Int
eval (Con a) = a
eval (Op f a b) = evalOp f (eval a) (eval b) where
evalOp Add = (+)
evalOp Sub = (-)
evalOp Mul = (*)
evalOp Div = div
You can do the same with show
.
Upvotes: 0
Reputation: 110
You should use recursion.
eval (Add a1 a2) = (eval a1) + (eval a2)
etc..
Upvotes: 6