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

なぜ>>私が期待したように振る舞わないのか説明してください(もちろん誤解があるに違いありません)、正しい解釈方法は何>>ですか?

4

2 に答える 2

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番目のリストの要素」を意味します。 。

于 2013-02-19T09:03:00.793 に答える
12

foo >> barと同じfoo >>= \_ -> barです。したがって、IO の場合、そのアクションの戻り値を無視して左のアクションを実行し、次に右のアクションを実行します。リストの場合、各要素の値を無視して左側のリストの各要素にマップし、各ポイントに右側のリストを挿入します。

別の見方をすると、>>=for リストは と同じでflip concatMap>>は と同じflip (concatMap . const)です。

于 2013-02-19T09:01:28.527 に答える