11module Data.Foldable
22 ( Foldable , foldr , foldl , foldMap
3+ , foldrDefault , foldlDefault , foldMapDefaultL , foldMapDefaultR
34 , fold
45 , traverse_
56 , for_
@@ -25,7 +26,8 @@ import Data.Maybe.First (First(..), runFirst)
2526import Data.Maybe.Last (Last (..))
2627import Data.Monoid (Monoid , mempty )
2728import Data.Monoid.Additive (Additive (..))
28- import Data.Monoid.Dual (Dual (..))
29+ import Data.Monoid.Dual (Dual (..), runDual )
30+ import Data.Monoid.Endo (Endo (..), runEndo )
2931import Data.Monoid.Disj (Disj (..), runDisj )
3032import Data.Monoid.Conj (Conj (..), runConj )
3133import Data.Monoid.Multiplicative (Multiplicative (..))
@@ -35,15 +37,60 @@ import Data.Monoid.Multiplicative (Multiplicative(..))
3537-- | - `foldr` folds a structure from the right
3638-- | - `foldl` folds a structure from the left
3739-- | - `foldMap` folds a structure by accumulating values in a `Monoid`
40+ -- |
41+ -- | Default implementations are provided by the following functions:
42+ -- |
43+ -- | - `foldrDefault`
44+ -- | - `foldlDefault`
45+ -- | - `foldMapDefaultR`
46+ -- | - `foldMapDefaultL`
47+ -- |
48+ -- | Note: some combinations of the default implementations are unsafe to
49+ -- | use together - causing a non-terminating mutually recursive cycle.
50+ -- | These combinations are documented per function.
3851class Foldable f where
3952 foldr :: forall a b . (a -> b -> b ) -> b -> f a -> b
4053 foldl :: forall a b . (b -> a -> b ) -> b -> f a -> b
4154 foldMap :: forall a m . (Monoid m ) => (a -> m ) -> f a -> m
4255
56+
57+ -- | A default implementation of `foldr` using `foldMap`.
58+ -- |
59+ -- | Note: when defining a `Foldable` instance, this function is unsafe to use
60+ -- | in combination with `foldMapDefaultR`.
61+ foldrDefault :: forall f a b . (Foldable f ) =>
62+ (a -> b -> b ) -> b -> f a -> b
63+ foldrDefault c u xs = runEndo (foldMap (Endo <<< c) xs) u
64+
65+ -- | A default implementation of `foldl` using `foldMap`.
66+ -- |
67+ -- | Note: when defining a `Foldable` instance, this function is unsafe to use
68+ -- | in combination with `foldMapDefaultL`.
69+ foldlDefault :: forall f a b . (Foldable f ) =>
70+ (b -> a -> b ) -> b -> f a -> b
71+ foldlDefault c u xs = runEndo (runDual (foldMap (Dual <<< Endo <<< flip c) xs)) u
72+
73+ -- | A default implementation of `foldMap` using `foldr`.
74+ -- |
75+ -- | Note: when defining a `Foldable` instance, this function is unsafe to use
76+ -- | in combination with `foldrDefault`.
77+ foldMapDefaultR :: forall f a m . (Foldable f , Monoid m ) =>
78+ (a -> m ) -> f a -> m
79+ foldMapDefaultR f xs = foldr (\x acc -> f x <> acc) mempty xs
80+
81+ -- | A default implementation of `foldMap` using `foldl`.
82+ -- |
83+ -- | Note: when defining a `Foldable` instance, this function is unsafe to use
84+ -- | in combination with `foldlDefault`.
85+ foldMapDefaultL :: forall f a m . (Foldable f , Monoid m ) =>
86+ (a -> m ) -> f a -> m
87+ foldMapDefaultL f xs = foldl (\acc x -> f x <> acc) mempty xs
88+
89+
4390instance foldableArray :: Foldable Array where
44- foldr = foldrArray
45- foldl = foldlArray
46- foldMap f xs = foldr (\x acc -> f x <> acc) mempty xs
91+ foldr = foldrArray
92+ foldl = foldlArray
93+ foldMap = foldMapDefaultR
4794
4895foreign import foldrArray :: forall a b . (a -> b -> b ) -> b -> Array a -> b
4996foreign import foldlArray :: forall a b . (b -> a -> b ) -> b -> Array a -> b
0 commit comments