Monad
类定义了>>
方法,该方法对两个monadic动作进行排序:
>> :: Monad m => m a -> m b -> m b
绑定运算符>>=
具有翻转参数等价物=<<
;和monadic函数组合('fish')运算符>=>
和<=<
一样。但是,似乎没有<<
(在Hoogling几分钟之后)。这是为什么?
编辑:我知道这不是什么大问题。我只是喜欢使用左指向运算符看某些代码行的方式。 x <- doSomething =<< doSomethingElse
只是看起来更好,箭头的方式与x <- doSomethingElse >>= doSomething
相同。
答案 0 :(得分:11)
据我所知,没有充分的理由。请注意,您的Monad
也应该是Applicative
的实例,因此您可以使用<*
和*>
作为您的测序工具。
答案 1 :(得分:6)
这是一个替代答案,因为最近有人问过类似的问题并将其标记为重复。事实证明, (<<)
的定义完全不清楚!虽然在较旧答案的注释中提到了这个问题,但我认为这并不是事实完全清楚这里存在一个重大问题。
很明显,定义的两个合理的可能性是:
(<<) :: Monad m => m a -> m b -> m a
p << q = do {x <- p; q; return x} -- definition #1
p << q = do {q; p} -- definition #2
与适用的运算符(<*)
和(*>)
类似,很明显,新的(<<)
运算符应保留副作用从左到右的顺序,并且仅具有切换效果使用了哪个操作的返回值,因此定义1显然是正确的。它具有理想的属性,即<<
和<*
将成为(表现良好的)单子的同义词,就像>>
和*>
的同义词一样,因此不会感到惊讶。>
当然,与=<<
和>>=
类似,很明显,翻转大于号的方向应该具有翻转参数的效果,因此定义#2显然是正确的。具有单子运算管道的理想特性:
u >>= v >>= w >> x >>= y
可以通过翻转运算符来反转:
y =<< x << w =<< v =<< u
这也保留了Kleisli运算符的身份:
(f >=> g) x === f x >>= g
(f <=< g) x === f =<< g x
看起来应该像它们应该保持的样子。
无论如何,我不知道这是否是(<<)
被遗漏的最初原因。 (可能不会,因为该决定早于引入应用运算符,因此人们将“定义#2”作为唯一可能性),但是我敢肯定,由于不同的行为,这将是目前的症结所在鉴于人们期望在应用操作和monad操作之间存在密切的联系,(<<)
和(<*)
中的第一个变量将非常出乎意料。