23

私は困惑しています。私はこれを書くことができます:

import Control.Monad

main = print $ head $ (foldr (.) id [f, g]) [3]
  where f = (1:)
        g = undefined

出力は1です。それは次のように還元されるため、理にかなっています。

main = print $ head $ ((1:) . undefined . id) [3]
main = print $ head $ (1:) ((undefined . id) [3])
main = print $ head $ 1 : ((undefined . id) [3])
main = print $ 1

しかし、漠然と似たモナド手法を使用すると、同じようには機能しません。

import Control.Monad

main = print $ (foldr (<=<) return [f, g]) 3
  where f = const Nothing
        g = undefined

これは当たりprelude.Undefinedます。私はそれが減少すると予想するので、これは奇妙です:

main = print $ ((const Nothing) <=< undefined <=< return) 3
main = print $ return 3 >>= undefined >>= (\_ -> Nothing)
main = print $ Nothing -- nope! instead, undefined makes this blow up

ただし、構成の順序を反転します。

import Control.Monad

main = print $ (foldr (>=>) return [f, g]) 3
  where f = const Nothing
        g = undefined

予想される短絡を達成し、生成しNothingます。

main = print $ (const Nothing >=> undefined >=> return) 3
main = print $ (const Nothing 3) >>= undefined >>= return
main = print $ Nothing >>= undefined >>= return
main = print $ Nothing

2 つのアプローチを比較すると、リンゴとオレンジを比較することになると思いますが、その違いを説明していただけますか? f <=< gこれは のモナド類似体だと思っていましたが、思ったf . gほど類似していないようです。理由を説明できますか?

4

2 に答える 2

21

どのモナドを扱っているか、およびその(>>=)演算子がどのように定義されているかによって異なります。

の場合、Maybeダニエル(>>=)・フィッシャーが説明したように、最初の引数は正格です。

以下は、他のいくつかのモナドの結果です。

> :set -XNoMonomorphismRestriction
> let foo = (const (return 42) <=< undefined <=< return) 3
> :t foo
foo :: (Num t, Monad m) => m t

アイデンティティ:怠け者。

> Control.Monad.Identity.runIdentity foo
42

IO:厳密です。

> foo :: IO Integer
*** Exception: Prelude.undefined

読者:怠け者。

> Control.Monad.Reader.runReader foo "bar"
42

Writer:遅延バリアントと厳密バリアントの両方があります。

> Control.Monad.Writer.runWriter foo
(42,())
> Control.Monad.Writer.Strict.runWriter foo
*** Exception: Prelude.undefined

状態:厳密なバージョンと遅延バージョンの両方があります。

> Control.Monad.State.runState foo "bar"
(42,"*** Exception: Prelude.undefined
> Control.Monad.State.Strict.runState foo "bar"
*** Exception: Prelude.undefined

続き:厳しい。

> Control.Monad.Cont.runCont foo id
*** Exception: Prelude.undefined
于 2011-11-23T23:10:47.710 に答える
19

Maybe最初の引数のバインドは厳密です。

Just v >>= f = f v
Nothing >>= f = Nothing

だからあなたがしようとすると

Just v >>= undefined >>= \_ -> Nothing

あなたがヒット

undefined v >>= \_ -> Nothing

そして、実装は、使用する方程式であるundefined vかどうNothingかを確認する必要があります。Just something(>>=)

一方で、

Nothing >>= undefined

の2番目の引数を見ずに結果を決定します(>>=)

于 2011-11-23T22:47:38.893 に答える