-- 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.5.2


module Data.Distributive

-- | This is the categorical dual of <a>Traversable</a>.
--   
--   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 <tt>(-&gt;) x</tt> for some x.
--   
--   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

-- | The dual of <a>sequenceA</a>
--   
--   <pre>
--   &gt;&gt;&gt; distribute [(+1),(+2)] 1
--   [2,3]
--   </pre>
--   
--   <pre>
--   <a>distribute</a> = <a>collect</a> <a>id</a>
--   <a>distribute</a> . <a>distribute</a> = <a>id</a>
--   </pre>
distribute :: (Distributive g, Functor f) => f (g a) -> g (f a)

-- | <pre>
--   <a>collect</a> f = <a>distribute</a> . <a>fmap</a> f
--   <a>fmap</a> f = <a>runIdentity</a> . <a>collect</a> (<a>Identity</a> . f)
--   <a>fmap</a> <a>distribute</a> . <a>collect</a> f = <a>getCompose</a> . <a>collect</a> (<a>Compose</a> . f)
--   </pre>
collect :: (Distributive g, Functor f) => (a -> g b) -> f a -> g (f b)

-- | The dual of <a>sequence</a>
--   
--   <pre>
--   <a>distributeM</a> = <a>fmap</a> <a>unwrapMonad</a> . <a>distribute</a> . <a>WrapMonad</a>
--   </pre>
distributeM :: (Distributive g, Monad m) => m (g a) -> g (m a)

-- | <pre>
--   <a>collectM</a> = <a>distributeM</a> . <a>liftM</a> f
--   </pre>
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 :: (Distributive g, Functor f) => (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 :: (Distributive g, Monad m) => (m a -> b) -> m (g a) -> g b

-- | <a>fmapCollect</a> is a viable default definition for <a>fmap</a>
--   given a <a>Distributive</a> instance defined in terms of
--   <a>collect</a>.
fmapCollect :: forall f a b. Distributive f => (a -> b) -> f a -> f b
instance Data.Distributive.Distributive Data.Functor.Identity.Identity
instance Data.Distributive.Distributive Data.Proxy.Proxy
instance Data.Distributive.Distributive (Data.Tagged.Tagged t)
instance Data.Distributive.Distributive ((->) e)
instance Data.Distributive.Distributive g => Data.Distributive.Distributive (Control.Monad.Trans.Reader.ReaderT e g)
instance Data.Distributive.Distributive g => Data.Distributive.Distributive (Control.Monad.Trans.Identity.IdentityT g)
instance (Data.Distributive.Distributive f, Data.Distributive.Distributive g) => Data.Distributive.Distributive (Data.Functor.Compose.Compose f g)
instance (Data.Distributive.Distributive f, Data.Distributive.Distributive g) => Data.Distributive.Distributive (Data.Functor.Product.Product f g)
instance Data.Distributive.Distributive f => Data.Distributive.Distributive (Control.Applicative.Backwards.Backwards f)
instance Data.Distributive.Distributive f => Data.Distributive.Distributive (Data.Functor.Reverse.Reverse f)
instance Data.Distributive.Distributive Data.Monoid.Dual
instance Data.Distributive.Distributive Data.Monoid.Product
instance Data.Distributive.Distributive Data.Monoid.Sum
instance Data.Distributive.Distributive Data.Semigroup.Min
instance Data.Distributive.Distributive Data.Semigroup.Max
instance Data.Distributive.Distributive Data.Semigroup.First
instance Data.Distributive.Distributive Data.Semigroup.Last
instance Data.Distributive.Distributive Data.Complex.Complex
instance Data.Distributive.Distributive GHC.Generics.U1
instance (Data.Distributive.Distributive a, Data.Distributive.Distributive b) => Data.Distributive.Distributive (a GHC.Generics.:*: b)
instance (Data.Distributive.Distributive a, Data.Distributive.Distributive b) => Data.Distributive.Distributive (a GHC.Generics.:.: b)
instance Data.Distributive.Distributive GHC.Generics.Par1
instance Data.Distributive.Distributive f => Data.Distributive.Distributive (GHC.Generics.Rec1 f)
instance Data.Distributive.Distributive f => Data.Distributive.Distributive (GHC.Generics.M1 i c f)


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

-- | <a>collect</a> derived from a <a>Generic1</a> type
--   
--   This can be used to easily produce a <a>Distributive</a> 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 collect = genericCollect
--   </pre>
genericCollect :: (Functor f, Generic1 g, GDistributive (Rep1 g)) => (a -> g b) -> f a -> g (f b)

-- | <a>distribute</a> derived from a <a>Generic1</a> type
--   
--   It's often more efficient to use <a>genericCollect</a> instead.
genericDistribute :: (Functor f, Generic1 g, GDistributive (Rep1 g)) => f (g a) -> g (f a)
instance Data.Distributive.Generic.GDistributive GHC.Generics.U1
instance (Data.Distributive.Generic.GDistributive a, Data.Distributive.Generic.GDistributive b) => Data.Distributive.Generic.GDistributive (a GHC.Generics.:*: b)
instance (Data.Distributive.Distributive a, Data.Distributive.Generic.GDistributive b) => Data.Distributive.Generic.GDistributive (a GHC.Generics.:.: b)
instance Data.Distributive.Generic.GDistributive GHC.Generics.Par1
instance Data.Distributive.Distributive f => Data.Distributive.Generic.GDistributive (GHC.Generics.Rec1 f)
instance Data.Distributive.Generic.GDistributive f => Data.Distributive.Generic.GDistributive (GHC.Generics.M1 i c f)
