wiz*_*zup 12 monads haskell list
我想我确实理解monad列表然后我发现我不是.这是故事.
给出列表m和功能k
> let m = [1..10]
> :t m
m :: [Integer]
> let k = replicate 2
> :t k
k :: a -> [a]
Run Code Online (Sandbox Code Playgroud)
玩bind >>=会给我的期望
> :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]
Run Code Online (Sandbox Code Playgroud)
但对于 >>
预期(从IO monad体验,左侧的所有内容都将被丢弃)
m >> m
[1,2,3,4,5,6,7,8,9,10]
Run Code Online (Sandbox Code Playgroud)
拿到
> :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
Run Code Online (Sandbox Code Playgroud)
请解释为什么>>表现不像我预期的那样(当然我必须有误解)以及解释的正确方法是>>什么?
sha*_*haf 25
(>>)从第一个参数中丢弃值,但不丢弃效果.在这种情况下,可能更容易看到您是否使用不同类型的列表:
?> "ab" >> [1,2,3,4]
[1,2,3,4,1,2,3,4]
Run Code Online (Sandbox Code Playgroud)
请注意如何根本不使用第一个列表的值.
记住:的定义(>>):a >> b = a >>= (\_ -> b).所以这变成了"ab" >>= (\_ -> [1,2,3,4]),即concat (map (\_ -> [1,2,3,4]) ['a','b'])ie concat [[1,2,3,4],[1,2,3,4]](也[i | _ <- "ab", i <- [1,2,3,4]]).
用[],(>>=)意味着"为每个人".右边的函数作为参数得到左边的每个值.因此(>>),丢弃值仍然意味着"为每个" - 但这次它不能使用该值,所以它只是意味着"第二个列表的元素,重复次数与第一个列表中的元素一样多" .
sep*_*p2k 12
foo >> bar是一样的foo >>= \_ -> bar.因此,在IO的情况下,它执行左操作,忽略该操作的返回值,然后执行正确的操作.在列表的情况下,它映射左侧列表中的每个元素,忽略每个元素的值,并在每个点插入右侧列表.
另一种看待它的方法是,>>=对于列表是相同的flip concatMap,>>是相同的flip (concatMap . const).