## (Covariant) Functor

Initually, functor is a mapping from one category to another, which preserves the structure of the origin one.

Formally, functor is defined as

A functor $F:C→D$ between categories $C$ and $D$ is a mapping of objects to objects and arrows to arrows, in such a way that:

• $F(f:A→B)=F(f):F(A)→F(B)$
• $F(g\cdot f)=F(g)\cdot F(f)$
• $F(1_A)=1_{F(A)}$

class Functor f where
fmap ∷ (a → b) → f a → f b


## Contravariant1 Functor

A contravariant functor is like a functor but it reverses the directions of the morphisms. —— nLab

Basically it's the "reversed" version of covariant functor.

class Contravariant f where
contramap ∷ (b → a) → f a → f b


## Bi(nary )Functor

Bifunctor is a functor which domain is the product of two categories.

ie.

For $C_1$, $C_2$ and $D$ categories, a functor $F:C_1\times C_2→D$ is a bifunctor.

class Bifunctor f where
bimap ∷ (a → c) → (b → d) → f a b → f c d


Examples of bifunctor include Either and (,).

instance Bifunctor (,) where
bimap f g (x , y) = (f x , g y)

instance Bifunctor Either where
bimap f g = either (Left . f) (Right . g)


## Profunctor

A Profunctor is just a bifunctor that is contravariant in the first argument and covariant in the second. What's the problem? —— School of Haskell

So we just "reverse" the first argument of Bifunctor:

class Profunctor f where
dimap ∷ (c → a) → (b → d) → f a b → f c d


A good example of profunctor is (->):

instance Profunctor (->) where
dimap ca bd ab = bd . ab . ca

1

If you are familiar with "tradition" programming languages like Java or C#, you may have heard of "covariant" and "contravariant" before. For example, if type A is subtype of B, then IEnumerable<A> is subtype of IEnumerable<B>, so IEnumerable<T> is covariant on T. And similarly, Action<T> is contravariant on T. We can regard covariant and contravariant functors as more abstract (we weaken relationship from subtype to arbitrary binary relation) version of these types.