Brandon Ling

Relating categories with functors

September 14, 2020category theory

Tl;dr We introduce functors, which allow us to relate different categories. As an applied example, we think of database schemas as categories and database instances as functors.

We often want to relate one category to another. Perhaps we see that one category is embedded inside of another one, or that we can simplify our view of a category by mapping it onto a less complex one, or that one category is in some sense the same as another one. Functors formalize these ideas. They’re like the mathematical version of analogies.

A functor FF from a category C\mathcal{C} to a category D\mathcal{D}, written as F:CDF: \mathcal{C} \to \mathcal{D}, associates an object F(c)F(c) in D\mathcal{D} for every object cc in C\mathcal{C} and a morphism F(f):F(c1)F(c2)F(f): F(c_1) \to F(c_2) in D\mathcal{D} for every morphism f:c1c2f: c_1 \to c_2 in C.\mathcal{C}.

Furthermore, FF must respect the structure that defines a category, namely identities and composition. This means that

F(idc)=idF(c)F(id_c) = id_{F(c)}

for every cc in C\mathcal{C} and that for any three objects c1,c2,c3c_1, c_2, c_3 and morphisms f:c1c2,g:c2c3f: c_1 \to c_2, g: c_2 \to c_3 in C\mathcal{C},

F(gf)=F(g)F(f)F(g \circ f) = F(g) \circ F(f)

in D\mathcal{D}.

In plain words, these equations say that FF maps identity morphisms to identity morphisms and that a composition of two morphisms is mapped to the composition of the mappings of the two morphisms.

Examples of functors

Diagrams

Our pictures of categories, now referred to as diagrams, are in fact functors! Formally, a diagram DD of shape J\mathcal{J} in C\mathcal{C} is a functor D:JCD: \mathcal{J} \to \mathcal{C}.

This definition really confused me when I first encountered it, until I realized that what we draw is the image of the functor. This is a lot like when we plot a function, say, the parabola y=x2y = x^2, we often say that the graph is the function. Here’s a picture that illustrates what I mean:

The diagram on the right really means the functor shown on the left.
The diagram on the right really means the functor shown on the left.

In this picture PP is a category with two objects aa and bb with two morphisms ff and gg that go from aa to bb. I’ve also drawn a few sets in the category Set\mathbf{Set}1 and a few arrows representing functions between them. We want a diagram DD of this shape relating Bool\mathbf{Bool} to N\mathbb{N}. DD sends aa to Bool\mathbf{Bool} and bb to N.\mathbb{N}. DD also selects two functions from Bool\mathbf{Bool} to N\mathbb{N} to map ff and gg to: ff to k:BoolN,k: \mathbf{Bool} \to \mathbb{N}, and gg to h:BoolNh: \mathbf{Bool} \to \mathbb{N}.

To the right of the dotted line, I’ve drawn the image of the diagram DD, which is what we would normally draw for DD.

Isomorphic categories and a category of categories

Each category C\mathcal{C} has an identity functor idC:CCid_{\mathcal{C}}: \mathcal{C} \to \mathcal{C} which, as you might guess, takes each object to itself and each morphism to itself.

Our notation for identity functors and general functors between categories is really similar to the notation used for morphisms within a category. This is no coincidence.

We can define a category of categories by taking the objects to be categories and the morphisms to be functors between categories.

Composition of two functors F:ABF: \mathcal{A} \to \mathcal{B} and G:BCG: \mathcal{B} \to \mathcal{C} is given by the functor GF:ACG \circ F: \mathcal{A} \to \mathcal{C} defined by sending objects aa of AA to G(F(a))G(F(a)) and morphisms f:xyf: x \to y of A\mathcal{A} to G(F(f)):G(F(x))G(F(y)).G(F(f)): G(F(x)) \to G(F(y)).

