【问题标题】:Haskell - foldl' in terms of foldr and performance issuesHaskell - foldl' 在 foldr 和性能问题方面
【发布时间】:2015-11-19 09:25:33
【问题描述】:

在使用A tutorial on the universality and expressiveness of fold 深入研究fold 时,我发现使用foldrfoldl 进行了惊人的定义:

-- I used one lambda function inside another only to improve reading
foldl :: (b -> a -> b) -> b -> [a] -> b
foldl f z xs = foldr (\x g -> (\a -> g (f a x))) id xs z

了解了怎么回事后,我想我什至可以用foldr来定义foldl',会是这样的:

foldl' :: (b -> a -> b) -> b -> [a] -> b
foldl' f z xs = foldr (\x g -> (\a -> let z' = a `f` x in z' `seq` g z')) id xs z

与此平行:

foldl' :: (b -> a -> b) -> b -> [a] -> b
foldl' f z (x:xs) = let z' = z `f` x 
                    in seq z' $ foldl' f z' xs 
foldl' _ z _     = z

在这样的简单情况下,它们似乎都在恒定空间中运行(而不是创建 thunk):

*Main> foldl' (+) 0 [1..1000000]
500000500000

我可以认为foldl' 的两个定义在性能方面是等效的吗?

【问题讨论】:

    标签: performance haskell fold


    【解决方案1】:

    在 GHC 7.10+ 中,foldlfoldl' 都是根据 foldr 定义的。他们之前没有的原因是 GHC 没有将foldr 定义优化到足以参与foldr/build 融合的程度。但是 GHC 7.10 引入了一个新的优化,专门允许 foldr/build 融合成功,同时使用 foldl'foldl' 以这种方式定义。

    这里最大的胜利是像foldl' (+) 0 [1..10] 这样的表达式可以优化到根本不分配(:) 构造函数。而且我们都知道,绝对最快的垃圾收集是在没有垃圾要收集的时候。

    请参阅http://www.joachim-breitner.de/publications/CallArity-TFP.pdf,了解有关 GHC 7.10 中新优化的信息,以及为什么需要这样做。

    【讨论】:

      猜你喜欢
      • 2015-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-04
      • 1970-01-01
      • 2013-02-03
      • 1970-01-01
      相关资源
      最近更新 更多