【问题标题】:Haskell: List fusion, where is it needed?Haskell:列表融合,哪里需要?
【发布时间】:2012-06-08 08:28:38
【问题描述】:

假设我们有以下内容:

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

我们想做的事:

head l

所以我们得到:

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

现在,我们必须获取 this 的第一个元素。 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' 案例中,编译器应该很容易意识到重新计算上面的列表比存储它更快。

【问题讨论】:

    标签: optimization haskell lazy-evaluation fusion


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

        猜你喜欢
        • 2014-01-23
        • 1970-01-01
        • 2019-01-28
        • 2012-08-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-18
        • 1970-01-01
        相关资源
        最近更新 更多