Reputation: 5500
I noticed that the Foldable class contains fold, foldl, foldr, foldl', and foldr', but there's no fold' (for strict monoidal folds)
How can I emulate the behavior of fold' with an IntMap (which is implemented as a tree, but doesn't give direct access to the internal nodes).
Motivation:
In particular, if I have an IntMap containing M IntMap's of size K (with total size N = M*K), I'd like to union them in O(N * log(M)) big-O running time. Something like:
unionMaps :: IntMap (IntMap a) -> IntMap a
unionMaps = fold'
This would work because IntMap is an instance of Monoid with mappend defined as union. Note that in general, using foldl' or foldr' is theoretically slower since it requires Omega(N * log N) worst-case running time. Admittedly, this is probably an insignificant difference in practice, but I'm pedantic enough to care about theoretically optimal bounds
Oops, the above is wrong. I went over it more carefully and now I realize it doesn't matter whether you use fold or foldl or foldr, the running time will be in O(N * log(M)). So I no longer have any motivation for this question.
Upvotes: 4
Views: 192
Reputation: 18189
Since I couldn't find any library with the full Foldable
fold'
, to have an answer to the basic question, I wrote up some code for @Carl's suggestion from the comments above (WHNF only):
{-# 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
Upvotes: 3