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

module Data.Distributive

-- | This is the categorical dual of Traversable.
--   
--   Due to the lack of non-trivial comonoids in Haskell, we can restrict
--   ourselves to requiring a Functor rather than some Coapplicative
--   class. Categorically every Distributive functor is actually a
--   right adjoint, and so it must be Representable endofunctor
--   and preserve all limits. This is a fancy way of saying it is
--   isomorphic to (->) x 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

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

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

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

-- | 
--   collectM = distributeM . liftM f
--   
collectM :: (Distributive g, Monad m) => (a -> g b) -> m a -> g (m b)

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

-- | The dual of mapM
--   
--   
--   comapM f = fmap f . distributeM
--   
comapM :: (Distributive g, Monad m) => (m a -> b) -> m (g a) -> g b
instance Data.Distributive.Distributive Data.Functor.Identity.Identity
instance Data.Distributive.Distributive Data.Proxy.Proxy
instance forall k (t :: k). 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.Semigroup.Internal.Dual
instance Data.Distributive.Distributive Data.Semigroup.Internal.Product
instance Data.Distributive.Distributive Data.Semigroup.Internal.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 m, GHC.Base.Monad m) => Data.Distributive.Distributive (Control.Applicative.WrappedMonad m)
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)

-- | collect derived from a Generic1 type
--   
--   This can be used to easily produce a Distributive instance for
--   a type with a Generic1 instance,
--   
--   
--   data V2 a = V2 a a deriving (Show, Functor, Generic1)
--   instance Distributive V2' where collect = genericCollect
--   
genericCollect :: (Functor f, Generic1 g, GDistributive (Rep1 g)) => (a -> g b) -> f a -> g (f b)

-- | distribute derived from a Generic1 type
--   
--   It's often more efficient to use genericCollect 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)
