表达式中的模式匹配运算符/构造函数

时间:2019-02-20 07:50:07

标签: haskell pattern-matching

我正在尝试编写一个函数,通过识别将计算为零的部分来简化表达式,以便n * 0-> 0和n + 0-> n等。

elimiZeros :: Exp -> Exp

数据类型为:

data Exp = Num Int
     | Add Exp Exp
     | Sub Exp Exp
     | Mult Exp Exp
     | Div Exp Exp
     | Power Exp Exp
     | Neg Exp
     deriving Show

为避免必须自己对每个运算符进行模式匹配,我尝试同时匹配多个运算符,但是遇到编译器错误:“模式中解析错误: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)

使用这种语法模式匹配是否可行?

编辑:感谢您的澄清答复!

2 个答案:

答案 0 :(得分:4)

不能那样做。考虑一下这个:

data Operator = Add | Sub | Mult | Div | Power
data Exp = Num Int | Neg Exp | Bin Operator Exp Exp

现在,您可以编写与尝试的内容非常相似的内容:

elimiZeros (Bin a b c) = ...

答案 1 :(得分:3)

Haskell不允许使用类似模式

f (a b c) = ...

要了解原因,请考虑以下类型:

data T = A Int Int | B Bool Bool

f :: T -> ...
f (a b c) = ...

如果允许的话,bc的类型是什么?好吧,可能是IntBool,我们不确定。因此,通常,(a b c)模式是禁止的,要求模式必须以显式构造函数开始(当然,除非模式只是变量)。

在您的代码中,您可以尝试使用多个方程式

elimiZeros (Add b (Num 0)) = ...
elimiZeros (Add b c      ) = ...
...

避免使用您的大多数if