我想我确实了解列表monad,但后来发现我不是。这是故事。
给定列表m
和函数k
> let m = [1..10]
> :t m
m :: [Integer]
> let k = replicate 2
> :t k
k :: a -> [a]
玩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]
但是对于
>>
预期的(通过IO monad的体验,左侧的所有内容都将被丢弃)
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
请解释为什么
>>
的行为不符合我的预期(当然我一定会有误会),解释>>
的正确方法是什么? 最佳答案
(>>)
放弃其第一个参数的值,但不放弃效果。在这种情况下,查看是否使用不同类型的列表可能会更容易:
λ> "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”。右边的函数将左边的每个值作为参数。因此(>>)
(丢弃值)仍然表示“为每个值”,但这一次它不能使用该值,因此它的意思是“第二个列表中的元素,重复的次数与第一个列表中的元素重复的次数”。关于list - 是否应该(>>)丢弃所有左侧输出?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14953032/