foldl1 and foldr1
The two functions
foldl1 :: (a -> a -> a) -> t a -> a
foldr1 :: (a -> a -> a) -> t a -> a
are specialized versions of foldl
and foldr
for non-empty containers. In
this case, if the accumulated value is of the same type as the elements in the
container, we can get away without specifying the initial accumulator value.
Instead, we take the first or last container element (first for foldl1
, last
for foldr1
) as the initial accumulator value and then use the accumulation
function to combine the container elements.
Here are two possible default implementations of these functions, again using lists as an intermediate representation. They are different from the actual implementations, which are more complicated but avoid the detour via lists.
foldl1 f xs = foldl1 f $ foldMap singleton xs
foldr1 f xs = foldr1 f $ foldMap singleton xs
Again, foldMap singleton xs
takes care of converting the container to a list.
And then we use list-specific versions of foldl1
and foldr1
to accumulate
the list elements. We discussed list-specific implementations of foldl1
and
foldr1
before.