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


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


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

-- | Dual function arrows.
newtype Op a b
Op :: (b -> a) -> Op a b
getOp :: Op a b -> b -> a
instance Typeable1 Predicate
instance Typeable1 Comparison
instance Typeable1 Equivalence
instance Typeable2 Op
instance Contravariant (Op a)
instance Category Op
instance Contravariant Equivalence
instance Contravariant Comparison
instance Contravariant Predicate
instance Contravariant (Proxy *)
instance Contravariant f => Contravariant (Reverse f)
instance Contravariant f => Contravariant (Backwards f)
instance (Functor f, Contravariant g) => Contravariant (Compose f g)
instance Contravariant (Const a)
instance Contravariant (Constant a)
instance (Contravariant f, Contravariant g) => Contravariant (Product f g)
instance (Contravariant f, Contravariant g) => Contravariant (f :+: g)
instance (Functor f, Contravariant g) => Contravariant (f :.: g)
instance (Contravariant f, Contravariant g) => Contravariant (f :*: g)
instance Contravariant (K1 i c)
instance Contravariant f => Contravariant (M1 i c f)
instance Contravariant f => Contravariant (Rec1 f)
instance Contravariant U1
instance Contravariant V1


-- | 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)
