简体   繁体   English

是(>>)应该丢弃所有左侧输出?

[英]Is (>>) supposed to discard all left-side output?

I think I do understand the list monad but then I found I am not. 我想我确实理解monad列表然后我发现我不是。 Here is the story. 这是故事。

Given list m and function k 给定列表m和函数k

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

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

Playing with bind >>= give what I expect 玩绑定>>=给出我期望的

> :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]

but for >> 但是对于>>

Expected (from experiencing with IO monad, everything on left side would be discarded) 预期(从IO monad体验,左侧的所有内容都将被丢弃)

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

Got 得到

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

Please explain why >> is not behave like I expected (of course I must have misunderstanding) and what is the correct way to interpret >> ? 请解释为何>>没有表现得像我预期(当然我必须有误解),什么是解释正确的方法>>

(>>) discards values from its first argument, but not effects. (>>)丢弃第一个参数的 ,但不丢弃效果。 In this case it might be easier to see if you use lists with different types: 在这种情况下,可能更容易看到您是否使用不同类型的列表:

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

Note how the values of the first list aren't used at all. 请注意如何根本不使用第一个列表的值。

Remember the definition of (>>) : a >> b = a >>= (\\_ -> b) . 记住(>>)的定义: a >> b = a >>= (\\_ -> b) So this turns into "ab" >>= (\\_ -> [1,2,3,4]) , ie concat (map (\\_ -> [1,2,3,4]) ['a','b']) , ie concat [[1,2,3,4],[1,2,3,4]] (also, [i | _ <- "ab", i <- [1,2,3,4]] ). 所以这变成了"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]] )。

With [] , (>>=) means something like "for each". 使用[](>>=)表示“for each”。 The function on the right gets as an argument each value on the left. 右边的函数作为参数得到左边的每个值。 So (>>) , which discards values, still means "for each" -- but this time it can't use the value, so it just means "the elements of the second list, repeated as many times as there are elements in the first list". 所以(>>) ,丢弃值,仍然意味着“为每个” - 但这次它不能使用该值,所以它只是意味着“第二个列表的元素,重复的次数与第一个清单“。

foo >> bar is the same as foo >>= \\_ -> bar . foo >> barfoo >>= \\_ -> bar So in the case of IO it executes the left action, ignoring the return value of that action, and then executes the right action. 因此,在IO的情况下,它执行左操作,忽略该操作的返回值,然后执行正确的操作。 In the case of lists it maps over each element in the left list, ignoring the value of each elements, and inserts the right list at each point. 在列表的情况下,它映射左侧列表中的每个元素,忽略每个元素的值,并在每个点插入右侧列表。

Another way to look at it is that >>= for lists is the same as flip concatMap , >> is the same as flip (concatMap . const) . 另一种看待它的方法是>>= for lists与flip concatMap相同, >>flip (concatMap . const)相同flip (concatMap . const)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM