Let and be categories and and be functors . Then a natural transformation from to is a family of morphism that satisfies the following requirements:
-
For every object in , a natural transformation from the functor to the functor assigns a morphism between objects of . The morphism is called the component of at .
-
Components must be such that for every morphism in we have: (naturality condition)
These requirements can be expressed by the following commutative diagram:
\begin{xy} \xymatrix{ A \ar[r]_{F\ \ \ } \ar[d]_{f} \ar@/^1.5pc/[rr]^{\alpha_{A}\ \circ\ F} & F(A) \ar[r]_{\alpha_{A}} \ar[d]_{F(f)} & G(A) \ar[d]_{G(f)} \\ B \ar[r]^{F\ \ \ } \ar@/_1.5pc/[rr]_{\alpha_{B}\ \circ\ F} & F(B) \ar[r]^{\alpha_{B}} & G(B) } \end{xy}Natural transformations are often denoted as double arrows, , to distinguish them in diagrams from usual morphisms:
\begin{xy} \xymatrix @=5pc { \mathcal{C} \rtwocell<5>^{F}_{G}{\alpha} & \mathcal{D} } \end{xy}In other words, a natural transformation is a way of transforming one functor into another while respecting the internal structure of the categories involved. Natural transformations are one of the most important aspects of category theory. Saunders Mac Lane, one of the founders of category theory, once said:
I didn’t invent categories to study functors; I invented them to study natural transformations.
Example
In Haskell, we can define a natural transformation like so:
Or we could also define it the following way, as an infix operator (~>):
Again, the requirement of compatibility with the actions of the functors is not expressible as a type signature, but we can write it down as law in pseudocode:
Now Haskell supports parametric polymorphism, that means that a function will act on all types uniformly and thus automatically satisfies the naturality condition for any polymorphic function of the type:
where F and G are functors. The naturality condition in terms of Haskell means that it doesn’t matter whether we first apply a function, through the application of fmap
, and then change the structure via a structure preserving mapping; or first change the structure, and then apply the function to the new structure, with its own implementation of fmap
. [2]
Lets have a look at the following example:
This function returns Nothing in case of an empty list and the first element of the list in case of an non-empty List. This function is called safeHead
, because there is also a “unsafeHead” in the Haskell standard library, simply called head
. The unsafe variant throws an Exception in case the List is empty. We can prove by equational reasoning (or Coq if you like) that the naturality condition holds in case of safeHead
:
Here are some more natural transformations:
As we can see there is an infinite number of natural transformations.
You can open an interactive Haskell interpreter (ghci), load the functions and test the following examples.
References
- 1.Mac Lane, Saunders (1998), Categories for the Working Mathematician, Graduate Texts in Mathematics 5 (2nd ed.), Springer-Verlag, p. 16, ISBN 0-387-98403-8 ↩
- 2.Natural Transformations by Bartosz Milewski (2015) ↩