我一直在使用以下代码来获取预定数量的所有组合:
getList x = [ [a,b,c] | a <- [1..x], b <- [1..x], c <- [1..x]]
这开始很好,但我希望扩展程序以处理非常大的列表,我一直认为必须有更好的方法来执行此操作。我如何创建一个与此处采用相同参数x的函数,以及该子列表具有多少项的另一个参数。对于四个项目,我会去修改代码:
getList x = [ [a,b,c,d] | a <- [1..x], b <- [1..x], c <- [1..x], d <- [1..x]]
它不需要是列表理解。谢谢你的帮助。
答案 0 :(得分:17)
我相信你想要的是replicateM
中的Control.Monad
功能。
列表monad基于“尝试所有可能的组合”,而普通replicate
通过重复项目多次来创建列表。因此,replicateM
的结果是,给出一些可能的值列表,列出了从该列表中选择项目的所有可能方法的次数。
例如:
> replicateM 2 [0, 1]
[[0,0],[0,1],[1,0],[1,1]]
> replicateM 3 [0, 1]
[[0,0,0],[0,0,1],[0,1,0],[0,1,1],[1,0,0],[1,0,1],[1,1,0],[1,1,1]]
所以要将你的函数扩展到任意重复,你可以使用类似的东西:
getListN n x = replicateM n [1..x]
...您的原始getList
等同于getListN 3
。
答案 1 :(得分:3)
如果有人喜欢非Monadic解决方案来理解内部工作原理(尽管通过replicateM
解决问题很棒!):
getListN n = foldl (\ass bs -> [ b:as | b <- bs, as <- ass]) [[]] . replicate n
基本上,通过foldl
实现此功能的方式与replacatM
- 解决方案完全相同。