Foldl as foldr
From HaskellWiki
When you wonder whether to choose foldl or foldr you may remember,
that bothfoldl
foldl'
foldr
foldr
foldr
foldl
It holds
foldl :: (a -> b -> a) -> a -> [b] -> a foldl f a bs = foldr (\b g x -> g (f x b)) id bs a
Now the question are:
- How can someone find a convolved expression like this?
- How can we benefit from this rewrite?
1 Folding by concatenating updates
Instead of thinking in terms offoldr
g
I find it easier to imagine a fold as a sequence of updates. An update is a function mapping from an old value to an updated new value.
newtype Update a = Update {evalUpdate :: a -> a}
We need a way to assemble several updates.
To this end we define aMonoid
instance Monoid (Update a) where mempty = Update id mappend (Update x) (Update y) = Update (y.x)
Now left-folding is straight-forward.
foldlMonoid :: (a -> b -> a) -> a -> [b] -> a foldlMonoid f a bs = flip evalUpdate a $ mconcat $ map (Update . flip f) bs
foldr
mconcat
mconcat :: Monoid a => [a] -> a mconcat = foldr mappend mempty
mappend
Update
mconcat
foldl
foldl
By the way:
If you use aState
mapAccumL
2 foldl which may terminate early
The answer to the second question is:
We can write afoldl
and thus may also terminate on infinite input.
The functionfoldlMaybe
Nothing
Nothing
foldlMaybe :: (a -> b -> Maybe a) -> a -> [b] -> Maybe a foldlMaybe f a bs = foldr (\b g x -> f x b >>= g) Just bs a
