Haskell - 列表列表中的元素组合列表

Haskell - List of combinations of elements from list of lists

假设我有一些列表列表 [[a, b], [c], [d, e, f], ...],其中列表中的列表可以是任意长度。我已经对列表进行排序,使最短的列表排在第一位,并且我想生成列表中所有元素组合的列表,以便我得到一个列表 [[a, c, d, ...], [a, c, e, ...], [a, c, f, ...], [b, c, d, ...], ...],即组合是通过更改元素生成的首先从最后的列表中选择,向上移动列表以更改类似于计数的元素。

使用这个列表,我将让列表的头部使用惰性求值,因为我只需要 1 个满足谓词的列表。如何生成列表?

是的,这是sequenceA :: (Applicative f, Traversable t) => t (f a) -> f (t a)的特例:

Prelude> sequenceA ["ab", "c", "def"]
["acd","ace","acf","bcd","bce","bcf"]

这里以f ~ []t ~ []a ~ Char为例。 SequenceA 在这里等同于:

-- sequenceA for f ~ [] and t ~ []
sequenceAList [] = [[]]
sequenceAList (c:cs) = (:) <$> c <*> sequenceAList cs

对于单个项目 sequenceA ["def"] 因此等同于:

sequenceA ["def"] = (:) <$> "def" <*> [[]]

因此采用 "def" 的所有元素、Char 角色 'd''e''f',然后将其与所有元素组合列表 [[]](仅 []),因此产生 "d""e""f".

然后对于 sequenceA ["c", "def"] 它因此等同于:

sequenceA ["c", "def"] = (:) <$> "c" <*> ["d", "e", "f"]

因此产生:["cd", "ce", "cf"],最后:

sequenceA ["ab", "c", "def"] = (:) <$> "ab" <*> ["cd", "ce", "cf"]

将产生:

sequenceA ["ab", "c", "def"] = ["acd", "ace", "acf", "bcd", "bce", "bcf"]

你用列表理解标记了这个:

pCombs pred xs = take 1 [ ys | ys <- sequenceAL xs, pred ys]

sequenceAL (xs:t)     = [ x : ys  | x <- xs, ys <- sequenceAL t]
sequenceAL []         = [ [] ]
sequenceAL [xs]       = [ [x]     | x <- xs]
sequenceAL [xs,ys]    = [ [x,y]   | x <- xs, y <- ys]
sequenceAL [xs,ys,zs] = [ [x,y,z] | x <- xs, y <- ys, z <- zs]
--- ....

列表理解就像嵌套循环。

可以看出,sequenceALsequenceA专门用于列表,[])枚举其参数列表中所有序列的笛卡尔积(最后一个“旋转“ 最快的)。由于该列表的长度是任意的,因此元素被收集到列表中,而不是元组中。

我们还可以定义

sequenceAL (xs:t)     = [ x : ys  | ys <- sequenceAL t, x <- xs]

结果列表中的 第一个 元素旋转最快。枚举的顺序可能无关紧要,它可以帮助解决内存问题。有关更多信息,请参阅

此外,如果您的谓词可以应用于部分结果列表以提前清除某些列表,则应该这样做,将过滤与生成步骤结合起来,以减少枚举space.换句话说,尽早测试,以防止无用的枚举。