Haskell Monadic列表操作

时间:2012-05-06 21:12:52

标签: list haskell monads

我有以下

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

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

任何人都可以解释原因吗?

3 个答案:

答案 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以确定你是对的。然后去除它,并使用等式推理来得到正确的答案。