我在wiki.haskell.org上找到了一种算法,用于生成给定列表中n个元素的组合。它通过列表理解来构造[[a]]
。
combos :: Int -> [a] -> [[a]]
combos 0 _ = [ [] ]
combos n xs = [ y:ys | y:xs' <- tails xs
, ys <- combos (n-1) xs']
假设我们执行combos 2 [1,2,3]
,那么主函数将如下所示:
combos 2 [1,2,3] = [ y:ys | y:xs' <- [[1,2,3],[2,3],[3],[]]
, ys <- combos 1 xs']
我认为在模式中y:xs'
y
是一个列表(第一次运行时为[1,2,3]
),而xs'
是一个列表列表([[2,3],[3],[]]
第一次运行)。
当我将xs'
作为递归combos
调用(ys <- combos 1 xs')
调用的参数抛出时,我对此部分感到困惑。combos
现在变为[[a]] -> [[[a]]]
}?)
这一切是如何运作的?请问您能描述一下这个功能是如何工作的吗?
答案 0 :(得分:3)
请注意… <- …
和let … = …
之间的区别。在列表理解中,x <- xs
的两边不能具有相同的类型; x
连续分配给xs
的每个元素。
在您的示例中,(y:xs') <- [[1,2,3],[2,3],[3],[]]
表示我们从该列表中获取与模式(y:xs')
匹配的元素。因此,我们第一次在此处进行选择,y == 1
和xs' == [2,3]
;我们第二次做出选择,y == 2
和xs' == [3]
,等等。