笛卡尔积"发电机"在Haskell中(不是列表)

时间:2016-02-25 06:10:52

标签: performance haskell functional-programming cartesian-product

我对函数式编程很陌生,而且我试图找出一个递归生成一组列表中笛卡尔积的元素的函数。

我正在寻找的功能与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

并且最后一个命令非常可怕,非常缓慢。

1 个答案:

答案 0 :(得分:2)

将我的评论转到答案:

最后一行显得特别慢的唯一原因是它迫使所有其他行的工作,否则懒惰地累积。因此,每个子列表都是根据需要进行处理(尽管每个子列表上的排序强制整个子列表)。

要观察所有阶段需要时间而不仅仅是最后阶段,我们可以使用rnf Control.DeepSeq对中间结果强制执行。

但是生成和总结大约100亿件事需要一些时间。正如其他人所观察到的那样,在这种情况下,您应该更多地考虑一种更聪明的方式来获得您想要的结果(即,可以在不改变结果的情况下删除或转换哪些中间步骤,以及您可以利用的对称性)而不仅仅是更有效地做蛮力的事情。