|
| 1 | +module Data.Bifoldable where |
| 2 | + |
| 3 | +import Control.Apply ((*>)) |
| 4 | +import Data.Either (Either(..)) |
| 5 | +import Data.Monoid (Monoid) |
| 6 | +import Data.Monoid.Inf (Inf(..), runInf) |
| 7 | +import Data.Monoid.Sup (Sup(..), runSup) |
| 8 | +import Data.Tuple (Tuple(..)) |
| 9 | + |
| 10 | +-- | `Bifoldable` represents data structures with two type arguments which can be |
| 11 | +-- | folded. |
| 12 | +-- | |
| 13 | +-- | A fold for such a structure requires two step functions, one for each type |
| 14 | +-- | argument. Type class instances should choose the appropriate step function based |
| 15 | +-- | on the type of the element encountered at each point of the fold. |
| 16 | +-- | |
| 17 | +class Bifoldable p where |
| 18 | + bifoldr :: forall a b c. (a -> c -> c) -> (b -> c -> c) -> c -> p a b -> c |
| 19 | + bifoldl :: forall a b c. (c -> a -> c) -> (c -> b -> c) -> c -> p a b -> c |
| 20 | + bifoldMap :: forall m a b. (Monoid m) => (a -> m) -> (b -> m) -> p a b -> m |
| 21 | + |
| 22 | +instance bifoldableTuple :: Bifoldable Tuple where |
| 23 | + bifoldMap f g (Tuple a b) = f a <> g b |
| 24 | + bifoldr f g z (Tuple a b) = f a (g b z) |
| 25 | + bifoldl f g z (Tuple a b) = g (f z a) b |
| 26 | + |
| 27 | +instance bifoldableEither :: Bifoldable Either where |
| 28 | + bifoldMap f _ (Left a) = f a |
| 29 | + bifoldMap _ g (Right b) = g b |
| 30 | + bifoldr f _ z (Left a) = f a z |
| 31 | + bifoldr _ g z (Right b) = g b z |
| 32 | + bifoldl f _ z (Left a) = f z a |
| 33 | + bifoldl _ g z (Right b) = g z b |
| 34 | + |
| 35 | +-- | Fold a data structure, accumulating values in a monoidal type. |
| 36 | +bifold :: forall t m. (Bifoldable t, Monoid m) => t m m -> m |
| 37 | +bifold = bifoldMap id id |
| 38 | + |
| 39 | +-- | Traverse a data structure, accumulating effects using an `Applicative` functor, |
| 40 | +-- | ignoring the final result. |
| 41 | +bitraverse_ :: forall t f a b c d. (Bifoldable t, Applicative f) => (a -> f c) -> (b -> f d) -> t a b -> f Unit |
| 42 | +bitraverse_ f g = bifoldr ((*>) <<< f) ((*>) <<< g) (pure unit) |
| 43 | + |
| 44 | +-- | A version of `bitraverse_` with the data structure as the first argument. |
| 45 | +bifor_ :: forall t f a b c d. (Bifoldable t, Applicative f) => t a b -> (a -> f c) -> (b -> f d) -> f Unit |
| 46 | +bifor_ t f g = bitraverse_ f g t |
| 47 | + |
| 48 | +-- | Collapse a data structure, collecting effects using an `Applicative` functor, |
| 49 | +-- | ignoring the final result. |
| 50 | +bisequence_ :: forall t f a b. (Bifoldable t, Applicative f) => t (f a) (f b) -> f Unit |
| 51 | +bisequence_ = bitraverse_ id id |
| 52 | + |
| 53 | +-- | Test whether a predicate holds at any position in a data structure. |
| 54 | +biany :: forall t a b c. (Bifoldable t, BoundedLattice c) => (a -> c) -> (b -> c) -> t a b -> c |
| 55 | +biany p q = runSup <<< bifoldMap (Sup <<< p) (Sup <<< q) |
| 56 | + |
| 57 | +-- -- | Test whether a predicate holds at all positions in a data structure. |
| 58 | +biall :: forall t a b c. (Bifoldable t, BoundedLattice c) => (a -> c) -> (b -> c) -> t a b -> c |
| 59 | +biall p q = runInf <<< bifoldMap (Inf <<< p) (Inf <<< q) |
0 commit comments