И foldr
, и foldl'
чрезвычайно полезны для списков. Ни foldl
, ни foldr'
часто не полезны для списков. Но в наши дни эти функции на самом деле являются методами класса Foldable
, и они являются полезными в некоторых случаях. В качестве крайнего примера рассмотрим списки sno c:
data SL a = SL a :> a | Nil
infixl 5 :>
instance Foldable SL where
foldMap _ Nil = mempty
foldMap f (xs :> x) = foldMap f xs <> f x
foldl _ b Nil = b
foldl f b (xs :> x) = f (foldl f b xs) x
foldr' _ n Nil = n
foldr' c n (xs :> x) =
let n' = c x n
in n' `seq` foldr' c n' xs
Для списков sno c действительно полезны foldl
и foldr'
, тогда как foldr
и foldl'
довольно много бесполезного!
Многие контейнеры Foldable
могут эффективно использовать все четыре метода. Например, Data.Set.Set
, Data.Map.Map k
и Data.Sequence.Seq
могут быть прекрасно сложены в любом направлении.
import Data.Sequence (Seq)
import qualified Data.Sequence as S
toForwardList :: Seq a -> [a]
toForwardList = foldr (:) []
toReverseList :: Seq a -> [a]
toReverseList = foldl (flip (:)) []
Прямое и обратное преобразования одинаково эффективны и одинаково ленивы.