Haskell中>>
函数的签名是这样的:
(>>) :: m a -> m b -> m b
默认实现是:
x >> y = x >>= \_ -> y
据我所知,>>
函数总是返回其右参数,而不管左边的值是什么。 lambda甚至不关心左参数(x)的值是什么。那么,为什么Nothing >> Just 3
等于Nothing
?不应该只返回Just 3
,因为这是右边的参数的值吗?
我知道,当与Just
相关联时,任何Nothing
值都会返回Nothing
,但在这种情况下,Nothing
甚至不被lambda捕获。我错过了什么?
奖金问题,>>=
被称为绑定。什么是>>
?
感谢。
答案 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)
我认为有两种方法可以解释这种选择。
你诉诸于,例如,与IO不同,可能没有副作用。否则不评估第二个参数是没有意义的。在这种观点中,从逻辑的角度来看,它似乎是一种随意的选择,尽管它可能更有效,如果可能出乎意料的话。
你使Nothing代表一个错误。然后第一个参数中的错误将消除评估第二个参数的需要。这似乎是作者选择的理由:
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)
我想在其他好的答案中添加一些内容。
Nothing >>= f
必须为Nothing
的原因是因为无法检查f
是否实际使用了其参数(至少没有可怕的不安全黑客攻击)。
x >> y = x >>= \_ -> y
不仅仅是默认实现。 >>
的定义应始终产生与此相同的结果。它只允许过载,因为它有时可以更有效地实现。