contravariant-1.4: Contravariant functors

Copyright | (C) 2014-2015 Edward Kmett
License | BSD-style (see the file LICENSE)
Maintainer | Edward Kmett <ekmett@gmail.com>
Stability | provisional
Portability | portable
Safe Haskell | Safe
Language | Haskell98

Data.Functor.Contravariant.Divisible

Contents

- Contravariant Applicative
- Contravariant Alternative

Description

This module supplies contravariant analogues to the `Applicative` and `Alternative` classes.

Synopsis

- class Contravariant f => Divisible f where
- divided :: Divisible f => f a -> f b -> f (a, b)
- conquered :: Divisible f => f ()
- liftD :: Divisible f => (a -> b) -> f b -> f a
- class Divisible f => Decidable f where
- chosen :: Decidable f => f b -> f c -> f (Either b c)
- lost :: Decidable f => f Void

# Contravariant Applicative

class Contravariant f => Divisible f where #

A `Divisible` contravariant functor is the contravariant analogue of `Applicative`.

In denser jargon, a `Divisible` 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 `Applicative` 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:

    delta a = (a,a)

``divide` `delta`` should be associative with `conquer` as a unit

    divide delta m conquer = m
    divide delta conquer m = m
    divide delta (divide delta m n) o = divide delta m (divide delta n o)

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

    divide f m conquer = contramap (fst . f) m
    divide f conquer m = contramap (snd . f) m
    divide f (divide g m n) o = divide f' m (divide id n o) where
      f' a = case f a of (bc,d) -> case g bc of (b,c) -> (a,(b,c))

Minimal complete definition

divide, conquer

Methods

divide :: (a -> (b, c)) -> f b -> f c -> f a #

conquer :: f a #

The underlying theory would suggest that this should be:

    conquer :: (a -> ()) -> f a

However, as we are working over a Cartesian category (Hask) and the Cartesian product, such an input morphism is uniquely determined to be ``const` `mempty``, so we elide it.

Instances

