我有以下
[3,2,1] >> [1]
= [1,1,1]
我完全不明白为什么会这样?看看>>我希望[3,2,1]成为结果,但我看到这在列表上有所不同。
任何人都可以解释原因吗?
答案 0 :(得分:14)
对于任何monad,您都可以将a >> b
翻译为a >>= \_ -> b
。在列表monad中,绑定运算符(>>=)
为concatMap
,其参数被翻转,因此您的示例等效于
concatMap (\_ -> [1]) [3, 2, 1]
你可以这样评价。
concatMap (\_ -> [1]) [3, 2, 1]
= concat (map (\_ -> [1]) [3, 2, 1]) -- definition of concatMap
= concat [[1], [1], [1]] -- apply map
= [1, 1, 1] -- apply concat
答案 1 :(得分:7)
>>
可以这样定义:
ma >> mb = ma >>= const mb
(这不是Monad
实例[]
中的实际定义,但这无关紧要。)
在列表案例中,对于[1,2,3]
中的每个元素,您获得[1]
,整体结果等同于concat [[1],[1],[1]]
,即[1,1,1]
。
这是GHC.Base中[]
的实例:
m >>= k = foldr ((++) . k) [] m
m >> k = foldr ((++) . (\ _ -> k)) [] m
我们在这里使用折叠,左侧的每个元素的右侧的一个副本连接,忽略该元素可能是什么。
答案 2 :(得分:4)
回想一下,return
列表是\x -> [x]
。如果我用return
[1,2,3] >> return 1
让我们添加一些做符号糖
do [1,2,3]
return 1
你能看到吗? >>
不会从左边的参数中提取值,只包含围绕它们的上下文。在这种情况下,上下文是一个3元素列表,或者您可能会说,3个不同的选择都是非确定性地选择的。然后在每种情况下,return 1
。
如果您已经完成了
do x <- [1,2,3]
return x
然后你不在每种情况下选择1,但是x
,它代表每个“分支”的特定选择。试着猜猜结果是什么,然后检查ghci以确定你是对的。然后去除它,并使用等式推理来得到正确的答案。