pandora-0.1.6: Pandora/Pattern/Functor/Distributive.hs
module Pandora.Pattern.Functor.Distributive (Distributive (..)) where
import Pandora.Core.Functor (type (:.:))
import Pandora.Core.Morphism (identity, (.))
import Pandora.Pattern.Functor.Covariant (Covariant)
{- |
> Let f :: Distributive g => (a -> g b)
> When providing a new instance, you should ensure it satisfies the two laws:
> * Identity morphism: distribute . distribute ≡ identity
> * Interchange collection: collect f ≡ distribute . comap f
-}
infixl 5 >>-, >>>-, >>>>-, >>>>>-
class Covariant u => Distributive u where
{-# MINIMAL (>>-) #-}
-- | Infix version of 'collect'
(>>-) :: Covariant t => t a -> (a -> u b) -> (u :.: t) b
-- | Prefix version of '>>-'
collect :: Covariant t => (a -> u b) -> t a -> (u :.: t) b
collect f t = t >>- f
-- | The dual of 'sequence'
distribute :: Covariant t => (t :.: u) a -> (u :.: t) a
distribute t = t >>- identity
-- | Infix versions of `collect` with various nesting levels
(>>>-) :: (Covariant t, Covariant v)
=> (t :.: v) a -> (a -> u b) -> (u :.: t :.: v) b
x >>>- f = (collect . collect) f x
(>>>>-) :: (Covariant t, Covariant v, Covariant w)
=> (t :.: v :.: w) a -> (a -> u b) -> (u :.: t :.: v :.: w) b
x >>>>- f = (collect . collect . collect) f x
(>>>>>-) :: (Covariant t, Covariant v, Covariant w, Covariant j)
=> (t :.: v :.: w :.: j) a -> (a -> u b) -> (u :.: t :.: v :.: w :.: j) b
x >>>>>- f = (collect . collect . collect . collect) f x