[q1,..,qn]的Haskell列表理解

时间:2013-10-11 22:37:35

标签: haskell range list-comprehension

有没有办法生成类似的东西:

list n = [[q1,..,qn]|q1 <- [1..5], .., qn <- [1..5]]

我有一个集合,例如[1..5]和一个数字n,它决定了我的列表工作时间。我想要的是这个长度为n的列表的列表,其中每个位置的范围超出我给定的集合。

例如:

list 2 = [[1,1],[1,2],[1,3],[1,4],[1,5],[2,1],...]

list 3 = [[1,1,1],[1,1,2]...]

1 个答案:

答案 0 :(得分:5)

如果我理解正确,你想要的是一个函数,给定n列表,它们是他们的交叉产品。例如,

cross [[1, 2, 3], [10, 20, 30]] = [[1, 10], [2, 10], [3, 10]
                                  ,[1, 20], [2, 20], [3, 20]
                                  ,[1, 30], [2, 30], [3, 30]]

有趣的是,这个函数已经存在,它被称为sequence。例如:

Prelude> sequence [[1, 2, 3]]
[[1],[2],[3]]
Prelude> sequence [[1, 2, 3], [10, 20, 30]]
[[1,10],[1,20],[1,30],[2,10],[2,20],[2,30],[3,10],[3,20],[3,30]]
Prelude> sequence [[1, 2, 3], [10, 20, 30], [100, 200, 300]]
[[1,10,100],[1,10,200],[1,10,300],[1,20,100],[1,20,200],[1,20,300],[1,30,100],[1,30,200],[1,30,300],[2,10,100],[2,10,200],[2,10,300],[2,20,100],[2,20,200],[2,20,300],[2,30,100],[2,30,200],[2,30,300],[3,10,100],[3,10,200],[3,10,300],[3,20,100],[3,20,200],[3,20,300],[3,30,100],[3,30,200],[3,30,300]]

发生了什么事?好吧,请记住,列表类型[]是一个monad,sequence的类型为sequence :: [m a] -> m [a];实际上,它使用monadic绑定结合了monadic值。如果m是列表类型,则会变为[[a]] -> [[a]]。要了解其工作原理,请考虑以下代码:

do
  a <- [1, 2, 3]
  b <- [10, 20, 30]
  return [a, b]

这相当于sequence只能为两个输入列表执行的操作。列表绑定(>>=)只是flip concatMapreturn只是将给定值包装在列表中,所以这相当于

let aList = [1, 2, 3]
    bList = [10, 20, 30]
    flippedConcatMap = flip concatMap in
  aList `flippedConcatMap` (\a -> 
    bList `flippedConcatMap` (\b -> [[a, b]]))

这实际上是一个嵌套的for循环。对于aList中的每个值,我们应用a的函数。此函数获取bList中的每个值,并应用带有b的函数,该函数仅返回具有单个元素[a, b]的列表。然后,两个“for循环”(concatMaps)获取它们生成的所有元素并将它们粘贴到一个列表中,因此所有[a, b]列表都会聚合成一个,这会产生您在评估{{{GHCi 1}}。