Following our discussion of isomorphisms in my last post, two categories C\mathcal{C} and D\mathcal{D} are isomorphic if there are functors F:CDF: \mathcal{C} \to \mathcal{D} and G:DCG: \mathcal{D} \to \mathcal{C} such that

GF=idCandFG=idD.G \circ F = id_\mathcal{C} \quad \text{and} \quad F \circ G = id_\mathcal{D}.

Isomorphic categories have exactly the same structure.

An example of isomorphic categories. To prevent cluttering the picture, I’ve drawn the mapping between objects
 as double arrowed dotted lines. Notice that the mapping of morphisms is uniquely determined by the mapping of objects in this example.
An example of isomorphic categories. To prevent cluttering the picture, I’ve drawn the mapping between objects as double arrowed dotted lines. Notice that the mapping of morphisms is uniquely determined by the mapping of objects in this example.

Embedding one category within another

Going from a smaller category C\mathcal{C} to a larger category D\mathcal{D} (in terms of objects), we can think of a functor as embedding C\mathcal{C} in D\mathcal{D} if no information is lost, i.e., no objects or morphisms in C\mathcal{C} are collapsed together in D\mathcal{D}.

There are multiple embeddings of the category on the left to the category on the right.
 Again, the mapping of morphisms is determined by the mapping of the objects in this example.
 Can you come up with any more embeddings?
There are multiple embeddings of the category on the left to the category on the right. Again, the mapping of morphisms is determined by the mapping of the objects in this example. Can you come up with any more embeddings?

Collapsing categories

Example from Bool to Set

Recall Bool\mathbf{Bool} is the two-element preorder given by false true. We can define a functor F:BoolSetF: \mathbf{Bool} \to \mathbf{Set} by F(false)=F(true)=[0,1]F(\text{false}) = F(\text{true}) = [0, 1] where [0,1][0,1] is the set of all real numbers in between and including 0 and 1. FF sends :falsetrue≤: \text{false} \to \text{true} to f:[0,1][0,1]f: [0, 1] \to [0,1] defined by f(x)=x2f(x) = x^2 for all xx in [0,1].[0, 1].

Constant functors

An extreme case is a constant functor, which maps all objects to a single object cc in the target category and all morphisms to the identity morphism idcid_c.

A constant functor maps all objects to a single object in another category and maps
all morphisms to that object’s identity morphism.
A constant functor maps all objects to a single object in another category and maps all morphisms to that object’s identity morphism.

Nonexamples of functors

In the picture below, on the left we have a preorder C\mathcal{C} that consists of three objects c,c,cc, c', c'' where both cc and cc'' are c≤ c' (the corresponding arrows are labeled ff and gg). On the right is a preorder D\mathcal{D} with three objects d,d,dd, d', d'' where dddd ≤ d' ≤ d'' (the corresponding arrows are labeled ff' and gg').

I’ve also drawn a mapping of objects and morphisms of C\mathcal{C} to D\mathcal{D} which is not a functor. The mapping respects the direction of ff, but it reverses the direction of gg, in the sense that gg has source cc'', which maps to dd'', and target cc', which maps to dd', but gg is mapped to gg' which has source dd' and target dd''.

An example of a mapping between categories that is not a functor. It doesn’t preserve the direction of the arrow g.
An example of a mapping between categories that is not a functor. It doesn’t preserve the direction of the arrow g.

As we just saw, if a mapping of categories from C\mathcal{C} to D\mathcal{D} reverses morphisms, then the mapping can’t be a functor unless it reverses all the morphisms, in which case it could be a functor from the opposite category Cop\mathcal{C}^{\text{op}} to D\mathcal{D} (as long as it preserves identities and composition of course). Such a functor is known as a contravariant functor. A regular functor is referred to as a covariant functor.

This mapping of C to D is not a functor from C to D since it reverses all the morphisms,
 but it is a functor from the opposite category of C to D. 
 To see this, try drawing the same picture but with the opposite category of C.
