为什么没有>>只有3在Haskell中什么都没有?

时间:2014-04-17 18:09:48

标签: haskell monads

Haskell中>>函数的签名是这样的:

(>>) :: m a -> m b -> m b

默认实现是:

x >> y = x >>= \_ -> y

据我所知,>>函数总是返回其右参数,而不管左边的值是什么。 lambda甚至不关心左参数(x)的值是什么。那么,为什么Nothing >> Just 3等于Nothing?不应该只返回Just 3,因为这是右边的参数的值吗?

我知道,当与Just相关联时,任何Nothing值都会返回Nothing,但在这种情况下,Nothing甚至不被lambda捕获。我错过了什么?

奖金问题,>>=被称为绑定。什么是>>

感谢。

5 个答案:

答案 0 :(得分:13)

因为绑定甚至不关心lambda的值是什么!

Just x  >>= f = f x
Nothing >>= _ = Nothing

请注意(Nothing >>=)不评估其第二个参数。

答案 1 :(得分:6)

要真正理解(>>)在这种情况下的作用,您必须查看the definition of (>>=) for Maybe

(Just x) >>= k      = k x
Nothing  >>= _      = Nothing
无论Nothing >>= k函数是什么,

Nothing都会评估为k。在(>>)的特定情况下,k恰好是\_ -> y

答案 2 :(得分:3)

  
    

据此,我明白>>函数总是返回其正确的参数,而不管左边的值

  

这是你混乱的根源!

m >>= f调用f来查找"在"内找到的值m,"合并"结果(对于值是什么意味着什么"在内部找到" monadic值以及它意味着"结合"是monad特定的。)

m >> n必须等同于m >>= \_ -> n。因此,对于它在m中找到的每个值,它将在其上调用\_ -> n。但Nothing monad中的Maybe并没有任何值"内部"它。因此,\_ -> n甚至无法对任何内容进行调用,以便忽略它并返回n!因此,Nothing >>= \_ -> n必须返回不依赖n的内容,因为它无法调用函数来获取n。在此上下文中,还没有任何包装类型的值浮动,因此唯一可用的选项只是Nothing

因此,而不是你理解>>的直觉,它忽略了左边并返回右边的内容,最好认为它需要" monadic结构和" monadic结构& #34;左边的是什么&与右边的monadic值绑定。 " Monadic结构"是一个手动的术语,用于定义除其内部值之外的monadic值的所有内容"。

无论listA >> listB中的具体值如何,

listA都会做同样的事情,但重要的是它中包含多少元素。无论执行ioA >> ioB产生什么价值,ioA都会做同样的事情,但重要的是产生副作用。 stateA >> stateB忽略stateA生成的值,但会将当前状态发送到stateB。无论maybeA >> maybeB中的具体值如何,maybeA都会做同样的事情,但重要的是否有值。请注意,列表案例的行为与Maybe非常相似;如果listA 为空,则listA >> listB也必须为空。

至于你的奖金问题,当我自己阅读代码(在我脑海中)时,我倾向于将>>=>>都发音为" bind&#34 ;;当我在代码中查看以及在那里发表语言时,对语境的非语言意识就足够了,这种歧义并不重要。我实际上不知道我会说些什么来与>>=>>的人大声说话;也许"绑定"和"健忘的绑定"?

答案 3 :(得分:2)

我认为有两种方法可以解释这种选择。

  1. 你诉诸于,例如,与IO不同,可能没有副作用。否则不评估第二个参数是没有意义的。在这种观点中,从逻辑的角度来看,它似乎是一种随意的选择,尽管它可能更有效,如果可能出乎意料的话。

  2. 你使Nothing代表一个错误。然后第一个参数中的错误将消除评估第二个参数的需要。这似乎是作者选择的理由:

  3. http://hackage.haskell.org/package/base-4.7.0.0/docs/src/Data-Maybe.html#Maybe

    -- The 'Maybe' type is also a monad.  It is a simple kind of error
    -- monad, where all errors are represented by 'Nothing'.
    

答案 4 :(得分:1)

我想在其他好的答案中添加一些内容。

  1. Nothing >>= f必须为Nothing的原因是因为无法检查f是否实际使用了其参数(至少没有可怕的不安全黑客攻击)。

  2. x >> y = x >>= \_ -> y不仅仅是默认实现。 >>的定义应始终产生与此相同的结果。它只允许过载,因为它有时可以更有效地实现。