同様の質問が最近尋ねられ、重複をマークしたので、これは別の答えです。の定義がどうあるべきかはまったく明確ではないことがわかりました(<<)
! この問題は以前の回答へのコメントでほのめかされていましたが、ここに重大な問題があることが完全に明らかにされたとは思いません。
明らかに、定義の2つの合理的な可能性は次のとおりです。
(<<) :: 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演算子のIDも保持されます。
(f >=> g) x === f x >>= g
(f <=< g) x === f =<< g x
それは確かに彼らが保持すべきであるように見えます。
(<<)
とにかく、これが本来の理由が抜けていたのかどうかはわかりません。(おそらくそうではないでしょう、決定は適用可能な演算子の導入よりも前だったので、人々は「定義#2」を唯一の可能性として想定したでしょう)、しかし私はそれが別の振る舞いとして今のこだわりになると確信しています人々がアプリケーション操作とモナド操作の間に期待する密接な関係を考えると、これはまったく予想外のことです(<<)
。(<*)