Sat Jun 16 22:38:31 EDT 2018

Contravariant functor


It's clear in the definition of an example

contramap :: ( a -> b ) -> ( b -> Bool ) -> ( a -> Bool )
contramap f b = b . f

It is obviously the same when Bool is generalized to t.

Contrast this with an example of a covariant functor:

map :: ( a -> b ) -> ( Bool -> a ) -> ( Bool -> b )
map f a =  f . a

So one way to look at it is to see whether it transforms the output or
the input of something.

The a profunctor bundles the two cases in one.  E.g. both input and
output are transformed.  To make this more clear, use i and o type
parameters to draw the analogy with input and output:

dimap :: (o -> o') -> (i' -> i) -> p i o -> p i' o'

Or separately:

lmap :: (i' -> i) -> p i o -> p i' o   -- imap
rmap :: (o -> o') -> p i o -> p i o'   -- omap

So (->) is a profunctor, as are Arrow instances.


The latter mentions that Profunctors are more restricted than
pipelines, in that they just express how their ends can be adapted.
I.e. there is no composition mechanism such as for e.g. Arrow.

  The whole hierarchy of constraints involves Profunctor, Category,
  Strong, Choice, Arrow, and others.



  Contravariant itself may seem a bit surprising at first. The usual
  idea is that if f is contravariant, then its type argument only
  appears in a negative position. What does that mean? That it appears
  on the left side of an odd number of function arrows. For instance:

  a  -- positive position
  a -> Bool -- negative position
  (a -> Bool) -> Bool -- positive position
  ((a -> Bool) -> Bool) -> Bool -- negative position
  a -> Bool -> Bool = a -> (Bool -> Bool) -- negative position