Divisible U1 # |
Methods divide :: (a -> (b, c)) -> U1 b -> U1 c -> U1 a # conquer :: U1 a #
Divisible Equivalence # |
Methods divide :: (a -> (b, c)) -> Equivalence b -> Equivalence c -> Equivalence a # conquer :: Equivalence a #
Divisible Comparison # |
Methods divide :: (a -> (b, c)) -> Comparison b -> Comparison c -> Comparison a # conquer :: Comparison a #
Divisible Predicate # |
Methods divide :: (a -> (b, c)) -> Predicate b -> Predicate c -> Predicate a # conquer :: Predicate a #
Divisible f => Divisible (Rec1 f) # |
Methods divide :: (a -> (b, c)) -> Rec1 f b -> Rec1 f c -> Rec1 f a # conquer :: Rec1 f a #
Divisible (Proxy *) # |
Methods divide :: (a -> (b, c)) -> Proxy * b -> Proxy * c -> Proxy * a # conquer :: Proxy * a #
Divisible m => Divisible (MaybeT m) # |
Methods divide :: (a -> (b, c)) -> MaybeT m b -> MaybeT m c -> MaybeT m a # conquer :: MaybeT m a #
Divisible m => Divisible (ListT m) # |
Methods divide :: (a -> (b, c)) -> ListT m b -> ListT m c -> ListT m a # conquer :: ListT m a #
Monoid r => Divisible (Op r) # |
Methods divide :: (a -> (b, c)) -> Op r b -> Op r c -> Op r a # conquer :: Op r a #
(Divisible f, Divisible g) => Divisible ((:*:) f g) # |
Methods divide :: (a -> (b, c)) -> (f :*: g) b -> (f :*: g) c -> (f :*: g) a # conquer :: (f :*: g) a #
(Applicative f, Divisible g) => Divisible ((:.:) f g) # |
Methods divide :: (a -> (b, c)) -> (f :.: g) b -> (f :.: g) c -> (f :.: g) a # conquer :: (f :.: g) a #
Monoid m => Divisible (Const * m) # |
Methods divide :: (a -> (b, c)) -> Const * m b -> Const * m c -> Const * m a # conquer :: Const * m a #
Divisible f => Divisible (Alt * f) # |
Methods divide :: (a -> (b, c)) -> Alt * f b -> Alt * f c -> Alt * f a # conquer :: Alt * f a #
Divisible f => Divisible (Reverse * f) # |
Methods divide :: (a -> (b, c)) -> Reverse * f b -> Reverse * f c -> Reverse * f a # conquer :: Reverse * f a #
Divisible f => Divisible (Backwards * f) # |
Methods divide :: (a -> (b, c)) -> Backwards * f b -> Backwards * f c -> Backwards * f a # conquer :: Backwards * f a #
Divisible m => Divisible (WriterT w m) # |
Methods divide :: (a -> (b, c)) -> WriterT w m b -> WriterT w m c -> WriterT w m a # conquer :: WriterT w m a #
Divisible m => Divisible (WriterT w m) # |
Methods divide :: (a -> (b, c)) -> WriterT w m b -> WriterT w m c -> WriterT w m a # conquer :: WriterT w m a #
Divisible m => Divisible (StateT s m) # |
Methods divide :: (a -> (b, c)) -> StateT s m b -> StateT s m c -> StateT s m a # conquer :: StateT s m a #
Divisible m => Divisible (StateT s m) # |
Methods divide :: (a -> (b, c)) -> StateT s m b -> StateT s m c -> StateT s m a # conquer :: StateT s m a #
Divisible f => Divisible (IdentityT * f) # |
Methods divide :: (a -> (b, c)) -> IdentityT * f b -> IdentityT * f c -> IdentityT * f a # conquer :: IdentityT * f a #
Divisible m => Divisible (ExceptT e m) # |
Methods divide :: (a -> (b, c)) -> ExceptT e m b -> ExceptT e m c -> ExceptT e m a # conquer :: ExceptT e m a #
Divisible m => Divisible (ErrorT e m) # |
Methods divide :: (a -> (b, c)) -> ErrorT e m b -> ErrorT e m c -> ErrorT e m a # conquer :: ErrorT e m a #
Monoid m => Divisible (Constant * m) # |
Methods divide :: (a -> (b, c)) -> Constant * m b -> Constant * m c -> Constant * m a # conquer :: Constant * m a #
(Divisible f, Applicative g) => Divisible (ComposeCF f g) # |
Methods divide :: (a -> (b, c)) -> ComposeCF f g b -> ComposeCF f g c -> ComposeCF f g a # conquer :: ComposeCF f g a #
(Applicative f, Divisible g) => Divisible (ComposeFC f g) # |
Methods divide :: (a -> (b, c)) -> ComposeFC f g b -> ComposeFC f g c -> ComposeFC f g a # conquer :: ComposeFC f g a #
Divisible f => Divisible (M1 i c f) # |
Methods divide :: (a -> (b, c)) -> M1 i c f b -> M1 i c f c -> M1 i c f a # conquer :: M1 i c f a #
(Divisible f, Divisible g) => Divisible (Product * f g) # |
Methods divide :: (a -> (b, c)) -> Product * f g b -> Product * f g c -> Product * f g a # conquer :: Product * f g a #
Divisible m => Divisible (ReaderT * r m) # |
Methods divide :: (a -> (b, c)) -> ReaderT * r m b -> ReaderT * r m c -> ReaderT * r m a # conquer :: ReaderT * r m a #
(Applicative f, Divisible g) => Divisible (Compose * * f g) # |
Methods divide :: (a -> (b, c)) -> Compose * * f g b -> Compose * * f g c -> Compose * * f g a # conquer :: Compose * * f g a #
Divisible m => Divisible (RWST r w s m) # |
Methods divide :: (a -> (b, c)) -> RWST r w s m b -> RWST r w s m c -> RWST r w s m a # conquer :: RWST r w s m a #
Divisible m => Divisible (RWST r w s m) # |
Methods divide :: (a -> (b, c)) -> RWST r w s m b -> RWST r w s m c -> RWST r w s m a # conquer :: RWST r w s m a #

divided :: Divisible f => f a -> f b -> f (a, b) #

    divided = divide id

conquered :: Divisible f => f () #

Redundant, but provided for symmetry.

    conquered = conquer

liftD :: Divisible f => (a -> b) -> f b -> f a #

This is the divisible analogue of `liftA`. It gives a viable default definition for `contramap` in terms of the members of `Divisible`.

    liftD f = divide ((,) () . f) conquer

# Contravariant Alternative

class Divisible f => Decidable f where #

A `Divisible` 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.

    choose Left m (lose f)  = m
    choose Right (lose f) m = m
    choose f (choose g m n) o = divide f' m (divide id n o) where
      f' bcd = either (either id (Right . Left) . g) (Right . Right) . f

In addition, we expect the same kind of distributive law as is satisfied by the usual covariant `Alternative`, w.r.t `Applicative`, which should be fully formulated and added here at some point!

Minimal complete definition

lose, choose

Methods

lose :: (a -> Void) -> f a #

The only way to win is not to play.

choose :: (a -> Either b c) -> f b -> f c -> f a #

Instances

