2011-11-23 15 views
22

私は困惑しています。私はこれを書くことができます:折り畳み、機能構成、モナド、そして怠惰、ああ、私?

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 <=< gf . gのモナド類似体だと思ったが、明らかに彼らは私が思ったように類似していなかった。なぜ説明できますか?

答えて

20

これは、使用しているモナドとその演算子がどのように定義されているかによって異なります。

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 

脚本:は怠け者と厳格な変種の両方を持っています。

> 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 
19

Maybeのバインドは第1引数で厳密です。あなたは

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

をしようとすると、

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

は、だから、

undefined v >>= \_ -> Nothing 

を押すと、実装がundefined vを使用する(>>=)のどの式を参照するNothingJust somethingであるかどうかを確認する必要があります。一方

Nothing >>= undefined 

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

関連する問題