【问题标题】:Pattern matching operator/constructor in expression表达式中的模式匹配运算符/构造函数
【发布时间】:2019-02-20 23:38:24
【问题描述】:

我正在尝试编写一个函数来简化表达式,方法是识别将计算为零的部分,以便 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)

难道不能用这种语法进行模式匹配吗?

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

【问题讨论】:

  • 这不是模式匹配的工作原理——您只能针对构造函数执行此操作,并且不能如您在此处看到的那样使用变量来代表构造函数。也许有一个语言扩展允许这样做,如果我不知道的话。但我没有看到您实际上按照自己的方式编写的代码更少——而且我发现与标准方式相比,它的可读性更低。

标签: haskell pattern-matching


【解决方案1】:

不能这样做。请考虑一下:

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

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

elimiZeros (Bin a b c) = ...

【讨论】:

    【解决方案2】:

    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      ) = ...
    ...
    

    避免大部分ifs。

    【讨论】:

    • 可能(`Int` or `Bool`)。但是那or 会是什么?...在​​什么类型系统中?...关于 Haskell 的第一件事是,它希望提前完全了解它的类型。这很难让外人知道,尤其是。来自动态语言,尤其是。它从未真正说过。(至少我没有看到它)。
    • @WillNess 确实如此。一些类型系统允许像Int or Bool 这样的“联合类型”,但它们使用起来非常复杂(在类型检查/类型推断中)。在 Haskell 中,没有真正需要使用它。 AFAIK,mypy 确实使用联合类型,取得了一些成功,但类型推断(总体上)比 Haskell 更简单。
    猜你喜欢
    • 1970-01-01
    • 2012-04-29
    • 1970-01-01
    • 1970-01-01
    • 2021-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-06
    相关资源
    最近更新 更多