haskell、monad、绑定的定义以及输出值上的奇怪模式匹配?

haskell, monad, definition of bind, and weird pattern matching on an output value?

下面是来自 another stack overflow question 答案的一些代码。我已经开始研究 Haskell 好几个星期了,但我还没有遇到这种特殊的语法,而且我找不到任何解释,甚至连定义都找不到。 所以,代码:

data Pair a = P a a

instance Functor Pair where
  fmap f (P x y) = P (f x) (f y)

instance Monad Pair where
  return x = P x x
  P a b >>= f = P x y
     where P x _ = f a
           P _ y = f b

我花了最后 half-hour 试图理解它的含义,或者如果我已经知道的东西解释了这个绑定 (>>=) 方法的定义。 GHCI 毫不费力地加载了它(好吧,它需要一个 Applicative 实例,但除此之外),所以它必须是非常允许的,即使我还没有理解它的开头。

看起来像 pattern-matching 定义的已定义数据构造函数的含义是什么? x和y是什么,它们从哪里来?

感谢所有回答此问题的人。如果有人对这个问题有一个好的、具体的标题的好主意——鉴于我真的不明白语法的含义,我很难找到一个。


@leftaroundabout 给了我需要的信息,就是那段代码

P x y
  where P x _ = f a
        P _ y = f b

是 "value-unboxing" 类型的 pattern-matching 的一种形式,而不是类似于 case of 的 choice-oriented 类型。我对 _ 模式的存在感到困惑,因此我没有看到上面两个 pattern-matching 的原样,即 x 然后 [= 的定义19=], 因为它是以我以前从未见过的方式完成的。

我知道我们可以这样写:

f :: foo -> (Int, Int)
...
i = let (a,b) = f x
    in a + b

但我不知道我们可以在 "value-unboxing" 的这些情况下使用(例如这里 ab,或者 xy 在困扰我的代码中),pattern-matching 中可能性的全部范围,也就是说,至少,定义使用 _ 来隔离我们不想要的部分,我们不想要的值'不想绑定到任何 "label".

总之我不知道在上面的例子中,这个等式

P x _ = f a

实际上是 x 到 pattern-matching 在 (f a) 的结果上的定义,因此它在效果上严格等同于

x = g (f a)
  where g (P t _) = t

我一直以为这是 already-defined 数据构造函数的定义 P

这里没有“特定语法”,只是一个普通的模式匹配。代码相当于

pFst, pSnd :: Pair a -> a
pFst (Pair x _) = x
pSnd (Pair _ y) = y

instance Monad Pair where
  return x = P x x
  P a b >>= f = P x y
     where x = pFst $ f a
           y = pSnd $ f b

如果您内联 pFstpSnd,您会发现这直接导致原始定义。

如果您不信服,请考虑(非递归)where 绑定可以替换为 lambda 抽象:

  P a b >>= f = (\(Pair x _) (Pair _ y) -> P x y)
                  (f a)      (f b)

显然,lambda 也可以写成命名的局部函数:

  P a b >>= f = pFstAndPSnd (f a) (f b)
   where pFstAndPSnd (Pair x _) (Pair _ y) = P x y

如果您看到了寻找普通元组的代码,也许就不会那么混乱了:

(>>=) :: (c,c) -> (c -> (d,d)) -> (d,d)
(a,b) >>= f = (x,y)
  where (x,_) = f a
        (_,y) = f b

显然 没有以任何方式重新定义 (,) 构造函数,只是用它来进行模式匹配函数的元组结果。


好吧,好吧,也许 不那么明显,因为你也可以做类似 let 1+2=4 in 1+2,得到4作为结果。

P 确实是 Pair 的构造函数所以 ab 将是这个的第一个和第二个元素(有点奇怪) pair(如果你说 x = P 1 2 然后做 x >>= f 那么这里 a = 1b = 2 - 这正是 模式匹配

我猜你在定义函数时遇到了问题。如果有帮助你可以写成:

(>>=) (P a b) f = P x y
    where ...

也是

请参阅:正如您可以在参数之间使用运算符一样,您可以在那里定义它吗