Bifunctors
Functors are themselves morphisms in the category which is the category of categories. They map one category to another. This means we can sometimes think of them as functions from one category to another category. Especially in .
This means that functors can take more than one argument, and here we will go over a bifunctor (or binary functor), which is a functor in two arguments. Functor has kind while bifunctor has kind .
In parallel with the functor which maps objects to objects the bifunctor maps pairs of objects to another category. Given two categories and the bifunctor maps the objects and to an object . It's a mapping from a Cartesian product of categories . Each object is itself a category.
And because functors map morphisms as well the bifunctor maps a pair of morphisms, one from each category to the product category. This composition is satisfied as per the categorical rules (it is associative and has identity).
These morphisms though are an actual set, the hom-set for the given objects in the category.
Bifunctor typeclass in Haskell:
Product and coproduct are bifunctors
Product as a bifunctor
The product of two objects, the categorical product, is a bifunctor. If a product exists for any pair of objects then the mapping from those objects to the product is bifunctorial.
The pair constructor is the simplest product (as we found before), and here is it's Bifunctor instance:
The action of the bifunctor here is to make pairs of types:
Coproduct as a bifunctor
The type is itself a bifunctor, here is it's instance implementation:
Algebraic Data Types are functorial
Since ADTs are constructed from simpler data types, and we know that product and coproduct are functorial, it then follows that ADTs are also functorial as long as the type itself is parameterized (which is one of the requirements for a type to be a functor, it has kind ).
Constructors that have no dependency on the functors type parameter are equivalent to the functor while those that simply encapsulate the type are equivalent to the functor. These are the primitives used in the product and coproduct to construct ADTs.
Now we can see types in a different light. is a coproduct type which is functorial, and is therefore isomorphic to of the and functors:
This means that is the composition of the bifunctor with two functors and . is actually a bifunctor but here it is used partially applied.