为什么在列表列表中应用`sequence`会导致其笛卡尔积的计算?

时间:2011-03-14 13:37:24

标签: haskell functional-programming monads cartesian-product

我的问题是关于sequence中的Prelude函数,其签名如下:

sequence :: Monad m => [m a] -> m [a]

我了解此功能对List Maybe的效果如何。例如,在sequence上应用[Just 3, Just 9]会产生Just [3, 9]

我注意到在sequence的{​​{1}}上应用List会给出其笛卡尔积。有人可以帮我理解这是怎么回事?为什么会这样?

3 个答案:

答案 0 :(得分:31)

这很有效,因为在Haskell中使用列表作为monad会使它们成为模型的不确定性。考虑:

sequence [[1,2],[3,4]]

根据定义,它与:

相同
do x <- [1,2]
   y <- [3,4]
   return [x,y]

只需将其读作“首先选择1和2之间,然后选择3到4”。列表monad现在将累积所有可能的结果 - 因此答案[[1,3],[1,4],[2,3],[2,4]]

(对于更加模糊的例子,请参阅here

答案 1 :(得分:20)

sequence的行为就好像是这样定义的。

sequence [] = return []
sequence (m:ms) = do
    x <- m
    xs <- sequence ms
    return (x:xs)

(或sequence = foldr (liftM2 (:)) (return []),但无论如何......)

考虑一下应用于列表列表时会发生什么。

sequence [] = [[]]
sequence (list : lists) =
    [ x : xs
    | x <- list
    , xs <- sequence lists
    ]

答案 2 :(得分:2)

只是为了解释一下,为什么将序列应用到列表列表与序列应用到Maybe-values列表有很大不同:

当您将sequence应用于列表列表时,序列类型将专门用于

sequence :: Monad m => [m a] -> m [a]

to(类型构造函数m设置为[])

sequence :: [[] a] -> [] [a] 

(与sequence :: [[a]] -> [[a]]相同)

在内部,序列使用(&gt;&gt; =) - 即monadic绑定函数。对于列表,这个绑定函数的实现完全不同于m设置为Maybe!