This mapping of C to D is not a functor from C to D since it reverses all the morphisms, but it is a functor from the opposite category of C to D. To see this, try drawing the same picture but with the opposite category of C.

An application: database schemas and instances

A database schema C\mathcal{C} is essentially a finitely-presented category with path equations.

By finitely-presented category, we mean that the category is obtained by interpreting a finite graph as a category (taking vertices as objects and arrows as morphisms), and any relationships between morphisms (often thought of as constraints or business rules) are given by path equations.

Here’s an example schema for a university that is pretty self-explanatory:

A simple schema for a university.
A simple schema for a university.

We have a constraint Dept.chair.worksIn = Dept, which says that the chair of a department works in that department. This constraint leads to other constraints, like Professor.worksIn.chair.worksIn.chair = Professor.worksIn.chair, which amounts to saying that a professor’s department chair’s chair is themself.

An instance (in time) of a database schema C\mathcal{C}, i.e., actual data, is a functor from C\mathcal{C} to Set. One way to think about this is that the schema is the abstract structure, and the functor is a representation of that structure in the form of concrete data.

Here is a schema C\mathcal{C}:

An example abstract database schema.
An example abstract database schema.

We can give this a concrete representation as a database instance by defining a functor F:CSetF: \mathcal{C} \to \textbf{Set} by setting F(a)F(a) to be the set of all college students in the US, F(b)F(b) to be the set of all students at a given university XX, and F(c)F(c) to be the power set of all courses at XX.

F(f)F(f) selects out the all students at the university XX who got all A’s, F(g)F(g) maps students at XX to the courses they’re taking, and F(h)F(h) maps students at XX to the courses they got at least a B in.

If we first filter by the students that get an A in all their courses, then those students’ courses are the same as the courses that they at least got a B in. In other words, F(g)F(h)F(g) \neq F(h), but F(g)F(f)=F(h)F(f)F(g) \circ F(f) = F(h) \circ F(f).

Graphs as database instances

We can even view graphs as database instances of the schema given by the category Gr\mathbf{Gr}:

A diagram of the category Gr representing a schema for graphs.
A diagram of the category Gr representing a schema for graphs.

Gr\mathbf{Gr} has two objects, one labelled arrow\text{arrow} and one labelled vertex\text{vertex}. There are two morphisms from arrow\text{arrow} to vertex\text{vertex} labelled source\text{source} and target\text{target}.

As an example, we can view the graph GG pictured below as a functor G:GrSetG: \mathbf{Gr} \to \mathbf{Set}, where G(vertex)={1,2,3,4,5,6}G(\text{vertex}) = \{1, 2, 3, 4, 5, 6 \}, G(arrow)={a,b,c,d,e,f,g}G(\text{arrow}) = \{a, b, c, d, e, f, g \} where

a:15b:42c:12d:54e:53f:54g:21,a: 1 \to 5 \\ b: 4 \to 2 \\ c: 1 \to 2 \\ d: 5 \to 4 \\ e: 5 \to 3 \\ f: 5 \to 4 \\ g: 2 \to 1,

G(source)G(\text{source}) maps each arrow to its source vertex, and G(target)G(\text{target}) maps each arrow to its target vertex.

A graph G as a database instance of Gr.
A graph G as a database instance of Gr.

As is discussed in Seven Sketches in Compositionality, you can use functors between database schemas to create special functors to migrate data. The benefit is that you can reason with them and prove that a data migration won’t fail.

Do functors form categories?

Functors relate categories to one another, but can we also think of functors forming their own categories? The answer is yes, and categories whose objects can be interpreted as functors are known as functor categories.

But what are the morphisms in such a category? How do we relate one functor to another? This will be the topic of my next category theory post natural transformations.

References

See chapter 3 of Seven Sketches in Compositionality for much more detail on all of the topics covered here and more.


  1. Recall that Set\mathbf{Set} is the category of sets, where sets are the objects and functions between sets are the morphisms.

Written by Brandon Ling — physicist now developer.