diff --git a/docs/src/main/tut/datatypes/functionk.md b/docs/src/main/tut/datatypes/functionk.md index f2fe719c8a..53e1cb1070 100644 --- a/docs/src/main/tut/datatypes/functionk.md +++ b/docs/src/main/tut/datatypes/functionk.md @@ -121,3 +121,20 @@ type ErrorOr[A] = Either[String, A] val errorOrFirst: FunctionK[List, ErrorOr] = λ[FunctionK[List, ErrorOr]](_.headOption.toRight("ERROR: the list was empty!")) ``` + +## Natural Transformation + +In category theory, a [natural transformation](https://ncatlab.org/nlab/show/natural+transformation) provides a morphism between Functors while preserving the internal structure. It's one of the most fundamental notions of category theory. + +If we have two Functors `F` and `G`, `FunctionK[F, G]` is a natural transformation via parametricity. That is, given `fk: FunctionK[F, G]`, for all functions `A => B` and all `fa: F[A]` the following are equivalent: +```Scala +fk(F.map(fa)(f)) <-> G.map(fk(fa))(f) +``` + +We don't need to write a law to test the implementation of the `fk` for the above to be true. It's automatically given by parametricity. + +Thus natural transformation can be implemented in terms of `FunctionK`. This is why a parametric polymorphic function `FunctionK[F, G]` is sometimes referred as a natural transformation. However, they are two different concepts that are not isomorphic. + +For more details, Bartosz Milewski has written a great blog post titled +["Parametricity: Money for Nothing and Theorems for Free"](https://bartoszmilewski.com/2014/09/22/parametricity-money-for-nothing-and-theorems-for-free/). +