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

Ben*_*son 12 monads haskell

Monad类定义了一个>>方法,该方法序列的两个一元操作:

>> :: Monad m => m a -> m b -> m b
Run Code Online (Sandbox Code Playgroud)

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

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

Phi*_* JF 11

据我所知,没有充分的理由.请注意,您Monad也应该是一个实例Applicative,因此您可以使用<**>不是作为您的测序工具.

  • 但请注意,虽然`*>`相当于`>>`,但a <*b`并不等同于`b*> a`. (14认同)

K. *_*uhr 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
Run Code Online (Sandbox Code Playgroud)

与应用运算符(<*)和相似(*>),很明显,新(<<)运算符应保留副作用从左到右的顺序,并且仅具有切换使用哪个动作的返回值的效果,因此定义#1显然是正确的。它具有理想的特性,<<并且<*将成为(行为良好的)单子的同义词,正如>>*>的代名词一样,因此不会感到惊讶。

当然,通过与=<<和进行类比>>=,很明显,将大于号的方向翻转应该具有翻转自变量的效果,因此定义#2显然是正确的。这具有单子运算管道的理想特性:

u >>= v >>= w >> x >>= y
Run Code Online (Sandbox Code Playgroud)

可以通过翻转运算符来反转:

y =<< x << w =<< v =<< u
Run Code Online (Sandbox Code Playgroud)

这也保留了Kleisli运算符的身份:

(f >=> g) x  ===  f x >>= g
(f <=< g) x  ===  f =<< g x
Run Code Online (Sandbox Code Playgroud)

当然看起来他们应该坚持。

无论如何,我不知道这是否是最初的原因(<<)。(可能不会,因为该决定早于引入应用运算符,因此人们将“定义#2”作为唯一的可能性),但是我很确定这将是一个症结所在,因为不同的行为的(<<)(<*)将给予密切的关联人合用的单子和操作之间的预期是相当意外的。

  • `(&lt;*)`和`(**)`互不保留特效顺序。它们是`(&lt;*&gt;)`的变体,它们对所包含的值的合并较少。因此,第一段中的正确类比是,就像`(&gt;&gt;)`是`(&gt;&gt; =)`的变体一样,它对所包含的值的合并较少,`(&lt;&lt;)`应该是变体(= &lt;&lt;)的值,它对包含的值进行的合并较少。(没有超级组合器`&gt;&gt; = &lt;&lt;`或`(&gt;&gt;)`和`(&lt;&lt;)`都应该是变体的任何形式。)这使两个参数融​​为一体,坚定地支持了定义方面#1 (3认同)
  • @lehins是的,我检查并再次检查后仍然出错:我的评论应为“ ...肯定支持定义#2的一面。”。 (2认同)