2013-02-19 5 views
12

私はのリストのモナドを理解していると思うが、私はそうでないと分かった。ここに物語があります。私は何を期待与えるバインド>>=と遊ぶ(>>)はすべての左側の出力を破棄しますか?

与えられたリストmと機能k

> let m = [1..10] 
> :t m 
m :: [Integer] 

> let k = replicate 2 
> :t k 
k :: a -> [a] 

> :t (>>=) 
(>>=) :: Monad m => m a -> (a -> m b) -> m b 
> :t m >>= k 
m >>= k :: [Integer] 
> m >>= k 
[1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10] 

が、左に>>

のためのIOモナド、すべてを経験してから(期待側は捨てられる)

m >> m 
[1,2,3,4,5,6,7,8,9,10] 

ガット

> :t (>>) 
(>>) :: Monad m => m a -> m b -> m b 
:t m >> m 
m >> m :: [Integer] 
> m >> m 
[1,2,3,4,5,6,7,8,9,10,1,2,3,4,5 ... 9,10] -- truncated, real output is 100 elements 

私は期待のよう>>が振る舞うされていません(もちろん、私は誤解を持っている必要があります)と>>を解釈するための正しい方法は何である理由を説明してください?

答えて

25

(>>)破棄最初の引数からのものですが、影響はありません。この場合、異なるタイプのリストを使用するかどうかを確認する方が簡単です。

λ> "ab" >> [1,2,3,4] 
[1,2,3,4,1,2,3,4] 

最初のリストの値がどのように使用されないか注意してください。

(>>)の定義を覚えています:a >> b = a >>= (\_ -> b)。したがって、これは"ab" >>= (\_ -> [1,2,3,4])になります。すなわち、concat (map (\_ -> [1,2,3,4]) ['a','b'])、つまりconcat [[1,2,3,4],[1,2,3,4]](また、[i | _ <- "ab", i <- [1,2,3,4]])となります。

[]の場合、(>>=)は「それぞれの」のような意味です。右の関数は、左の各値を引数として取ります。したがって、値を破棄する(>>)は、それぞれ "for each"を意味しますが、今度は値を使うことはできませんので、最初のリストに要素があるように何度も繰り返される2番目のリストの要素"

+0

うわー!どのような明確な(そして非常に速い)答え。ありがとう – wizzup

12

foo >> barは、と同じです。したがって、IOの場合は、左のアクションを実行し、そのアクションの戻り値を無視してから、正しいアクションを実行します。リストの場合は、左のリストの各要素をマップし、各要素の値は無視し、各点に右のリストを挿入します。それを見て

もう一つの方法は、リストの>>=flip concatMapと同じであり、>>flip (concatMap . const)と同じであるということです。

+0

ありがとう、私は1つの受け入れられた答えだけを選ぶことができる悪い。 – wizzup

関連する問題