我对函数式编程很陌生,而且我试图找出一个递归生成一组列表中笛卡尔积的元素的函数。
我正在寻找的功能与sequence
完全相同(如此处所述:Calculate n-ary Cartesian Product),但我不想将整个内容表达为列表。
我目前正在使用sequence
并遇到此处所述问题的变体:Summing a large list of numbers is too slow。
例如,sequence [[1,2,3],[1,2,3]]
生成[[1,1],[1,2],[1,3],[2,1],[2,2],[2,3],[3,1],[3,2],[3,3]]
。处理每个组合(即[1,2]
等)作为列表是完全可以接受的,我只想避免构建长外部列表,而是在计算时递归地处理数据。我会这样做吗?
我目前正在做类似于这个快速ghci的例子:
> let stuff = sequence $ replicate 10 [0..9]
> let morestuff = map (sum . take 2 . reverse . sort) stuff
> sum morestuff
并且最后一个命令非常可怕,非常缓慢。
答案 0 :(得分:2)
将我的评论转到答案:
最后一行显得特别慢的唯一原因是它迫使所有其他行的工作,否则懒惰地累积。因此,每个子列表都是根据需要进行处理(尽管每个子列表上的排序强制整个子列表)。
要观察所有阶段需要时间而不仅仅是最后阶段,我们可以使用rnf
Control.DeepSeq
对中间结果强制执行。
但是生成和总结大约100亿件事需要一些时间。正如其他人所观察到的那样,在这种情况下,您应该更多地考虑一种更聪明的方式来获得您想要的结果(即,可以在不改变结果的情况下删除或转换哪些中间步骤,以及您可以利用的对称性)而不仅仅是更有效地做蛮力的事情。