Haskell のモナドの >> 演算子は、しばしば次のように定義されます。
(>>) :: m a -> m b -> m b
a >> b = a >>= \_ -> b
のようなものを印刷するために使用できます。
main = putStr "foo" >> putStrLn "bar"
コンパイラが の値を最適化せずputStr "foo"、単に評価しないのはなぜputStrLn "bar"ですか? それは必要ないのに、なぜそれを計算するのですか?
Haskell のモナドの >> 演算子は、しばしば次のように定義されます。
(>>) :: m a -> m b -> m b
a >> b = a >>= \_ -> b
のようなものを印刷するために使用できます。
main = putStr "foo" >> putStrLn "bar"
コンパイラが の値を最適化せずputStr "foo"、単に評価しないのはなぜputStrLn "bar"ですか? それは必要ないのに、なぜそれを計算するのですか?
クリスが言ったように、それはモナドに依存します。Identityorは、結果の計算に必要ないため、Readerの前の部分を評価しません。、、、またはwill>>のような他のモナド。WriterMaybeEitherStateIO
Maybe例として挙げてみましょう。>>=と定義されている
Nothing >>= _ = Nothing
(Just x) >>= f = f x
したがって、展開する>>と、
Nothing >> _ = Nothing
(Just x) >> y = y
そのため、結果が または になるかどうかを確認するためMaybeに、 の前にあるものを評価する必要があります。>>Nothingy
IO結果が必要かどうかにかかわらず、アクションが評価されるように意図的に定義されています (そうでなければ、使用することは不可能です)。
は?もちろん、 の値が必要ですputStr "foo"。モナド>>=をアクションと考えたい場合は、アクション自体ではなく、アクションの結果のみが破棄されます。
たとえば、パーサーでは、解析されたばかりのシーケンスを破棄することを意味しますが、まだ解析されているため、カーソルはまだ前方に移動しています。
それはモナドに依存します。IO では評価されます。Identity では、最初のものは評価されません。
> import Control.Monad.Identity
> import Control.Monad.Trace
> let x = trace "x" $ return () :: Identity ()
> let y = trace "y" $ return () :: Identity ()
> runIdentity $ x >> y
y
()