Consider these various attempts at something that works like last:
Prelude> import Data.Foldable
Prelude Data.Foldable> foldr const undefined (reverse [1,2,3])
3
Prelude Data.Foldable> foldr' const undefined (reverse [1,2,3])
3
Prelude Data.Foldable> foldl (flip const) undefined [1,2,3]
3
Prelude Data.Foldable> foldl' (flip const) undefined [1,2,3]
*** Exception: Prelude.undefined
CallStack (from HasCallStack):
error, called at libraries/base/GHC/Err.hs:79:14 in base:GHC.Err
undefined, called at <interactive>:5:21 in interactive:Ghci4
It makes sense to me that foldl and foldr both work, since they aren't strict in their accumulator, and it makes sense to me that foldl' doesn't, since it is. But why does foldr' work? Isn't it supposed to be strict in its accumulator too?
For reference, the instance
Foldable []overridesfoldr,foldl,foldl', but notfoldr'(source):foldr'is defined by default as (source):Note that there is only a strictness annotation on the result of
f. So the initial accumulator is not forced.This suggests a different implementation which does force the accumulator:
(Edited: the previous version was specialized to lists.)
I have no idea why one was chosen over the other. Probably an oversight, and it would be more consistent for
foldr'to not use the default implementation in theFoldable []instance.As an aside, the default definition of
foldl'is also different from the list one in the same way: