Bjørn
Bjørn

Reputation: 13

Pattern matching operator/constructor in expression

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

Answers (2)

chi
chi

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 ifs.

Upvotes: 3

Daniel Wagner
Daniel Wagner

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

Related Questions