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"
ですか? それは必要ないのに、なぜそれを計算するのですか?
クリスが言ったように、それはモナドに依存します。Identity
orは、結果の計算に必要ないため、Reader
の前の部分を評価しません。、、、またはwill>>
のような他のモナド。Writer
Maybe
Either
State
IO
Maybe
例として挙げてみましょう。>>=
と定義されている
Nothing >>= _ = Nothing
(Just x) >>= f = f x
したがって、展開する>>
と、
Nothing >> _ = Nothing
(Just x) >> y = y
そのため、結果が または になるかどうかを確認するためMaybe
に、 の前にあるものを評価する必要があります。>>
Nothing
y
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
()