|
| 1 | +module Data.Semigroup.Foldable |
| 2 | + ( class Foldable1 |
| 3 | + , foldMap1 |
| 4 | + , fold1 |
| 5 | + , traverse1_ |
| 6 | + , for1_ |
| 7 | + , sequence1_ |
| 8 | + , foldMap1Default |
| 9 | + , fold1Default |
| 10 | + ) where |
| 11 | + |
| 12 | +import Prelude |
| 13 | +import Data.Foldable (class Foldable) |
| 14 | +import Data.Monoid.Dual (Dual(..)) |
| 15 | +import Data.Monoid.Multiplicative (Multiplicative(..)) |
| 16 | + |
| 17 | +-- | `Foldable1` represents data structures with a minimum of one element that can be _folded_. |
| 18 | +-- | |
| 19 | +-- | - `fold1` folds a structure using a `Semigroup` instance |
| 20 | +-- | - `foldMap1` folds a structure by accumulating values in a `Semigroup` |
| 21 | +-- | |
| 22 | +-- | Default implementations are provided by the following functions: |
| 23 | +-- | |
| 24 | +-- | - `fold1Default` |
| 25 | +-- | - `foldMap1Default` |
| 26 | +-- | |
| 27 | +-- | Note: some combinations of the default implementations are unsafe to |
| 28 | +-- | use together - causing a non-terminating mutually recursive cycle. |
| 29 | +-- | These combinations are documented per function. |
| 30 | +class Foldable t <= Foldable1 t where |
| 31 | + foldMap1 :: forall a m. Semigroup m => (a -> m) -> t a -> m |
| 32 | + fold1 :: forall m. Semigroup m => t m -> m |
| 33 | + |
| 34 | +-- | A default implementation of `fold1` using `foldMap1`. |
| 35 | +fold1Default :: forall t m. Foldable1 t => Semigroup m => t m -> m |
| 36 | +fold1Default = foldMap1 id |
| 37 | + |
| 38 | +-- | A default implementation of `foldMap1` using `fold1`. |
| 39 | +foldMap1Default :: forall t m a. Foldable1 t => Functor t => Semigroup m => (a -> m) -> t a -> m |
| 40 | +foldMap1Default f = (map f) >>> fold1 |
| 41 | + |
| 42 | +instance foldableDual :: Foldable1 Dual where |
| 43 | + foldMap1 f (Dual x) = f x |
| 44 | + fold1 = fold1Default |
| 45 | + |
| 46 | +instance foldableMultiplicative :: Foldable1 Multiplicative where |
| 47 | + foldMap1 f (Multiplicative x) = f x |
| 48 | + fold1 = fold1Default |
| 49 | + |
| 50 | +newtype Act f a = Act (f a) |
| 51 | + |
| 52 | +getAct :: forall f a. Act f a -> f a |
| 53 | +getAct (Act f) = f |
| 54 | + |
| 55 | +instance semigroupAct :: Apply f => Semigroup (Act f a) where |
| 56 | + append (Act a) (Act b) = Act (a *> b) |
| 57 | + |
| 58 | +-- | Traverse a data structure, performing some effects encoded by an |
| 59 | +-- | `Apply` instance at each value, ignoring the final result. |
| 60 | +traverse1_ :: forall t f a b. Foldable1 t => Apply f => (a -> f b) -> t a -> f Unit |
| 61 | +traverse1_ f t = unit <$ getAct (foldMap1 (Act <<< f) t) |
| 62 | + |
| 63 | +-- | A version of `traverse1_` with its arguments flipped. |
| 64 | +-- | |
| 65 | +-- | This can be useful when running an action written using do notation |
| 66 | +-- | for every element in a data structure: |
| 67 | +for1_ :: forall t f a b. Foldable1 t => Apply f => t a -> (a -> f b) -> f Unit |
| 68 | +for1_ = flip traverse1_ |
| 69 | + |
| 70 | +-- | Perform all of the effects in some data structure in the order |
| 71 | +-- | given by the `Foldable1` instance, ignoring the final result. |
| 72 | +sequence1_ :: forall t f a. Foldable1 t => Apply f => t (f a) -> f Unit |
| 73 | +sequence1_ = traverse1_ id |
0 commit comments