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


-- | Contravariant functors
--   
--   Contravariant functors
@package contravariant
@version 1.2.0.1


-- | <a>Contravariant</a> functors, sometimes referred to colloquially as
--   <tt>Cofunctor</tt>, even though the dual of a <a>Functor</a> is just a
--   <a>Functor</a>. As with <a>Functor</a> the definition of
--   <a>Contravariant</a> for a given ADT is unambiguous.
module Data.Functor.Contravariant

-- | Any instance should be subject to the following laws:
--   
--   <pre>
--   contramap id = id
--   contramap f . contramap g = contramap (g . f)
--   </pre>
--   
--   Note, that the second law follows from the free theorem of the type of
--   <a>contramap</a> and the first law, so you need only check that the
--   former condition holds.
class Contravariant f where (>$) = contramap . const
contramap :: Contravariant f => (a -> b) -> f b -> f a
(>$) :: Contravariant f => b -> f b -> f a
(>$<) :: Contravariant f => (a -> b) -> f b -> f a
(>$$<) :: Contravariant f => f b -> (a -> b) -> f a
newtype Predicate a
Predicate :: (a -> Bool) -> Predicate a
getPredicate :: Predicate a -> a -> Bool

-- | Defines a total ordering on a type as per <a>compare</a>
newtype Comparison a
Comparison :: (a -> a -> Ordering) -> Comparison a
getComparison :: Comparison a -> a -> a -> Ordering

-- | Compare using <a>compare</a>
defaultComparison :: Ord a => Comparison a

-- | Define an equivalence relation
newtype Equivalence a
Equivalence :: (a -> a -> Bool) -> Equivalence a
getEquivalence :: Equivalence a -> a -> a -> Bool

-- | Check for equivalence with <a>==</a>
defaultEquivalence :: Eq a => Equivalence a
comparisonEquivalence :: Comparison a -> Equivalence a

-- | Dual function arrows.
newtype Op a b
Op :: (b -> a) -> Op a b
getOp :: Op a b -> b -> a
instance [safe] Typeable Predicate
instance [safe] Typeable Comparison
instance [safe] Typeable Equivalence
instance [safe] Typeable Op
instance [safe] Floating a => Floating (Op a b)
instance [safe] Fractional a => Fractional (Op a b)
instance [safe] Num a => Num (Op a b)
instance [safe] Monoid a => Monoid (Op a b)
instance [safe] Semigroup a => Semigroup (Op a b)
instance [safe] Contravariant (Op a)
instance [safe] Category Op
instance [safe] Monoid (Equivalence a)
instance [safe] Semigroup (Equivalence a)
instance [safe] Contravariant Equivalence
instance [safe] Monoid (Comparison a)
instance [safe] Semigroup (Comparison a)
instance [safe] Contravariant Comparison
instance [safe] Contravariant Predicate
instance [safe] Contravariant Proxy
instance [safe] Contravariant f => Contravariant (Reverse f)
instance [safe] Contravariant f => Contravariant (Backwards f)
instance [safe] (Functor f, Contravariant g) => Contravariant (Compose f g)
instance [safe] Contravariant (Const a)
instance [safe] Contravariant (Constant a)
instance [safe] (Contravariant f, Contravariant g) => Contravariant (Product f g)
instance [safe] (Contravariant f, Contravariant g) => Contravariant (Sum f g)
instance [safe] (Contravariant f, Contravariant g) => Contravariant (f :+: g)
instance [safe] (Functor f, Contravariant g) => Contravariant (f :.: g)
instance [safe] (Contravariant f, Contravariant g) => Contravariant (f :*: g)
instance [safe] Contravariant (K1 i c)
instance [safe] Contravariant f => Contravariant (M1 i c f)
instance [safe] Contravariant f => Contravariant (Rec1 f)
instance [safe] Contravariant U1
instance [safe] Contravariant V1

module Data.Functor.Contravariant.Divisible

