2

我有以下

[3,2,1] >> [1]
= [1,1,1]

我不完全明白为什么会这样?查看 >> 我希望 [3,2,1] 是结果,但我发现这在列表中有所不同。

谁能解释为什么?

4

3 回答 3

14

对于任何 monad,您都可以翻译a >> ba >>= \_ -> b. 在 list 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
于 2012-05-06T21:22:17.187 回答
7

>>可以这样定义:

ma >> mb = ma >>= const mb

(这不是它在Monad实例中的实际定义 for [],但这并不重要。)

在列表情况下,对于 中的每个元素[1,2,3],您会得到[1],并且总体结果等价于concat [[1],[1],[1]],即[1,1,1]

这是[]GHC.Base 中的实例:

m >>= k             = foldr ((++) . k) [] m
m >> k              = foldr ((++) . (\ _ -> k)) [] m

我们在这里使用折叠连接左侧每个元素的右侧副本,忽略该元素可能是什么。

于 2012-05-06T21:20:31.470 回答
4

回想一下,return对于列表是\x -> [x]. 如果我根据以下方面重写您的示例,也许会更清楚return

[1,2,3] >> return 1

让我们添加一些 do 符号糖

do [1,2,3]
   return 1

你现在能看到吗?>>不会从其左参数中提取值,仅从它们周围的上下文中提取值。在这种情况下,上下文是一个 3 元素列表,或者您可以说,3 个不同的选择都是非确定性选择的。然后在每种情况下,return 1

如果你做了

do x <- [1,2,3]
   return x

那么您不是在每种情况下都选择 1 ,而是x,它代表每个“分支”的特定选择。尝试猜测这将是什么结果,然后检查 ghci 看你是否正确。然后对其进行脱糖,并使用等式推理得到正确答案。

于 2012-05-06T23:38:25.237 回答