为什么没有<<在Haskell标准库中?

时间:2013-01-05 21:38:22

标签: haskell monads

Monad类定义了>>方法,该方法对两个monadic动作进行排序:

>> :: Monad m => m a -> m b -> m b

绑定运算符>>=具有翻转参数等价物=<<;和monadic函数组合('fish')运算符>=><=<一样。但是,似乎没有<<(在Hoogling几分钟之后)。这是为什么?

编辑:我知道这不是什么大问题。我只是喜欢使用左指向运算符看某些代码行的方式。 x <- doSomething =<< doSomethingElse只是看起来更好,箭头的方式与x <- doSomethingElse >>= doSomething相同。

2 个答案:

答案 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操作之间存在密切的联系,(<<)(<*)中的第一个变量将非常出乎意料。