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

haskell,monad,绑定的定义,以及输出值上奇怪的模式匹配?,haskell,pattern-matching,bind,monads,Haskell,Pattern Matching,Bind,Monads,下面是来自的答案的一些代码。我已经开始研究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 _ =

下面是来自的答案的一些代码。我已经开始研究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
我花了半个小时试图理解它的含义,或者如果我已经知道的东西解释了这个bind(>>=)方法的定义。GHCI加载它时没有烦恼(它需要一个应用程序实例,但除此之外),所以它必须是非常允许的,即使我还没有理解它的开始

对已经定义的数据构造函数进行模式匹配定义的含义是什么?x和y是什么,它们来自哪里

感谢所有回答这个问题的人。如果有人对这个问题有一个好的、具体的标题有好主意的话——考虑到我真的不理解语法意义,我很难找到一个


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

P x y
  where P x _ = f a
        P _ y = f b
是一种“值取消装箱”类型的模式匹配形式,而不是类似于面向选择的模式匹配。我被
\uuu
模式的存在所迷惑,因此我没有看到上面两种模式的匹配,也就是说,作为
x
然后
y
的定义,因为它是以我以前从未见过的方式完成的

我知道我们可以写这样的东西:

f :: foo -> (Int, Int)
...
i = let (a,b) = f x
    in a + b
但我不知道,在这些“值取消绑定”的情况下(例如,这里是
a
b
,或者是在困扰我的代码中是
x
y
),我们可以充分利用模式匹配的可能性,也就是说,至少定义使用
来隔离我们不想要的部分,我们不希望绑定到任何“标签”的值

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

P x _ = f a
实际上是通过对
(f a)
结果的模式匹配来定义
x
,因此它在效果上严格等同于

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

我一直认为这是已经定义的数据构造函数的定义,这里没有“特定语法”,只有正常的模式匹配。代码相当于

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
如果您内联
pFst
pSnd
,您会看到这直接导致原始定义

如果您不信服,请考虑(非递归)<代码>,其中绑定可以用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
这显然是†没有以任何方式重新定义
(,)
构造函数,只是使用它对函数的元组结果进行模式匹配



†嗯,好吧,也许这不是很明显,因为你也可以做一些事情,比如
让1+2=4乘1+2
,然后得到
4

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

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
如果您内联
pFst
pSnd
,您会看到这直接导致原始定义

如果您不信服,请考虑(非递归)<代码>,其中绑定可以用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
这显然是†没有以任何方式重新定义
(,)
构造函数,只是使用它对函数的元组结果进行模式匹配



†好吧,好吧,也许这并不那么明显,因为你也可以做类似于
的事情,让1+2=4在1+2
中,得到
4

好吧
p
确实是
对的构造函数,所以
a
b
将是这对(有点奇怪)的第一和第二个元素(如果你说
x=p12
an do
x>>=f
,那么这里是
a=1
b=2
——这就是模式匹配

我的猜测是,您对函数的定义有问题。如果有帮助,您可以将其编写为:

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


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

那么
p
确实是
对的构造函数,因此
a
b
将是这对(有点奇怪)的第一个和第二个元素(如果你说
x=p12
an do
x>>=f
,那么这里是
a=1
b=2
——这就是模式匹配

我的猜测是,您对函数的定义有问题。如果有帮助,您可以将其编写为:

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


请看:正如你可以在参数之间使用运算符那样,你可以在那里定义它吗?如果我正确地翻译它,这意味着,显然,一个人可以反向模式匹配,用相同模式的变量定义模式的一部分,所以我可以写:
let(a,)=(1,2);(,b)=(3,4)in(a,b)=(1,4)
。这种通过连续的“部分”模式匹配来定义值的能力,从其他变量中提取位,我只是忽略了这一点。基本上,我在没有
\uu
的情况下就知道了它,当然除了定义函数时,但在这里它隐含着完全不同,你不认为吗?顺便说一句,你写了
pFst(Pair\uy)=y
但是我们是复制粘贴十六进制的受害者,因为它应该是
pSnd
。当然,谢谢。我试图编辑我以前的评论,但被拒绝了。我是SOverflow的新手,现在问题解决了,我需要做些特别的事情吗?Comme