Haskell:列表融合,它需要在哪里?

时间:2012-06-08 08:28:39

标签: optimization haskell lazy-evaluation fusion

假设我们有以下内容:

l = map f (map g [1..100])

我们想做:

head l

所以我们得到:

head (map f (map g [1..100]))

现在,我们必须得到第一个元素。 map定义如下:

map f l = f (head l) : (map f (tail l))

然后我们得到:

f (head (map g [1..100]))

然后再次申请:

f (g (head [1..100]))

结果是

f (g 1)

由于懒惰,没有形成中间名单。

这种分析是否正确?并且使用这样的简单结构:

foldl' ... $ map f1 $ map f2 $ createlist

是有史以来创建的中间列表,即使没有“列表融合”? (我认为懒惰应该琐碎地消除它们。)


我唯一可以看到保留清单的理由就是:

l' = [1..100]
l = map f (map g l')

如果在其他地方使用,我们可能希望保留l'。但是,在上面的l'情况下,编译器要快速重新计算上面的列表而不是存储它应该是相当简单的。

2 个答案:

答案 0 :(得分:7)

map示例中,列表单元格已创建,然后立即进行垃圾回收。使用列表融合时,不需要GC或thunk操作(它们都不是免费的)。

答案 1 :(得分:7)

当中间数据结构昂贵时,融合最有利。当传递的结构是惰性的并且以顺序方式访问时,结构可能相对便宜(如列表的情况)。

  • 对于懒惰的结构,融合消除了创建thunk的常数因素,并立即垃圾收集它。
  • 对于严格的结构,融合可以删除 O(n)的工作。

因此,对于严格的阵列和类似的结构,最大的好处是。然而,由于数据局部性增加,即使融合懒惰列表仍然是一个胜利,因为更少的中间结构被分配为thunk。