Haskell运算符的交换属性?

Mar*_*tos 11 haskell operators pattern-matching commutativity

有没有办法说明运算符是可交换的,所以我不必为两个方向给出相同的定义?例如:

data Nat = Zero | Succ Nat

(+) :: Nat -> Nat -> Nat
Zero + x = x
x + Zero = x
...
Run Code Online (Sandbox Code Playgroud)

在这里,有没有一种方法可以让我不必同时给出这两种定义,其中一种定义会从另一种定义中暗示出来?有没有办法说明这一点fn = flip fn

Jon*_*rdy 9

这个加法运算符没有必要,但一般来说,你可以通过添加翻转参数的最终方程式来实现一个可交换的函数而不实现所有翻转的情况:

data X = A | B | C

adjacent A B = True
adjacent B C = True
adjacent A C = False
adjacent x y = adjacent y x  -- covers B A, C B, and C A
Run Code Online (Sandbox Code Playgroud)

然而,缺点是,如果您忘记处理案例,这很容易导致无限循环:

adjacent A B = True
adjacent B C = True
adjacent x y = adjacent y x
Run Code Online (Sandbox Code Playgroud)

在这里,adjacent A C会打电话adjacent C A,打电话adjacent A C,等等.和GHC的模式匹配穷举检查(-fwarn-incomplete-patterns-Wall)在这里不会帮助你.

我想你可以添加一个额外的参数来防止循环:

data Commute = Forward | Reverse

adjacent = go Forward
  where
    go _ A B = True
    go _ B C = True
    go Forward x y = go Reverse y x  -- try to commute
    go Reverse _ _ = False           -- commuting failed
Run Code Online (Sandbox Code Playgroud)

现在GHC会抱怨如果你没有添加go Reverse等式来处理你减刑的情况,但仍然没有匹配.

但我认为这只适用于具有大量案例的函数 - 否则,简单地枚举它们就更清楚了.