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


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


-- | <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
contramap :: Contravariant f => (a -> 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

-- | Dual function arrows.
newtype Op a b
Op :: (b -> a) -> Op a b
getOp :: Op a b -> b -> a
instance [safe] Typeable1 Predicate
instance [safe] Typeable1 Comparison
instance [safe] Typeable1 Equivalence
instance [safe] Typeable2 Op
instance [safe] Contravariant (Op a)
instance [safe] Category Op
instance [safe] Contravariant Equivalence
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)


-- | 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 (Functor f, Functor g) => Functor (ComposeCF f g)
instance (Contravariant f, Functor g) => Contravariant (ComposeCF 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)


-- | The Day convolution of two contravariant functors is a contravariant
--   functor.
--   
--   <a>http://ncatlab.org/nlab/show/Day+convolution</a>
module Data.Functor.Contravariant.Day

-- | The Day convolution of two contravariant functors.
data Day f g a
Day :: (f b) -> (g c) -> (a -> (b, c)) -> Day f g a

-- | Construct the Day convolution
--   
--   <pre>
--   <a>day1</a> (<a>day</a> f g) = f
--   <a>day2</a> (<a>day</a> f g) = g
--   </pre>
day :: f a -> g b -> Day f g (a, b)

-- | Break apart the Day convolution of two contravariant functors.
runDay :: (Contravariant f, Contravariant g) => Day f g a -> (f a, g a)

-- | Day convolution provides a monoidal product. The associativity of this
--   monoid is witnessed by <a>assoc</a> and <a>disassoc</a>.
--   
--   <pre>
--   <a>assoc</a> . <a>disassoc</a> = <a>id</a>
--   <a>disassoc</a> . <a>assoc</a> = <a>id</a>
--   <a>contramap</a> f <a>.</a> <a>assoc</a> = <a>assoc</a> <a>.</a> <a>contramap</a> f
--   </pre>
assoc :: Day f (Day g h) a -> Day (Day f g) h a

-- | Day convolution provides a monoidal product. The associativity of this
--   monoid is witnessed by <a>assoc</a> and <a>disassoc</a>.
--   
--   <pre>
--   <a>assoc</a> . <a>disassoc</a> = <a>id</a>
--   <a>disassoc</a> . <a>assoc</a> = <a>id</a>
--   <a>contramap</a> f <a>.</a> <a>disassoc</a> = <a>disassoc</a> <a>.</a> <a>contramap</a> f
--   </pre>
disassoc :: Day (Day f g) h a -> Day f (Day g h) a

-- | The monoid for Day convolution <i>in Haskell</i> is symmetric.
--   
--   <pre>
--   <a>contramap</a> f <a>.</a> <a>swapped</a> = <a>swapped</a> <a>.</a> <a>contramap</a> f
--   </pre>
swapped :: Day f g a -> Day g f a

-- | Proxy serves as the unit of Day convolution.
--   
--   <pre>
--   <a>day1</a> <a>.</a> <a>intro1</a> = <a>id</a>
--   <a>contramap</a> f <a>.</a> <a>intro1</a> = <a>intro1</a> <a>.</a> <a>contramap</a> f
--   </pre>
intro1 :: f a -> Day Proxy f a

-- | Proxy serves as the unit of Day convolution.
--   
--   <pre>
--   <a>day2</a> <a>.</a> <a>intro2</a> = <a>id</a>
--   <a>contramap</a> f <a>.</a> <a>intro2</a> = <a>intro2</a> <a>.</a> <a>contramap</a> f
--   </pre>
intro2 :: f a -> Day f Proxy a

-- | In Haskell we can do general purpose elimination, but in a more
--   general setting it is only possible to eliminate the unit.
--   
--   <pre>
--   <a>day1</a> <a>.</a> <a>intro1</a> = <a>id</a>
--   <a>day1</a> = <a>fst</a> <a>.</a> <a>runDay</a>
--   <a>contramap</a> f <a>.</a> <a>day1</a> = <a>day1</a> <a>.</a> <a>contramap</a> f
--   </pre>
day1 :: Contravariant f => Day f g a -> f a

-- | In Haskell we can do general purpose elimination, but in a more
--   general setting it is only possible to eliminate the unit. <tt>
--   <a>day2</a> <a>.</a> <a>intro2</a> = <a>id</a> <a>day2</a> =
--   <a>snd</a> <a>.</a> <a>runDay</a> <a>contramap</a> f <a>.</a>
--   <a>day2</a> = <a>day2</a> <a>.</a> <a>contramap</a> f </tt>
day2 :: Contravariant g => Day f g a -> g a

-- | Diagonalize the Day convolution:
--   
--   <pre>
--   <a>day1</a> <a>.</a> <a>diag</a> = <a>id</a>
--   <a>day2</a> <a>.</a> <a>diag</a> = <a>id</a>
--   'runDay <a>.</a> <a>diag</a> = a -&gt; (a,a)
--   <a>contramap</a> f . <a>diag</a> = <a>diag</a> . <a>contramap</a> f
--   </pre>
diag :: f a -> Day f f a

-- | Apply a natural transformation to the left-hand side of a Day
--   convolution.
--   
--   This respects the naturality of the natural transformation you
--   supplied:
--   
--   <pre>
--   <a>contramap</a> f <a>.</a> <a>trans1</a> fg = <a>trans1</a> fg <a>.</a> <a>contramap</a> f
--   </pre>
trans1 :: (forall x. f x -> g x) -> Day f h a -> Day g h a

-- | Apply a natural transformation to the right-hand side of a Day
--   convolution.
--   
--   This respects the naturality of the natural transformation you
--   supplied:
--   
--   <pre>
--   <a>contramap</a> f <a>.</a> <a>trans2</a> fg = <a>trans2</a> fg <a>.</a> <a>contramap</a> f
--   </pre>
trans2 :: (forall x. g x -> h x) -> Day f g a -> Day f h a
instance Contravariant (Day f g)
instance (Typeable1 f, Typeable1 g) => Typeable1 (Day f g)
