Reputation: 13
I'm trying to write a function that simplifies expressions by identifying parts of it that will evaluate to zero, so that n*0 -> 0 and n+0 -> n etc.
elimiZeros :: Exp -> Exp
The data type is:
data Exp = Num Int
| Add Exp Exp
| Sub Exp Exp
| Mult Exp Exp
| Div Exp Exp
| Power Exp Exp
| Neg Exp
deriving Show
To avoid having to pattern match each operator by themselves, I tried matching several at the same time, however I get a compiler error: "Parse error in pattern: a":
elimiZeros :: Exp -> Exp
elimiZeros (Num n) = (Num n)
elimiZeros (a b c) =
if c == (Num 0)
then case a of
Add -> elimiZeros b
Sub -> elimiZeros b
Mult -> (Num 0)
else if b == (Num 0)
then case a of
Add -> elimiZeros c
Sub -> elimiZeros c
-- etc, not finished
else (a b c)
Isn't it possible to pattern match with this syntax?
Edit: Thank you for the clarifying responses!
Upvotes: 1
Views: 719
Reputation: 116139
Haskell does not allow patterns like
f (a b c) = ...
To see why, consider this type:
data T = A Int Int | B Bool Bool
f :: T -> ...
f (a b c) = ...
If that were allowed, what would be the type of b
and c
? Well, it could be Int
or Bool
, we can't know for sure. So, in general, (a b c)
patterns are forbidden, requiring that a pattern must start with an explicit constructor (unless the pattern is just a variable, of course).
In your code, you can try using multiple equations
elimiZeros (Add b (Num 0)) = ...
elimiZeros (Add b c ) = ...
...
avoiding most of your if
s.
Upvotes: 3
Reputation: 152837
Can't do that. Consider this instead:
data Operator = Add | Sub | Mult | Div | Power
data Exp = Num Int | Neg Exp | Bin Operator Exp Exp
Now you can write something very similar to what you tried:
elimiZeros (Bin a b c) = ...
Upvotes: 4