-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Distributive functors -- Dual to Traversable
--   
--   Distributive functors -- Dual to Traversable
@package distributive
@version 0.4.4


module Data.Distributive.Generic
class GDistributive g
gdistribute :: (GDistributive g, Functor f) => f (g a) -> g (f a)

-- | <tt>distribute</tt> derived from a <a>Generic1</a> type
--   
--   This can be used to easily produce a <tt>Distributive</tt> instance
--   for a type with a <a>Generic1</a> instance,
--   
--   <pre>
--   data V2 a = V2 a a deriving (Show, Functor, Generic1)
--   instance Distributive V2' where distribute = genericDistribute
--   </pre>
genericDistribute :: (Functor f, Generic1 g, GDistributive (Rep1 g)) => f (g a) -> g (f a)
instance GDistributive f => GDistributive (M1 i c f)
instance GDistributive f => GDistributive (Rec1 f)
instance GDistributive Par1
instance (Functor a, Functor b, GDistributive a, GDistributive b) => GDistributive (a :.: b)
instance (GDistributive a, GDistributive b) => GDistributive (a :*: b)
instance GDistributive U1


module Data.Distributive

-- | This is the categorical dual of <tt>Traversable</tt>.
--   
--   Due to the lack of non-trivial comonoids in Haskell, we can restrict
--   ourselves to requiring a <a>Functor</a> rather than some Coapplicative
--   class. Categorically every <a>Distributive</a> functor is actually a
--   right adjoint, and so it must be <tt>Representable</tt> endofunctor
--   and preserve all limits. This is a fancy way of saying it isomorphic
--   to `(-&gt;) x` for some x.
--   
--   Minimal complete definition: <a>distribute</a> or <a>collect</a>
--   
--   To be distributable a container will need to have a way to
--   consistently zip a potentially infinite number of copies of itself.
--   This effectively means that the holes in all values of that type, must
--   have the same cardinality, fixed sized vectors, infinite streams,
--   functions, etc. and no extra information to try to merge together.
class Functor g => Distributive g where distribute = collect id collect f = distribute . fmap f distributeM = fmap unwrapMonad . distribute . WrapMonad collectM f = distributeM . liftM f
distribute :: (Distributive g, Functor f) => f (g a) -> g (f a)
collect :: (Distributive g, Functor f) => (a -> g b) -> f a -> g (f b)
distributeM :: (Distributive g, Monad m) => m (g a) -> g (m a)
collectM :: (Distributive g, Monad m) => (a -> g b) -> m a -> g (m b)

-- | The dual of <a>traverse</a>
--   
--   <pre>
--   <a>cotraverse</a> f = <a>fmap</a> f . <a>distribute</a>
--   </pre>
cotraverse :: (Functor f, Distributive g) => (f a -> b) -> f (g a) -> g b

-- | The dual of <a>mapM</a>
--   
--   <pre>
--   <a>comapM</a> f = <a>fmap</a> f . <a>distributeM</a>
--   </pre>
comapM :: (Monad m, Distributive g) => (m a -> b) -> m (g a) -> g b
instance Distributive f => Distributive (Reverse f)
instance Distributive f => Distributive (Backwards f)
instance (Distributive f, Distributive g) => Distributive (Product f g)
instance (Distributive f, Distributive g) => Distributive (Compose f g)
instance Distributive g => Distributive (IdentityT g)
instance Distributive g => Distributive (ReaderT e g)
instance Distributive ((->) e)
instance Distributive (Tagged * t)
instance Distributive (Proxy *)
instance Distributive Identity
