Some type structures in Haskell, and type theory in general, are inspired by algebraic objects in category theory. For example, there are correspondences between
Functor in Haskell and categorical functors;
Applicative functors in Haskell and lax monoidal/closed functors (with some more properties) in category theory;
Monad in Haskell and monads in category theory.
Functors and Functors
In Haskell, Functor is a typeclass defined by
classFunctorfwherefmap::(a->b)->fa->fb
with two properties:
(Identity) fmap id = id,
(Composition) fmal (f . g) == fmap f . fmap g.
Note that sometimes we also see (<$) :: a -> f b -> f a or ($>), but these are just variations of fmap. Examples are omitted as they can be found abundantly online.
In mathematics, a functor between categories C and D is a mapping that
associates an object X∈obC to an object FX=F(X)∈obD,
and associates a morphism f:X→Y∈HomC(X,Y) to a morphism Ff=F(f)∈HomD(FX,FY) subject to the following conditions
(Identity) for any X∈C, we have F(idX)=idF(X);
(Composition) for any morphism f:X→Y, g:Y→Z in C, we have F(g∘f)=F(g)∘F(f);
Correspondence
With the above notation, f in Haskell is exactly the categorical functor on objects, while fmap is the categorical functor on morphisms. This had to be split into two different things because of the overloading of the functor in mathematics. The functor laws between the two are basically identical, taking the type inference in the Haskell version in to account.
Parametrised polymorphic functions and Natural transformations
In Haskell, a (parametrised) polymorphic function is a function parametrised over some of it's types, for example:
id::foralla.a->aappend::foralla.[a]->[a]->a
Parametricity is a property of polymorphic functions: for (some) polymorphic functions f parametrised on type a, and for any function g :: a -> b, we have f . (fmap g) = (fmap g) . f. (As always, the omitted types due to Haskell's type inference is making things hard to understand, more clarity can be found in the mathematics below.) In his well-known paper Theorems for Free1 (based by a paper by Reynolds), Wadler explains that all (parametrised) polymorphic functions have this parametricity property and gives a strategy to find the "theorem" for any polymorphic function.
The parametric polymorphism condition on functions restricts them to being (some sort of) natural transformation, even though it is not the case that all indexed families of morphisms are natural transformations.
An outline of "every parametrised polymorphic function is a natural transformation" can be found at this stackexchange post, citing Reynold's paper.
Note, we are not being fully assertive about the correspondence because some functors have contravariance, leads to a more general idea of dinaturality.
In mathematics, a natural transformation is a mapping between functors. For functors F,G:C→D, a natural transformation η:F→G is a collection of morphisms {ηX:F(X)→G(X)}X∈C in D such that the following diagram commutes for every morphism f:X→Y∈C.
The commutativity of the diagram is the same as saying ηY∘F(f)=G(f)∘ηX.
More genersally, a dinatural transformation adds one edge to each of the two branches to account for contravariance in the domain and the codomain, leading to a hexagonal shape rather than a square. The contravariant parts reverse the direction of the function f. For a concrete example, see filter below.
Correspondence
It is pretty clear that parametrised polymorphic functions have some correspondence to natural transformations, and parametricity corresponds to the commutativity of the diagram. To give more clarity to the Haskell version, we describe it more explicitly. Let F,G :: * -> * be (covariant) functors and η :: forall t. F t -> G t be a polymorphic function. Then parametricity we stated above says that for any function f :: a -> b,
η .fmapf=fmapf. η
To break down the types, the left has η :: F b -> G b (where b is the codomain of f) and fmap f :: F a -> F b. The right has η :: F a -> G a (where a is the domain of f) and fmap f :: G a -> G b. These are deduced in Haskell with type inference.
Examples
Here are some standard examples (see [Wadler1, Figure 1]).
Notation. For a polymorphic function η:∀A.F(A)→G(A) we write ηX:F(X)→G(X) (as above) for the polymorphic function applied to a specific type X.
head :: forall a. [a] -> a
This is a natural transformation from the list functor L to the identity functor Id.
Given a function f:X→Y, the parametricity property follows: headY∘L(f)=Id(f)∘headX
simplified: headY∘L(f)=f∘headX
in haskell: head . fmap f = f . head
(++) :: forall a. [a] -> [a] -> [a]
This is a natural transformation from the product of list functors L×L:∗×∗→∗ (defined as you would expect on products) to the list functor L.
Note that we "uncurry" this (ie. apply tensor-hom adjuction) so that this fits into the above definitions of natural transformation. Hence why we use the product L×L.
Given a function f:X→Y, the parametricity property follows: (++)Y∘(L×L)(f)=L(f)∘(++)X
simplified: (++)Y∘(L(f)×L(f))=L(f)∘(++)X
in haskell: (++) (fmap f xs) (fmap f ys) = fmap f ((++) xs ys)
or with infix: (fmap f xs) ++ (fmap f ys) = fmap f (xs ++ ys)
filter :: forall a. (a -> Bool) -> [a] -> [a] (hard)
This example is in fact not natural, not even extranatural, but a dinatural transformation (a generalisation of natural transformation)
We include this anyway, to show how to obtain Wadler's "theorem" for filter
This is a dinatural transformation from Hom(−,Bool)×L:∗op×∗→∗ to the list functor L:∗op×∗→∗ (deformed in such a way to ignore it's contravariant argument).
Here, we uncurried so we can have two functors.
Recall the (contravariant) Hom(−,Bool) functor is defined such that on types X,
A comment on parametric functions on multiple variables
The analogous concept is collections of morphisms with multiple indexing variables, where we can be eg. natural in one variable and extranatural in another. This leads to multiple properties that they satisfy. An easy example is the evaluation map evalX,Y:Hom(Y,X)×Y→X (the counit of the tensor-hom adjunction), which is natural in X with commutative diagram
and extranatural in Y (because fixing X in Hom(Y,X) makes that component contravariant) with:
In Haskell we can write eval :: forall a. forall b. (a -> b) -> a -> b for the evaluation function. Then naturality, or "parametricity", will give two properties:
("for X") for all f :: a -> a', we have f . (eval g) = eval (f . g),
("for Y") for all f :: b -> b', we have eval (g . f) x = eval g (f x),
which are both pretty obvious properties you would expect from an evaluation function. This idea can probably be extended to functions parametrised over multiple types.
(associativity) m >>= (\x -> k x >>= h) = (m >>= k) >>= h.
Note that in Prelude, we see an additional method (>>) :: m a -> m b -> m b which is derived from >>= by m >> k = m >>= (\_ -> k). This is just included for convenience and is not required to define a Monad. Also the definition of Monad in Haskell requires m to be Applicative, but that can be derived from the methods here.
In mathematics, a monad is a monoid object in the category of endofunctors. More precisely, for a category C, the endofunctors of the category End(C)=Hom(C,C) form a category where objects are endofunctors, morphisms are natural transformations and composition is vertical composition ∘v of natural transformations (we may write this as just ∘). Furthermore, this is a strict monoidal category with the unit object id=idC, tensor product of objects given by composition of functors and tensor product of morphisms is horizontal composition ∘h of natural transformations. Hence a monad (with respect to C) is a monoid object M in the monoidal category End(C). That is, M∈End(C) equipped with natural transformations
(unit) η:id→M,
(multiplication) μ:M∘M→M,
such that the following diagrams commute:
(associativity)
(unit)
where M⋅μ:M∘(M∘M)→M∘M etc. denotes whiskering (horizontal composition with the identity natural transformation idM, see Appendix A1).
Equationally, these diagrams correspond to the relations
(associativity) μ∘v(μ⋅M)=μ∘v(M⋅μ),
(unit) μ∘v(η⋅M)=μ∘v(M⋅η)=idM.
Correspondence
Note: we take advantage of having elements in the objects in our category, but proofs purely from morphism compositions can also be written down (although difficult).
We first check that the structure maps agree.
the pure/return function return :: a -> m a corresponds the unit natural transformation ηA:A→MA.
The bind function >>= (which we will write as β, where βA,B:MA×Hom(A,MB)→MB) appears to be completely different from the multiplication map μ, but can be constructed from one another.
(>>= to μ)
μ is called join in Haskell, and is defined using >>= by
join::m(ma)->majoinx=x>>=id
where id is the identity function id x = x
Mathematically, μA=βMA,A(−,idMA):M2A→MA (partial application of β)
and we have the categorical left-unit relation μ∘(η⋅M)=idM (which, at B, is μB∘(ηMB)=idMB).
Right Unit
We have βA,A(m,ηA)=μA∘M(ηA)(m)=m, by the categorical right-unit relation μ∘(M⋅η)=idM (which, at A, is μA∘(M(ηA))=idMA).
Associativity
The right hand side is βB,C(βA,B(m,f),g)
=βB,C(μB∘M(f)(m),g)
=μC∘M(g)(μB∘M(f)(m))
=μC∘M(g)∘μB∘M(f)(m).
The left hand side is βA,C(m,βB,C(f(−),g))
=βA,C(m,μC∘M(g)∘f)
=μC∘M(μC∘M(g)∘f)(m)
=μC∘M(μC)∘M2(g)∘M(f)(m)
by functoriality of M
=μC∘μMC∘M2(g)∘M(f)(m)
by the categorical associativity relation μ∘(M⋅μ)=μ∘(μ⋅M). At C, this is μC∘M(μC)=μC∘μMC
=μC∘M(g)∘μB∘M(f)(m)
by naturality of μ
which is the same as the right hand side.
Relations: Haskell to Cats
We can also use the Monad properties and relations in Haskell to show the categorical monad properties also hold.
We still work in the math world, assuming the relations noted in the start of the previous section and assuming β and η are (di)natural in each component (this is sensible because such properties always exist for polymorphic functions (eg. the Monad structure maps), see Theorems for free!1 on parametricity).
Since μ doesn't exist in Haskell, we use the translation mentioned before μA=βMA,A(−,idMA).
Left Unit
We want to prove that μ∘(η⋅M)=idM. The component at A is μA∘ηMA=idMA. The left hand side applied to x∈A is μA∘ηMA(x)=βMA,A(−,idMA)∘ηMA(x)
=βMA,A(ηMA(x),idMA)
=idMA(x)=x
by the Haskell left-unit relation.
Right Unit
We want to prove that μ∘(M⋅η)=idMA. The component at A is μA∘M(ηA)=idMA. The left hand side applied to x∈A is μA∘M(ηA)(x)=βMA,A(−,idMA)∘M(ηA)(x)
=βMA,A(M(ηA)(x),idMA)
=βA,A(x,idMA∘ηA)=βA,A(x,ηA)
by extranaturality of β
=x=idMA(x)
by the Haskell right-unit relation.
Associativity
We want to prove that μ∘(μ⋅M)=μ∘(M⋅μ). The component at A is μA∘μMA=μA∘M(μA). The left hand side applied to x∈M3A is μA∘μMA(x)=βMA,A(−,idMA)∘βM2A,MA(−,idM2A)(x)
Applicative Functors and Lax Monoidal/Closed Functors
Applicative functors were first defined for computer science as a generalisation of monads. As a result, the laws defined are mathematically unwieldly. In addition to the complexity of the structure of closed monoidal categories and closed/monoidal functors, I have not worked out all of them (likely due to not fully understanding closed categories) and probably will not anytime soon.
(composition) pure (.) <*> u <*> v <*> w = u <*> (v <*> w).
The structure maps are related to fmap by fmap f x = pure f <*> x, which is a consequence of the previous laws.
In mathematics, a lax closed functor is a structure preserving map F:C→D between closed categories with
a natural transformation F^A,B:F([A,B]C)→[FA,FB]D, natural in A,B
a morphism η1F:1D→F(1C)
that satisfy particular commuting diagrams (see MF1, MF2, MF3 in Chapter 2 Section 1 of 2). We work with this over lax monoidal functors (these are equivalent: see Appendix A2) because the structure maps already line up in this case. If we assume that C and D are closed monoidal, then this is equivalent to a lax monoidal functor. We also need one more thing, which is if F is an endofunctor (i.e. C=D) then we can define tensorial strength: a natural isomorphism σ:X⊗FY∼F(X⊗Y) satisfying certain commuting diagrams.
Note: Tensorial strength is particularly defined for the monoidal structure. There is an equivalent natural transformation for closed endofunctors tA,B:[A,B]→[FA,FB] that deals with enrichment of endofunctors. The correspondence was studied by Kock 3 (also see Stack Exchange, nLab (Idea)), called "strengths". I have not found how to use it.
Correspondence (Cats to Haskell)
I have only worked out some of the correspondence in this direction: showing that Haskell Applicative is indeed a lax closed functor. We are choosing to work with closed functors because the structure maps line up nicely, so we don't need to translate everything to the monoidal functor world. The only downside is that tensorial strength doesn't work nicely here, and I don't know how to use it's closed functor counterpart.
The structure maps are almost the same between Applicative and lax closed functors, however pure is parametrised whereas η1F is only defined on the unit object. Paterson and McBride's paper4 describes how η1F can be extended to a natural transformation ηAF using tensorial strength:
ηAF:ArA−1A⊗1A⊗η1FA⊗F(1)σA,1F(A⊗1)FrAFA
which evaluates to η1F when A=1. This is natural in A because functors preserve naturality, vertical composition of naturals is natural, and each component is natural in A.
The Applicative relations can be written mathematically as
for u∈F[B,C],v∈F[A,B],w∈FA and LB,CA is the composition structure map in the closed category.
The last two of these will not be proven, so I'm not sure if they are the best way to translate the rules to mathematics. Also, since these axioms are defined in a category similar to Set, we may take the liberty to think of 1={∗}, [A,B]=Hom(A,B) and jA(∗)=idA, see Eilenberg-Kelly2 (2.4).
Identity
By construction the map j in the definition of closed categories "picks out the identity morphism", so we have jA(∗)=idA as mentioned above. The following diagram commutes
where the left square commutes by naturality of ηF and the right square by property CF12 of closed functors. Note that the bottom two arrows are identified, so the left-top branch is the same as the right arrow, i.e. F^A,A∘η[A,A]F∘jA(∗)=jFA(∗). Therefore
We first prove the "bonus" identity in the Applicative definition, fmap f x = pure f <*> x.
For a morphism f:A→B have the commutative diagram
where the left square commutes by property CF12 of closed functors, and the right square commutes by naturality of F^A,B in A. If we write jf:=[A,f]∘jA, then the diagram becomes
which is the relation jFf=F^A,B∘Fjf∘η1F. Then we have the diagram
where the outside rectangle is the above diagram, and the top-left triangle commutes by naturality of ηF. Then the bottom right triangle commutes, which is that
jFf=F^A,B∘η[A,B]F∘jf.
Evaluating at ∗, we get exactly Ff=F^A,B∘η[A,B]F(f).
With this fact, we can prove the homomorphism relation with ease. Applying the above to the left side of the relation, we have (F^A,B∘η[A,B]F(f))(ηAF(x))=Ff(ηAF(x))=ηBF(f(x)), where the second equality is naturality of ηF.
Others?
They are hard, but feel free to try it yourself...
Applicatives were introduced in the paper by Paterson and McBride, Applicative programming with effects5 under the name of "Idiom". In Section 7, they also suggest the correspondence between Applicative and lax monoidal functors with tensorial strength, but without proof.
Appendix
A1. Horizontal and vertical composition of natural transformations
Definition. (Vertical composition) Let F,G,H:C→D be functors and α:F→G, β:G→H be natural transformations. Define the vertical composition of these natural transformations to be the natural transformation β∘vα:F→H, with X∈C component (β∘vα)X:=βX∘αX.
This is the usual composition of morphisms in the category of endofunctors, so it is often just written ∘.
Definition. (Horizontal composition) Let F1,G1:C→D, F2,G2:D→E be functors and α:F1→G1, β:F2→G2 be natural transformations. Define the horizontal composition (or Godement product) of these natural transformations to be the natural transformation β∘hα:F→H, with X∈C component
(β∘hα)X:=βG1(X)∘F2(αX)
or (β∘hα)X:=G2(αX)∘βF1(M).
These two expressions are equal by the interchange law of Cat (the 2-category of small categories).
This operation is a monoidal product in any monoidal category of endofunctors.
To make sense of these, lets apply this to the special case of whiskering. Let F,G:C→D and H:D→E be functors, and α:F→G be a natural transformation. Then define left and right whiskering to be
H⋅α:=idH∘hα:H∘F→H∘G
and α⋅H:=α∘hidH:F∘H→G∘H,
where idH:H→H is the identity natural transformation. Explicitly, these are natural transformations with the X∈C components
(H⋅α)X=(idH∘hα)X=(idH)G(X)∘H(αX)=H(αX),
(α⋅H)X=(α∘hidH)X=αH(X)∘F((idF)X)=αH(X).
If we had defined this independently of horizontal composition, then we can alternatively write the definition of horizontal composition as
β∘hα:=(β⋅G1)∘v(F2⋅α)
or β∘hα:=(G2⋅α)∘v(β⋅F1).
Notice that left-whiskering is like pasting H onto the left of α and leaving it unchanged, and right-whiskering is like pasting on the right. This hints at a visual interpretation of horizontal composition and the interchange law. These exist! A small taster can be found in Chapter 2.1 of my honours thesis6 in the case of monoidal categories (loop space of a 2-category with one object).
A2. Lax monoidal functors and lax closed functors
There is an equivalence between lax monoidal functors and lax closed functors on closed monoidal categories. Let us assume we are working with such categories, then we describe how the structure maps correspond. We write [X,Y] for the internal homs in these categories, defined to be right adjoint to the monoidal product ⊗. We mainly refer to a conference paper by Eilenberg and Kelly2 that lay out this correspondence and many others in excruciating detail.
A lax monoidal functor is F:C→D with
a natural transformation F~A,B:F(A)⊗DF(B)→F(A⊗CB), natural in A,B,
a morphism ηF:1D→F(1C), where 1 denotes the unit object in the corresponding category
which satisfy particular commuting diagrams (see CF1, CF2, CF3 in Chapter 1 Section 3 of 2).
A lax closed functor is F:C→D with
a natural transformation F^A,B:F([A,B]C)→[FA,FB]D, natural in A,B
a morphism ηF:1D→F(1C)
which satisfy particular commuting diagrams (see MF1, MF2, MF3 in Chapter 2 Section 1 of 2).
Let us write πA,B,C:Hom(A⊗B,C)∼Hom(A,[B,C]) for the natural isomorphism defining the adjunction −⊗B⊣[B,−]. If this adjunction was initially defined by the unit ηB:Id→[B,−⊗B] and counit ϵB:[B,−]⊗B→Id of adjunction, then we can describe what π does to maps:
for f∈Hom(A⊗B,C), we have πA,B,C(f)=[B,f]∘ηB,A∈Hom(A,[B,C]), and
for g∈Hom(A,[B,C]), we have πA,B,C−1(g)=ϵB,C∘(g⊗B)∈Hom(A⊗B,C).
With this notation, Eilenberg and Kelly show that if we work with monoidal closed categories, then there the following diagram commutes (2, Chapter 2, (3.23)), giving a correspondence between F^ and F~.
Following the morphism f∈Hom(A⊗B,C) gives the relation
πFA,FB,FC(Ff∘F~A,B)=F^B,C∘F∘πA,B,C(f).
Setting C=A⊗B and f=idA⊗B, this becomes πFA,FB,F(A⊗B)(F~A,B)=F^A,B∘F∘πA,B,A⊗B(id)=F^A,B∘F([B,id]∘ηB,A)=F^B,A⊗B∘F(ηB,A). Therefore
Similarly, if we invert the top and bottom π maps, following a morphism f∈Hom(A,[B,C]) gives the relation
πFA,FB,FC−1(F^B,C∘Ff)=F(πA,B,C−1(f))∘F~A,B
and setting A=[B,C] and f=id[B,C] this becomes πF[B,C],FB,FC−1(F^B,C)=F(π[B,C],B,C−1(id))∘F~[B,C],B=F(ϵB,C∘(id⊗B))∘F~[B,C],B=FϵB,C∘F~[B,C],B. Hence
The other structure morphism ηF just stays the same. What remains is to show that the defining relations of these functors correspond, this can be found in Chapter 2 Proposition 4.3 of 2. A further remark is that the correspondence between F^ and F~ given in Example 3.1 in the nLab Closed Functor7 article gives the same equality, using π and it's inverse to obtain adjuncts, and noting that ηB,A=πA,B,A⊗B(idA⊗B) and ϵB,C=π[B,C],B,C−1(id[B,C]) are adjuncts of the appropriate identity morphism.