Decidable U1 # |
Methods lose :: (a -> Void) -> U1 a # choose :: (a -> Either b c) -> U1 b -> U1 c -> U1 a #
Decidable Equivalence # |
Methods lose :: (a -> Void) -> Equivalence a # choose :: (a -> Either b c) -> Equivalence b -> Equivalence c -> Equivalence a #
Decidable Comparison # |
Methods lose :: (a -> Void) -> Comparison a # choose :: (a -> Either b c) -> Comparison b -> Comparison c -> Comparison a #
Decidable Predicate # |
Methods lose :: (a -> Void) -> Predicate a # choose :: (a -> Either b c) -> Predicate b -> Predicate c -> Predicate a #
Decidable f => Decidable (Rec1 f) # |
Methods lose :: (a -> Void) -> Rec1 f a # choose :: (a -> Either b c) -> Rec1 f b -> Rec1 f c -> Rec1 f a #
Decidable (Proxy *) # |
Methods lose :: (a -> Void) -> Proxy * a # choose :: (a -> Either b c) -> Proxy * b -> Proxy * c -> Proxy * a #
Divisible m => Decidable (MaybeT m) # |
Methods lose :: (a -> Void) -> MaybeT m a # choose :: (a -> Either b c) -> MaybeT m b -> MaybeT m c -> MaybeT m a #
Divisible m => Decidable (ListT m) # |
Methods lose :: (a -> Void) -> ListT m a # choose :: (a -> Either b c) -> ListT m b -> ListT m c -> ListT m a #
Monoid r => Decidable (Op r) # |
Methods lose :: (a -> Void) -> Op r a # choose :: (a -> Either b c) -> Op r b -> Op r c -> Op r a #
(Decidable f, Decidable g) => Decidable ((:*:) f g) # |
Methods lose :: (a -> Void) -> (f :*: g) a # choose :: (a -> Either b c) -> (f :*: g) b -> (f :*: g) c -> (f :*: g) a #
(Applicative f, Decidable g) => Decidable ((:.:) f g) # |
Methods lose :: (a -> Void) -> (f :.: g) a # choose :: (a -> Either b c) -> (f :.: g) b -> (f :.: g) c -> (f :.: g) a #
Decidable f => Decidable (Alt * f) # |
Methods lose :: (a -> Void) -> Alt * f a # choose :: (a -> Either b c) -> Alt * f b -> Alt * f c -> Alt * f a #
Decidable f => Decidable (Reverse * f) # |
Methods lose :: (a -> Void) -> Reverse * f a # choose :: (a -> Either b c) -> Reverse * f b -> Reverse * f c -> Reverse * f a #
Decidable f => Decidable (Backwards * f) # |
Methods lose :: (a -> Void) -> Backwards * f a # choose :: (a -> Either b c) -> Backwards * f b -> Backwards * f c -> Backwards * f a #
Decidable m => Decidable (WriterT w m) # |
Methods lose :: (a -> Void) -> WriterT w m a # choose :: (a -> Either b c) -> WriterT w m b -> WriterT w m c -> WriterT w m a #
Decidable m => Decidable (WriterT w m) # |
Methods lose :: (a -> Void) -> WriterT w m a # choose :: (a -> Either b c) -> WriterT w m b -> WriterT w m c -> WriterT w m a #
Decidable m => Decidable (StateT s m) # |
Methods lose :: (a -> Void) -> StateT s m a # choose :: (a -> Either b c) -> StateT s m b -> StateT s m c -> StateT s m a #
Decidable m => Decidable (StateT s m) # |
Methods lose :: (a -> Void) -> StateT s m a # choose :: (a -> Either b c) -> StateT s m b -> StateT s m c -> StateT s m a #
Decidable f => Decidable (IdentityT * f) # |
Methods lose :: (a -> Void) -> IdentityT * f a # choose :: (a -> Either b c) -> IdentityT * f b -> IdentityT * f c -> IdentityT * f a #
(Applicative f, Decidable g) => Decidable (ComposeFC f g) # |
Methods lose :: (a -> Void) -> ComposeFC f g a # choose :: (a -> Either b c) -> ComposeFC f g b -> ComposeFC f g c -> ComposeFC f g a #
Decidable f => Decidable (M1 i c f) # |
Methods lose :: (a -> Void) -> M1 i c f a # choose :: (a -> Either b c) -> M1 i c f b -> M1 i c f c -> M1 i c f a #
(Decidable f, Decidable g) => Decidable (Product * f g) # |
Methods lose :: (a -> Void) -> Product * f g a # choose :: (a -> Either b c) -> Product * f g b -> Product * f g c -> Product * f g a #
Decidable m => Decidable (ReaderT * r m) # |
Methods lose :: (a -> Void) -> ReaderT * r m a # choose :: (a -> Either b c) -> ReaderT * r m b -> ReaderT * r m c -> ReaderT * r m a #
(Applicative f, Decidable g) => Decidable (Compose * * f g) # |
Methods lose :: (a -> Void) -> Compose * * f g a # choose :: (a -> Either b c) -> Compose * * f g b -> Compose * * f g c -> Compose * * f g a #
Decidable m => Decidable (RWST r w s m) # |
Methods lose :: (a -> Void) -> RWST r w s m a # choose :: (a -> Either b c) -> RWST r w s m b -> RWST r w s m c -> RWST r w s m a #
Decidable m => Decidable (RWST r w s m) # |
Methods lose :: (a -> Void) -> RWST r w s m a # choose :: (a -> Either b c) -> RWST r w s m b -> RWST r w s m c -> RWST r w s m a #

chosen :: Decidable f => f b -> f c -> f (Either b c) #

    chosen = choose id

lost :: Decidable f => f Void #

    lost = lose id