为什么没有折叠'方法?

时间:2014-06-16 20:48:18

标签: haskell big-o lazy-evaluation fold monoids

我注意到Foldable类包含fold,foldl,foldr,foldl'和foldr'但是没有折叠' (对于严格的幺半褶)

我如何模仿fold'的行为?使用IntMap(实现为树,但不能直接访问内部节点)。


动机:

特别是,如果我有一个包含大小为K的N IntMap的IntMap(总大小为N = M * K),我想在O中合并它们(N * log(M) )大O运行时间。类似的东西:

unionMaps :: IntMap (IntMap a) -> IntMap a
unionMaps = fold'

这样可行,因为IntMap是Monoid的一个实例,mappend定义为union。请注意,一般来说,使用foldl'或者折叠'理论上较慢,因为它需要Omega(N * log N)最坏情况下的运行时间。不可否认,这在实践中可能是一个微不足道的差异,但我迂腐足以关心理论上的最佳界限


哎呀,以上是错的。我仔细检查过,现在我发现无论你使用折叠还是折叠或折叠都没关系,运行时间都是O(N * log(M))。所以我不再有这个问题的动机了。

1 个答案:

答案 0 :(得分:3)

由于我无法找到任何包含完整Foldable fold'的图书馆,为了回答基本问题,我为@ Carl的建议编写了一些代码。以上评论(仅限WHNF):

{-# LANGUAGE BangPatterns #-}
import Data.Monoid
import Data.Foldable

newtype StrictM m = StrictM { getStrict :: m }

instance Monoid m => Monoid (StrictM m) where
    mempty = StrictM mempty
    mappend (StrictM !x) (StrictM !y) = StrictM (mappend x y)

fold' :: (Foldable t, Monoid m) => t m -> m
fold' = getStrict . foldMap StrictM