Profunctor is a typeclass provided by the
profunctors package in
See the "Remarks" section for a full explanation.
Profunctors are, as described by the docs on Hackage, "a bifunctor where the first argument is contravariant and the second argument is covariant."
So what does this mean? Well, a bifunctor is like a normal functor, except that it has two parameters instead of one, each with its own
fmap-like function to map on it.
Being "covariant" means that the second argument to a profunctor is just like a normal functor: its mapping function (
rmap) has a type signature of
Profunctor p => (b -> c) -> p a b -> p a c. It just maps the function on the second argument.
Being "contravariant" makes the first argument a little weirder. Instead of mapping like a normal functor, its mapping function (
lmap) has a type signature of
Profunctor p => (a -> b) -> p b c -> p a c. This seemingly backward mapping makes most sense for inputs to a function: you would run
a -> b on the input, and then your other function, leaving the new input as
Note: The naming for the normal, one argument functors is a little misleading: the
Functor typeclass implements "covariant" functors, while "contravariant" functors are implemented in the
Contravariant typeclass in
Data.Functor.Contravariant, and previously the (misleadingly named)
Cofunctor typeclass in
(->) is a simple example of a profunctor: the left argument is the input to a function, and the right argument is the same as the reader functor instance.
instance Profunctor (->) where lmap f g = g . f rmap f g = g . g