-- | A <a>Divisible</a> contravariant functor is the contravariant analogue
--   of <tt>Applicative</tt>.
--   
--   In denser jargon, a <a>Divisible</a> contravariant functor is a monoid
--   object in the category of presheaves from Hask to Hask, equipped with
--   Day convolution mapping the Cartesian product of the source to the
--   Cartesian product of the target.
--   
--   By way of contrast, an <tt>Applicative</tt> functor can be viewed as a
--   monoid object in the category of copresheaves from Hask to Hask,
--   equipped with Day convolution mapping the Cartesian product of the
--   source to the Cartesian product of the target.
--   
--   Given the canonical diagonal morphism:
--   
--   <pre>
--   delta a = (a,a)
--   </pre>
--   
--   <tt><a>divide</a> <tt>delta</tt></tt> should be associative with
--   <a>conquer</a> as a unit
--   
--   <pre>
--   <a>divide</a> <tt>delta</tt> m <a>conquer</a> = m
--   <a>divide</a> <tt>delta</tt> <a>conquer</a> m = m
--   <a>divide</a> <tt>delta</tt> (<a>divide</a> <tt>delta</tt> m n) o = <a>divide</a> <tt>delta</tt> m (<a>divide</a> <tt>delta</tt> n o)
--   </pre>
--   
--   With more general arguments you'll need to reassociate and project
--   using the monoidal structure of the source category. (Here fst and snd
--   are used in lieu of the more restricted lambda and rho, but this
--   construction works with just a monoidal category.)
--   
--   <pre>
--   <a>divide</a> f m <a>conquer</a> = <a>contramap</a> (<a>fst</a> . f) m
--   <a>divide</a> f <a>conquer</a> m = <a>contramap</a> (<a>snd</a> . f) m
--   <a>divide</a> f (<a>divide</a> g m n) o = <a>divide</a> f' m (<a>divide</a> <a>id</a> n o) where
--     f' a = case f a of (bc,d) -&gt; case g bc of (b,c) -&gt; (a,(b,c))
--   </pre>
class Contravariant f => Divisible f
divide :: Divisible f => (a -> (b, c)) -> f b -> f c -> f a
conquer :: Divisible f => f a

-- | <pre>
--   <a>divided</a> = <a>divide</a> <a>id</a>
--   </pre>
divided :: Divisible f => f a -> f b -> f (a, b)

-- | Redundant, but provided for symmetry.
--   
--   <pre>
--   <a>conquered</a> = 'conquer
--   </pre>
conquered :: Divisible f => f ()

-- | This is the divisible analogue of <tt>liftA</tt>. It gives a viable
--   default definition for <a>contramap</a> in terms of the members of
--   <a>Divisible</a>.
--   
--   <pre>
--   <a>liftD</a> f = <a>divide</a> ((,) () . f) <a>conquer</a>
--   </pre>
liftD :: Divisible f => (a -> b) -> f b -> f a

-- | A <a>Divisible</a> contravariant functor is a monoid object in the
--   category of presheaves from Hask to Hask, equipped with Day
--   convolution mapping the cartesian product of the source to the
--   Cartesian product of the target.
--   
--   <pre>
--   <a>choose</a> Left m (<a>lose</a> f)  = m
--   <a>choose</a> Right (<a>lose</a> f) m = m
--   <a>choose</a> f (<a>choose</a> g m n) o = <a>divide</a> f' m (<a>divide</a> <a>id</a> n o) where
--     f' bcd = <a>either</a> (<a>either</a> <a>id</a> (<a>Right</a> . <a>Left</a>) . g) (<a>Right</a> . <a>Right</a>) . f
--   </pre>
--   
--   In addition, we expect the same kind of distributive law as is
--   satisfied by the usual covariant <tt>Alternative</tt>, w.r.t
--   <tt>Applicative</tt>, which should be fully formulated and added here
--   at some point!
class Divisible f => Decidable f
lose :: Decidable f => (a -> Void) -> f a
choose :: Decidable f => (a -> Either b c) -> f b -> f c -> f a

-- | <pre>
--   <a>chosen</a> = <a>choose</a> <a>id</a>
--   </pre>
chosen :: Decidable f => f b -> f c -> f (Either b c)

-- | <pre>
--   <a>lost</a> = <a>lose</a> <a>id</a>
--   </pre>
lost :: Decidable f => f Void
instance Monoid r => Decidable (Op r)
instance Decidable Predicate
instance Decidable Equivalence
instance Decidable Comparison
instance Divisible Predicate
instance Divisible Equivalence
instance Divisible Comparison
instance Monoid r => Divisible (Op r)


-- | Composition of contravariant functors.
module Data.Functor.Contravariant.Compose

-- | Composition of two contravariant functors
newtype Compose f g a
Compose :: f (g a) -> Compose f g a
getCompose :: Compose f g a -> f (g a)

-- | Composition of covariant and contravariant functors
newtype ComposeFC f g a
ComposeFC :: f (g a) -> ComposeFC f g a
getComposeFC :: ComposeFC f g a -> f (g a)

-- | Composition of contravariant and covariant functors
newtype ComposeCF f g a
ComposeCF :: f (g a) -> ComposeCF f g a
getComposeCF :: ComposeCF f g a -> f (g a)
instance (Divisible f, Applicative g) => Divisible (ComposeCF f g)
instance (Functor f, Functor g) => Functor (ComposeCF f g)
instance (Contravariant f, Functor g) => Contravariant (ComposeCF f g)
instance (Applicative f, Decidable g) => Decidable (ComposeFC f g)
instance (Applicative f, Divisible g) => Divisible (ComposeFC f g)
instance (Functor f, Functor g) => Functor (ComposeFC f g)
instance (Functor f, Contravariant g) => Contravariant (ComposeFC f g)
instance (Contravariant f, Contravariant g) => Functor (Compose f g)
