category-theory-illustrated/_chapters/06_functors.md

571 lines
36 KiB
Markdown
Raw Normal View History

2021-08-23 21:49:05 +03:00
---
layout: default
title: Functors
---
2021-10-21 16:46:26 +03:00
Functors
2021-08-10 21:36:14 +03:00
===
2023-02-19 00:41:02 +03:00
From this chapter on, we will change the tactic a bit (as I am sure you are tired of jumping through different subjects) and we will dive at full throttle into the world of categories, using the structures that we saw so far as context. This will allow us to generalize some of the concepts that we examined in these structures and thus make them valid for all categories.
2021-08-10 21:36:14 +03:00
2021-08-19 20:12:49 +03:00
Categories we saw so far
2021-08-10 21:36:14 +03:00
===
2021-08-17 23:10:45 +03:00
2022-09-11 08:56:25 +03:00
So far, we saw many different categories and category types. Let's review them once more:
2021-08-23 21:49:05 +03:00
2021-10-31 02:21:39 +03:00
The category of sets
2021-10-21 16:46:26 +03:00
---
2023-02-19 00:41:02 +03:00
We began by reviewing the mother of all categories - *the category of sets*
2021-10-31 02:21:39 +03:00
![The category of sets](category_sets.svg)
2021-08-23 21:49:05 +03:00
2023-02-19 00:41:02 +03:00
The category of sets contains within itself many other categories, such as the category of types in programming languages.
2021-12-25 19:31:58 +03:00
Special types of categories
2021-10-21 16:46:26 +03:00
---
2021-08-23 21:49:05 +03:00
2023-02-19 00:41:02 +03:00
We also learned about some *special types of categories* each of which has some distinct properties, like categories that have just one *object* (monoids, groups) and categories that have only one *morphism* between any two objects (preorders, partial orders.)
2021-08-23 21:49:05 +03:00
2021-10-21 16:46:26 +03:00
![Types of categories](category_types.svg)
Other categories
---
2023-02-19 00:41:02 +03:00
We also defined a lot of *categories based on different concepts*, like the ones based on logics/programming languages, but also some "less-serious ones", as for example the color-mixing partial order/category.
2021-08-23 21:49:05 +03:00
2021-08-24 23:26:16 +03:00
![Category of colors](category_color_mixing.svg)
2021-08-23 21:49:05 +03:00
2021-10-21 16:46:26 +03:00
Finite categories
---
2023-02-19 00:41:02 +03:00
And most importantly, we saw some categories that are *completely made up*, such as my soccer player hierarchy. Those are formally called *finite categories*.
2021-10-21 16:46:26 +03:00
![Finite categories](finite_categories.svg)
2023-02-19 00:41:02 +03:00
Although they are not useful by themselves, the idea behind them is important - we can draw any combination of points and arrows and call it a category, in the same way that we can construct a set out of every combination of objects.
2022-09-11 08:56:25 +03:00
Examining some finite categories
---
2023-01-28 23:25:12 +03:00
For future reference, let's see some important finite categories.
2022-09-11 08:56:25 +03:00
The simplest category is $0$ (enjoy the minimalism of this diagram.)
2021-10-31 02:21:39 +03:00
![The finite category 0](finite_zero.svg)
2022-09-11 08:56:25 +03:00
The next simplest category is $1$ - it is comprised of one object no morphism besides its identity morphism (which we we don't draw, as usual)
2021-10-31 02:21:39 +03:00
![the finite category 1](finite_one.svg)
2021-12-25 19:31:58 +03:00
If we increment the number of objects to two, we see a couple of more interesting categories, like for example the category $2$ containing two objects and one morphism.
2021-10-31 02:21:39 +03:00
![the finite category 2](finite_two.svg)
**Task:** There are just two more categories that have 2 objects and at most one morphism between two objects, draw them.
2021-12-25 19:31:58 +03:00
And finally the category $3$ has 3 objects and also 3 morphisms (one of which is the composition of the other two.)
2021-10-31 02:21:39 +03:00
![the finite category 3](finite_three.svg)
2021-08-10 21:36:14 +03:00
2021-12-25 19:31:58 +03:00
Isomorphisms
2021-08-10 21:36:14 +03:00
===
2023-02-19 00:41:02 +03:00
Many of the categories that we saw are similar to one another, as for example both the color-mixing order and categories that represent logic have greatest and least objects. To pinpoint such similarities and understand what they mean, it is useful to have formal ways to connect categories with one another. The simplest type of connection is the good old isomorphism.
2021-12-25 19:31:58 +03:00
2022-09-11 08:56:25 +03:00
Set isomorphisms
---
2023-02-19 00:41:02 +03:00
In chapter 1 we talked about *set isomorphisms*, which establish an equivalence between two sets. In case you have forgotten, a set isomorphism is a *two-way function* between two sets.
2021-08-10 21:36:14 +03:00
![Set isomorphism](set_isomorphism.svg)
2023-02-19 00:41:02 +03:00
It can alternatively be viewed as two "twin" functions each of which equals identity when composed with the other.
2022-09-11 08:56:25 +03:00
Order isomorphisms
---
2023-02-19 00:41:02 +03:00
Then, in chapter 4, we encountered *order isomorphisms* and we saw that they are like set isomorphisms, but with one extra condition - aside from just being there, the functions that define the isomorphism have to preserve the order of the object e.g. a greatest object of one order should be connected to the greatest object of the other one, a least object should be connected to a least object and same for all objects in between.
2021-08-10 21:36:14 +03:00
![Order isomorphism](order_isomorphism.svg)
2023-02-19 00:41:02 +03:00
Or more formally put, for any $a$ and $b$ if we have $a ≤ b$ we should also have $F(a) ≤ F(b)$ (and vise versa.)
2022-09-11 08:56:25 +03:00
Categorical isomorphisms
---
2023-02-19 00:41:02 +03:00
Now we will generalize the definition of order isomorphisms, so it also applies to all other categories (to categories that may have more than one morphism between two objects):
2022-09-11 08:56:25 +03:00
2023-02-19 00:41:02 +03:00
> Given two categories, an isomorphism between them is an invertible function between the underlying sets of objects, *and* an invertible function between the morphisms that connect them, which maps each morphism from one category to a morphism *with the same signature*.
2021-08-10 21:36:14 +03:00
![Category isomorphism](category_isomorphism.svg)
2023-02-19 00:41:02 +03:00
If we examine it closely we will see that, although it *sounds* a bit more complex, this definition is actually the same definition as one we have for orders, it is just that the so-called "morphism functions" between categories that have just one morphism for any two objects, are trivial - we always map the single morphism of the source category to the single morphism of the target category (which is guaranteed to exist, due to the *order-preserving* condition.)
2021-08-25 16:17:57 +03:00
2022-09-11 08:56:25 +03:00
![Order isomorphism](category_order_isomorphism_2.svg)
2021-11-01 09:53:05 +03:00
2023-01-28 23:25:12 +03:00
However, when we can have more than one morphism between two given objects we need to make sure that each morphism in one category has a corresponding morphism in the other one.
2021-11-01 09:53:05 +03:00
2022-09-11 08:56:25 +03:00
![Category isomorphism](category_order_isomorphism.svg)
2021-11-01 09:53:05 +03:00
2023-02-19 00:41:02 +03:00
As you see, categorical isomorphisms are easy to define, however there is another issue with them, namely that they are *very rare in practice* (the only one that comes to mind to me is the Curry-Howard-Lambek isomorphism from the last section) as two categories that are isomorphic are basically the same category.
2023-01-28 23:25:12 +03:00
2023-02-19 00:41:02 +03:00
In the next chapter, we will see in detail why the whole concept of categorical isomorphism is not useful, and we will devise a more apt way to define a *two-way connection* between categories. But first, we will define *one-way connections* between them, i.e. *functors*.
2021-08-10 21:36:14 +03:00
2021-08-24 23:26:16 +03:00
<!--
comics:
OK, I think I got it - isomorphisms are when you have two similar pictures and you connect the dots.
2021-08-10 21:36:14 +03:00
2021-08-24 23:26:16 +03:00
Pretty much.
-->
2021-08-10 21:36:14 +03:00
2023-02-18 13:58:53 +03:00
What are functors
2021-08-10 21:36:14 +03:00
===
2023-02-19 00:41:02 +03:00
The logician Rudolf Carnap invented the word "functor" as part of his project to formalize the syntax for the natural languages such as English, in order to create a precise way to talk about science. Originally, he took it to mean a phrase whose meaning can be customized by combining it with numerical values, such as the phrase "the temperature at $x$ o'clock" (which has a different meaning depending on the value of $x$).
In other words, a functor is a phrase that acts as a function, only not a function between sets, but one between *linguistic concepts* (such as times and temperature.)
2023-01-28 23:25:12 +03:00
![Functor, as envisioned by Rudolf Carnap.](functor_carnap.svg)
2023-02-19 00:41:02 +03:00
Later, one of the inventors of category theory Sanders Mac Lane borrowed the word, to describe a function between *categories* as well, which he defined in the following way:
> A functor between two categories (let's call them $A$ and $B$) consists of a pair of mappings - a mapping that maps each *object* in $A$ to an object in $B$ and a mapping that maps each *morphism* between any objects in $A$ to a morphism between objects in $B$, in a way that *preserves the structure* of the category.
2021-08-23 21:49:05 +03:00
![Functor](functor.svg)
2023-01-28 23:25:12 +03:00
Now let's unpack this definition by going through each of its components.
2021-08-24 23:26:16 +03:00
2021-10-21 16:46:26 +03:00
Object mapping
2021-08-24 23:26:16 +03:00
---
2023-02-19 00:41:02 +03:00
We said that, a functor contains a mapping between the categories' objects, and we used the word "mapping" to avoid misusing the word "function" which is a term that has a precise meaning since chapter 1. In this particular case, however, it wouldn't be a misuse - the mapping between the categories' objects is just a regular old function.
2021-08-23 21:49:05 +03:00
2021-08-24 23:26:16 +03:00
![Functor for objects](functor_objects.svg)
2021-08-23 21:49:05 +03:00
2023-02-19 00:41:02 +03:00
Or more formally, the object mapping of the functor is a function between the two categories' *underlying sets*, and underlying set of a category being the set of its objects. With the definition of a function being the following:
> A function is a relationship between two sets that matches each element of one set, called the *source set* of the function, with exactly one element from another set, called the *target set* of the function.
2021-11-01 09:53:05 +03:00
2021-10-21 16:46:26 +03:00
Morphism mapping
2021-08-24 23:26:16 +03:00
---
2023-02-19 00:41:02 +03:00
The other mapping that forms the functor is not so straightforward - it is a mapping between the categories' morphisms. This mapping resembles a function as well, but with the added requirement that each morphism with a given source and target must be mapped to a morphism with a corresponding source and target, as per the object mapping.
2021-08-24 23:26:16 +03:00
![Functor for morphisms](functor_morphisms.svg)
2021-08-23 21:49:05 +03:00
2023-02-19 00:41:02 +03:00
A more formal definition of a morphism mapping involves the concept of the *homomorphism set* - this is a set that contains all morphisms that go between given two objects in a given category.
2023-01-28 23:25:12 +03:00
2023-02-19 00:41:02 +03:00
Utilizing this concept, we can say that a mapping between the morphisms of the two categories is actually a set of the functions between their respective homomorphism sets.
2021-08-23 21:49:05 +03:00
2021-08-24 23:26:16 +03:00
![Functor for morphisms](functor_morphisms_formal.svg)
2022-09-11 08:56:25 +03:00
Note how the concepts of *homomorphism set* and of *underlying set* allowed us to "escape" to set theory when defining categorical concepts.
2021-08-25 16:17:57 +03:00
2021-08-24 23:26:16 +03:00
Functor laws
---
2023-02-19 00:41:02 +03:00
So these are the two mappings that constitute a functor. But not every such pair of mappings is a functon. As we said, in addition to existing, the mappings should *preserve the structure* of the source category into the target category.
2021-08-24 23:26:16 +03:00
2023-02-19 00:41:02 +03:00
To describe the structure of a category we revisit the definition from chapter 2:
2021-12-25 19:31:58 +03:00
> A category is a collection of *objects* (we can think of them as points) and *morphisms* (arrows) that go from one object to another, where:
2021-10-21 16:46:26 +03:00
> 1. Each object has to have the identity morphism.
2023-02-19 00:41:02 +03:00
> 2. There should be a way to compose two morphisms with an appropriate type signature into a third one, in a way that is associative.
2021-08-24 23:26:16 +03:00
2023-02-19 00:41:02 +03:00
So this definition translates to the following two *functor laws*
2021-08-24 23:26:16 +03:00
2021-12-25 19:31:58 +03:00
1. Functions between morphisms should *preserve identities* i.e. all identity morphisms should be mapped to other identity morphisms.
![Functor](functor_laws_identity.svg)
2021-08-24 23:26:16 +03:00
2021-12-25 19:31:58 +03:00
2. Functors should also *preserve composition* i.e. for any two morphisms $f$ and $g$, the morphism that corresponds to their composition $F(g•f)$ in the source category should be the same as the morphism that corresponds to the composition of their counterparts in the target directory, so $F(g•f) = F(g)•F(f)$.
2021-08-24 23:26:16 +03:00
2023-02-19 00:41:02 +03:00
![Functor](functor_laws_composition.svg)
2021-08-24 23:26:16 +03:00
2023-02-19 00:41:02 +03:00
And these laws conclude the definition of functors - a simple but, as we will see shortly, very powerful concept. To see *why* is it so powerful, let's check some examples.
2021-08-25 16:17:57 +03:00
2023-02-18 13:58:53 +03:00
Diagrams are functors
---
2021-12-25 19:31:58 +03:00
2023-02-18 13:58:53 +03:00
> “A sign is something by knowing which we know something more.” — Charles Sanders Peirce
2021-08-24 23:26:16 +03:00
2023-02-19 00:41:02 +03:00
We will start with an example of a functor that is very *meta* - the diagrams/illustrations in this book.
You might have noticed that diagrams play a special role in category theory - while in other disciplines they only serve a complementary function i.e. they only show what is already defined in another way, here *the diagrams themselves serve as definitions*.
2021-09-08 16:45:37 +03:00
2023-02-18 13:58:53 +03:00
For example, in chapter 1 we presented the following definition of functional composition.
2021-08-25 16:17:57 +03:00
2023-02-18 13:58:53 +03:00
> The composition of two functions $f$ and $g$ is a third function $h$ defined in such a way that this diagram commutes.
2021-09-08 16:45:37 +03:00
2023-02-18 13:58:53 +03:00
![Functional composition - general definition](functions_compose_general.svg)
2021-08-25 16:17:57 +03:00
2023-02-19 00:41:02 +03:00
So in other words we *used the diagram as a definition* of functional composition. This is cool, but kinda confusing at first - definitions in mathematics are supposed to be formal, so if we want to use diagrams as definitions we must first formalize the definition of a diagram itself.
But how do we do that? One key observation is that diagrams look as small finite categories, as, for example, the above definition looks like the category $3$, which we saw earlier (and the fact that the diagram commutes means just that the morphism in the finite category are sometimes composites of one another.)
2021-12-25 19:31:58 +03:00
2023-02-18 13:58:53 +03:00
![the finite category 3](finite_three.svg)
2021-08-25 16:17:57 +03:00
2023-02-19 00:41:02 +03:00
However, finite categories, by themselves, are only part of the story, as they are just structures, whereas diagrams are *signs* i.e. They are "something by knowing which we know something more.", as Peirce tells us (or "...which can be used in order to tell a lie", in the words of Umberto Eco.)
2021-08-10 21:36:14 +03:00
2023-02-19 00:41:02 +03:00
So, besides the finite categories, diagrams must include ways for "interpreting" those categories in some other context i.e. they include *functors*.
2021-08-25 16:17:57 +03:00
2023-02-18 13:58:53 +03:00
![diagram as a functor](diagram_functor.svg)
2023-02-19 00:41:02 +03:00
This is how the concept of functors allows us to formalize the notion of diagrams:
> A *diagram* is comprised of one finite category (called an *index category*) and a functor from it to some other category.
(And, since we involved Umberto Eco, in semiotic terms you may view the source and target categories of the functor as *signifier* and *signified*.)
2023-02-18 13:58:53 +03:00
2023-02-19 00:41:02 +03:00
And so, you can already see that the concept of a functor plays a very important role in category theory. Because of it, diagrams in category theory can be *specified formally* i.e. they are categorical objects *per se*.
You might even say that they are categorical objects *par excellance* (TODO: remove that last joke.)
2023-02-18 13:58:53 +03:00
Maps are functors
2021-08-23 21:49:05 +03:00
---
2021-10-21 16:46:26 +03:00
2023-02-19 00:41:02 +03:00
Functors are sometimes called "maps" for a good reason - maps, like all other diagrams are functors. For example, if we consider a map of different cities and roads between them categorically, then a diagram is a map of the region where the cities are located (or an index category as we dubbed it in the definition), together with a functor connectin it to the region that it represents (i.e. a mapping from the objects in the map to real-world objects.)
2021-10-21 16:46:26 +03:00
2023-02-18 13:58:53 +03:00
![A map and a preorder of city pathways](preorder_map_functor.svg)
2021-10-31 02:21:39 +03:00
2023-02-18 13:58:53 +03:00
In maps, morphisms that are a result of composition are often not displayed, but we use them all the time - they are called *routes*.
2021-12-25 19:31:58 +03:00
2023-02-18 13:58:53 +03:00
![A map and a preorder of city pathways](preorder_map_functor_route.svg)
2021-10-21 16:46:26 +03:00
2023-02-19 00:41:02 +03:00
The law of preserving composition tells us that the route we create on a map corresponds to a real-world route.
Notice that in order to be a functor, a map does not have to list *all* roads that exist in real life, and *all* travelling options ("the map is not the territory"), the only requirement is that *the roads that it lists should be actual* - this is a characteristic shared by all many-to-one relationships (i.e. functions.)
2021-11-08 19:19:26 +03:00
2023-02-18 13:58:53 +03:00
Human perception is functorial
---
As you can see from the last two chapters, we, humans, make a good use of functors in our thinking (especially considering that most of us don't know anything about them.) In my [blog post about using logic to model real-life thinking](/logic-thought)) I argue that is because human perception, human thinking is itself functorial.
![Perception is functorial](logic_thought.svg)
2021-11-08 19:19:26 +03:00
2023-02-19 00:41:02 +03:00
My thesis is that to perceive the world around us, we are creating a bunch of functors that go from more raw "low-level" maps to more abstract "high-level" ones.
For example, our brain creates a functor between the category of raw sensory data that we receive from our senses, to a category containing some basic model of how the world works (one that tells us where are we in space, how many objects are we seeing etc.) Then we are connecting this model to another, more abstract model, which provides us with a higher-level view of the situation that we are in, and so on.
You can view this progression of more simple to more abstract functors to a progression from categories with less morphisms to categories with more morphisms - we start with the category of pieces of sensory data that have no connections between one another, and proceed to another category where some of these pieces of data are connected. Then, we transfer this structure in another category with even more connnections.
2021-11-08 19:19:26 +03:00
2023-02-19 00:41:02 +03:00
This is, of course, all just a speculation. But how can we check if it is true. You might say that if it were true, functors would be everywhere i.e. all mathematical objects would have functors and functors will play a significant role for them. As we will see in the next chapters, this is not far from the truth.
2021-11-08 19:19:26 +03:00
2021-10-31 02:21:39 +03:00
Functors in monoids
2021-10-21 16:46:26 +03:00
===
2022-09-11 08:56:25 +03:00
In group theory, there is this cool thing called *group homomorphism* (or *monoid homomorphism* when we are talking about monoids) - it is a function between the groups' underlying sets which preserves the group operation.
2021-10-31 02:21:39 +03:00
2023-02-19 00:41:02 +03:00
If the time of the day right now is 00:00 o'clock (or 12 PM) then what would the time be after $n$ hours? The answer to this question can be expressed as a function with the set of integers as source and target.
2021-10-31 02:21:39 +03:00
![Group homomorphism as a function](group_homomorphism_function.svg)
2021-11-15 19:07:44 +03:00
This function is interesting - it preserves the operation of (modular) addition. That is, 13 hours from now the time will be 1 o'clock and if 14 hours from now it will be 2 o'clock, then the time after (13 + 14) hours will be (1 + 2) o'clock.
2023-02-18 13:58:53 +03:00
Or to put it formally, if we call it (the function) $F$, then we have the following equation - $F(a + b) = F(a) + F(b)$ (where $+$ in the right-hand side of the equation means modular addition) Because this equation holds, the $F$ function is a *group homomorphism* between the group of integers under addition and the group of modulo arithmetic with base 11 under modular addition (where you can replace 11 with any other number.)
2021-11-08 19:19:26 +03:00
2021-10-31 02:21:39 +03:00
![Group homomorphism](group_homomorphism.svg)
2023-02-18 13:58:53 +03:00
The groups don't have to be so similar for there to be a homomorphism between them. Take, for example, the function that maps any number $n$ to 2 to the *power of $n$,* so $n \to 2ⁿ$ (here, again, you can replace 2 with any other number.) This function gives a rise to a group homomorphism between the group of integers under addition and the integers under multiplication, or $F(a + b) = F(a) * F(b)$
2021-10-31 02:21:39 +03:00
![Group homomorphism between different groups](group_homomorphism_addition_multiplication.svg)
2023-02-19 00:41:02 +03:00
Wait, what were we talking about, again? Oh yeah - group homomorphisms are functors. To see why, we switch to the category-theoretic representation of groups and revisit our first example and (to make the diagram simpler, we use $mod2$ instead of $mod11$.)
2021-10-31 02:21:39 +03:00
![Group homomorphism as a functor](group_homomorphism_functor.svg)
2023-02-18 13:58:53 +03:00
When we view groups as one-object categories, a group homomorphism is just a functor between these categories).
2021-10-31 02:21:39 +03:00
Object mapping
---
2021-11-15 19:07:44 +03:00
Groups/monoids have just one object when viewed as categories, so there is also only one possible object mapping between any couple of groups/monoids - one that maps the (one and only) object of the source group to the object of the target group (not depicted in the diagram).
2021-10-31 02:21:39 +03:00
Morphism mapping
---
2022-09-11 08:56:25 +03:00
Because of the above, the morphism mapping is the only relevant component of the group homomorphism. In the category-theoretic perspective group objects are morphisms and so the morphism mapping is just mapping between the group's objects, as we can see in the diagram.
2021-10-31 02:21:39 +03:00
Functor laws
---
2021-12-25 19:31:58 +03:00
The first functor law trivial, it just says that the one and only identity object of the source group (which corresponds to the identity morphism of its one and only object) should be mapped to the one and only identity object of the target group. And we can see that this is the case - in our first example, $0$, the identity of the addition operation, is mapped to $0$. And in the second one $0$ is mapped to $1$ - the identity object of the multiplication operation.
2021-11-10 09:38:55 +03:00
2021-11-15 19:07:44 +03:00
As we said, in order for a function to be a group homomorphism, it must satisfy the equation
2023-02-18 13:58:53 +03:00
$F(a + b) = F(a) \times F(b)$ (where the $+$ and $\times$ operators are arbitrary.) And if you remember that, when interpreted categorically, group objects (like $1$ and $2$ $3$ etc.) correspond to morphisms (like $+1$, $+2$ $+3$ etc.) and the monoid operation of combining two objects corresponds to *functional composition*, you would see that this equation is actually a just a formulation of the second functor law: $F(g•f) = F(g)•F(f)$.
2021-10-31 02:21:39 +03:00
2023-02-18 13:58:53 +03:00
And many algebraic operations satisfy this equation, for example the functor law for the group homomorphism between $n \to 2ⁿ$ is just the famous algebraic rule, stating that $gᵃ gᵇ= gᵃ⁺ᵇ$.
2021-10-31 02:21:39 +03:00
2022-09-11 08:56:25 +03:00
**Task:** Although it's trivial, we didn't prove that the first functor law (the one about the preservation of identities always holds. Interestingly enough, for groups/monoids it actually follows from the second law. Try to prove that. Start with the definition of the identity function.
2021-10-31 02:21:39 +03:00
2022-05-08 19:30:39 +03:00
2021-10-31 02:21:39 +03:00
<!-- TODO show isomorphism theorems -->
Functors in orders
2021-10-21 16:46:26 +03:00
===
2023-02-19 00:41:02 +03:00
And now let's talk about one concept that is completely unrelated to functors, nudge-nudge (hey, bad jokes are better than no jokes at all, right?) In the theory of orders, we have the concept of functions between orders (which is unsurprising, given that orders, like monoids/groups, are based on sets.) One very interesting type of such function, which has applications in calculus and analysis, is a *monotonic function* (also called *monotone map*) - this is a function between two orders that *preserves the order of the objects in the source order, in the target order. So a function $F$ is monotonic when for every $a$ and $b$ in the source order, if $a ≤ b$ then $F(a) ≤ F(b)$.
2021-08-10 21:36:14 +03:00
2022-09-11 08:56:25 +03:00
For example, the function that maps the current time to the distance traveled by some object is monotonic because the distance traveled increases (or stays the same) as time increases.
2021-10-21 16:46:26 +03:00
2021-11-20 09:07:21 +03:00
![A monotonic function](monotone_map.svg)
2021-10-21 16:46:26 +03:00
2023-02-18 13:58:53 +03:00
If we plot this or any other monotonic function on a line graph, we see that it goes just one direction (i.e. just up or just down.)
2021-10-21 16:46:26 +03:00
2021-11-20 09:07:21 +03:00
![A monotonic function, represented as a line-graph](monotone_map_plot.svg)
2021-10-21 16:46:26 +03:00
2021-10-31 02:21:39 +03:00
Now we are about to prove that monotonic functions are functors too, ready?
2021-10-21 16:46:26 +03:00
2021-10-31 02:21:39 +03:00
Object mapping
2021-08-25 16:17:57 +03:00
---
2021-08-23 21:49:05 +03:00
2022-09-11 08:56:25 +03:00
Like with categories, the object mapping of an order is represented by a function between the orders' underlying sets.
2021-08-25 16:17:57 +03:00
2021-10-31 02:21:39 +03:00
Morphism mapping
2021-08-23 21:49:05 +03:00
---
2021-07-28 16:00:22 +03:00
2022-09-11 08:56:25 +03:00
With monoids, the object mapping component of functors was trivial. Here is the reverse - the morphism mapping is trivial - given a morphism between two objects from the source order, we map that morphism to the morphism between their corresponding objects in the target order. The fact that the monotonic function respects the order of the elements, ensures that the latter morphism exists.
2021-10-21 16:46:26 +03:00
2021-10-31 02:21:39 +03:00
Functor laws
---
2023-02-19 00:41:02 +03:00
It is not hard to see that monotone maps obey the first functor law as identities are the only morphisms that go between a given object and itself.
2021-10-31 02:21:39 +03:00
2023-02-19 00:41:02 +03:00
And the second law ($F(g•f) = F(g)•F(f)) also follows trivially: both morphisms $F(g•f)$ and $F(g)•F(f)$ have the same type signature - so for example if we take the signature of $f$ and $g$ to be $f :: a \to b$ and $g :: b \to c$, then they both would go from $F(a)$ and $F(c)$. But because in orders there can be just one morphism between $F(a)$ and $F(c)$ so these two morphisms must be equal to one another.
**Task:** Expand the proof.
<!--
2023-02-18 13:58:53 +03:00
And the second law ($F(g•f) = F(g)•F(f)) also follows from the fact that there is only one morphism with a given signature.
2021-10-31 02:21:39 +03:00
2023-02-18 13:58:53 +03:00
Suppose that in the source order we have two morphisms with the following type signature:
2021-10-31 02:21:39 +03:00
2023-02-18 13:58:53 +03:00
$f :: a \to b$ and $g :: b \to c$.
2021-11-20 09:07:21 +03:00
2023-02-18 13:58:53 +03:00
Then, if we compose those two morphisms in the target order ($F(g)•F(f)$), we get a morphism from object $F(a)$ to object $F(c)$ ($F(g)•F(f) :: F(a) \to F(c)$.)
If we compose the two morphisms in the source order, and we use the functor to get the corresponding morphism in the target order ($F(g•f)$) we get another morphism from object $F(a)$ to object $F(c)$ ($F(g•f) :: F(a) \to F(c)$)
But because in orders there can be just one morphism between $F(a)$ and $F(c)$ so these two morphisms must be equal to one another.
2023-02-19 00:41:02 +03:00
-->
2021-10-31 02:21:39 +03:00
2023-01-28 23:25:12 +03:00
Linear functions
2021-10-31 02:21:39 +03:00
===
2023-02-19 00:41:02 +03:00
OK, enough with this abstract nonsence, let's talk about "normal" functions - ones between numbers.
2021-10-31 02:21:39 +03:00
2023-02-18 13:58:53 +03:00
In calculus, there is this concept of *linear functions* (also called "degree one polynomials") that are sometimes defined as functions of the form $f(x) = xa$ i.e. ones that contain no operations other than multiplying the argument by some constant (designated as $a$ in the example).
2021-12-25 19:31:58 +03:00
2023-02-19 00:41:02 +03:00
But if we start plotting some such functions we will realize that there is another way to describe them - their graphs are always comprised of straight lines.
2021-12-25 19:31:58 +03:00
2023-02-18 13:58:53 +03:00
![Linear functions](linear_functions.svg)
2021-12-25 19:31:58 +03:00
2023-02-18 13:58:53 +03:00
**Question:** Why is that?
2021-12-25 19:31:58 +03:00
2023-02-19 00:41:02 +03:00
Another interesting property of these functions is that most of them *preserve* addition, that is for any $x$ and $y$, you have $f(x) + f(y) = f(x + y)$.
2021-12-25 19:31:58 +03:00
2023-02-18 13:58:53 +03:00
![Linear functions](linear_function_functor.svg)
2021-12-25 19:31:58 +03:00
2023-02-19 00:41:02 +03:00
And if you pay attention, you would know that you just saw the functor law formula. So linear functions are just *functors between the group of natural numbers under addition and itself.* (more generally, they are functors in the category of vector spaces.)
2022-05-08 19:30:39 +03:00
2023-02-18 13:58:53 +03:00
**Question:** Are the two formulas we presented to define linear functions completely equivalent?
2021-12-25 19:31:58 +03:00
2023-02-18 13:58:53 +03:00
<!--
Let
$f(x) = ax $
2021-12-25 19:31:58 +03:00
2023-02-18 13:58:53 +03:00
and
$f(y) = ay $
Then
$f(x) + f(y) = ax + ay $
This means that
$f(x) + f(y) = a(x + y)$
but $f(x) = ax$, so
$f(x) + f(y) = f(x + y)$
-->
And if we view that natural numbers as an order, linear functions are also functors as well, as all functions that are plotted with straight lines are obviously monotonic.
2023-02-19 00:41:02 +03:00
The above definition has one caveat: not all functions that are straight lines preserve addition - functions of the form $f(x) = x * a + b$ in which $b$ is non-zero, are also straight lines (and are also called linear) but they don't preserve addition.
2023-02-18 13:58:53 +03:00
![Linear functions](linear_function_non_functor.svg)
For those, the above formula looks like this: $f(x) + b + f(y) + b = f(x + y) + b$.
<!--
2021-12-25 19:31:58 +03:00
2023-02-18 13:58:53 +03:00
The category of topological spaces
---
The smoothness of the mapping means that paths may stretch or collapse but not break.
-->
Functors in programming. The list functor
2021-12-25 19:31:58 +03:00
===
2023-02-18 13:58:53 +03:00
If types in programming language form a category, then what are the functors that are related to that category?
The short (but complex) answer to this question is that we can view functors between the category of types and itself as maps from the realm of simple (primitive) types and functions to the realm of more complex types and functions.
2021-12-25 19:31:58 +03:00
2023-02-18 13:58:53 +03:00
![A functor in programming](functor_programming.svg)
2021-12-28 15:58:33 +03:00
2023-02-18 13:58:53 +03:00
The long but simple answer - giving a definition of functor in programming context, is as simple as changing the terms we use, according to the table in chapter 2, and (more importantly) changing the font we use in our formulas from "modern" to "monospaced"
> A functor between two categories (let's call them `A` and `B`) consists of a mapping that maps each *type* in `A` to a type in `B` and a mapping that maps each *function* between types in `A` to a function between types in `B`, in a way that preserves the structure of the category.
Mathematicians and programmers - two very different communities, that are united by their appreciation of peculiar typefaces. And by the fact that they all use functors.
2021-12-25 19:31:58 +03:00
2023-01-28 23:25:12 +03:00
Type mapping
2021-08-25 16:17:57 +03:00
---
2021-08-24 23:26:16 +03:00
2023-01-28 23:25:12 +03:00
The first component of a functor is a mapping that converts one type (let's call it `A`) to another type (`B`). So it is *like a function, but between types*. Such constructions are supported by almost all programming languages that have static type checking in the first place - they go by the name of *generic types*.
2021-12-28 15:58:33 +03:00
2023-01-28 23:25:12 +03:00
A generic type is nothing but a function (sometimes called a *type-level function*) that maps one concrete type to another concrete type. For example, the type `Array<A>` maps the type `String` to `Array<String>`, `Number` to `Array<Number>` etc.
2021-08-23 21:49:05 +03:00
2023-01-28 23:25:12 +03:00
![A functor in programming - type mapping](functor_programming_objects.svg)
2021-08-23 21:49:05 +03:00
2023-02-18 13:58:53 +03:00
2021-10-21 16:46:26 +03:00
2023-01-28 23:25:12 +03:00
Function mapping
2021-12-25 19:31:58 +03:00
---
2021-10-21 16:46:26 +03:00
2023-01-28 23:25:12 +03:00
So the type mapping of a functor is simply a generic type in a programming language (we can also have functors between two generic types, but we will review those later.) However the nontrivial part of the functor is the *function mapping* - that is a mapping that convert any function operating on simple types, like `String ➞ Number` to a function between their more complex counterparts e.g. `Array<String> ➞ Array<Number>`.
2021-12-25 19:31:58 +03:00
2023-01-28 23:25:12 +03:00
![A functor in programming - function mapping](functor_programming_morphisms.svg)
2021-12-25 19:31:58 +03:00
2023-01-28 23:25:12 +03:00
In programming languages, this mapping is represented by a higher-order function called `map` with a signature (using Haskell notation), `(a ➞ b) ➞ (Fa ➞ Fb)`, where `F` represents the composite type.
2021-12-25 19:31:58 +03:00
2023-01-28 23:25:12 +03:00
Any function with that type signature that follows the laws gives rise to a functor, but not all such functors are useful. In practice, usually, there is only one of them that makes sense for a given generic type. For example, in the case of list and similar structures, `map` is a function that applies the original function (the one that converts simple types) to all elements of the list.
2021-12-25 19:31:58 +03:00
2023-01-28 23:25:12 +03:00
Because only one `map` function per generic type is useful (and also for simple convenience) you might sometimes see `map` defined directly in the generic datatype, as a method. For example, Here is how the list functor might look in TypeScript, implemented in the way that I described above:
2021-12-25 19:31:58 +03:00
2023-01-28 23:25:12 +03:00
```
class Array<A> {
map (f: A ➞ B): Array<B> {
let result = [];
for (obj of this) {
result.push(f(obj));
}
return result;
}
}
```
2021-12-25 19:31:58 +03:00
2023-02-18 13:58:53 +03:00
2023-01-28 23:25:12 +03:00
Functor laws
2021-12-25 19:31:58 +03:00
---
2023-01-28 23:25:12 +03:00
Aside from facilitating code reuse by bringing in all standard functions of simple types in a more complex context, `map` allows us to work in a way that is predictable, courtesy of the functor laws, which in programming context look like this.
2021-12-28 15:58:33 +03:00
2023-01-28 23:25:12 +03:00
```
a.map(a => a) == a
2021-12-28 15:58:33 +03:00
2023-01-28 23:25:12 +03:00
const compose = (f, g) => f(g)
a.map(f).map(g) == a.map(compose(g, f))
```
2021-12-28 15:58:33 +03:00
2023-01-28 23:25:12 +03:00
**Task:** Use examples to verify that the laws are followed.
2021-12-28 15:58:33 +03:00
2023-02-18 13:58:53 +03:00
What are functors for
2023-01-28 23:25:12 +03:00
===
2021-12-28 15:58:33 +03:00
2023-02-18 13:58:53 +03:00
Now, that we have seen some examples of functors, let's attempt to answer the million-dollar question: "How are functors *useful*?" (sometimes formulated also as "Why are you wasting my/your time with this (abstact) nonsense?") We just saw that *maps are functors* and we know that *maps are useful*, so let's start from there.
So why is a map (or any other kind of diagram) useful? Well, it obviously has to do with the fact that the points and arrows of the map corresponds to the cities and the roads in the place you are visiting in i.e. because of the very fact that it is a functor.
But there is a second aspect as well. Maps (or at least those of them that are useful) are *simpler to work with* than the actual things they represent.
For example, road maps are useful, because it is much easier to go through all routes between two given places by following a map, than to actually drive through all these routes in real life.
So why do programmers need functors? Because simple types like `string`, `number`, `boolean` etc are... well simple, there are numerous functions between those types, that are defined in all kinds of libraries e.g. there are a myriad functions that convert a number to boolean.
![Functions from array to boolean](set_arrows.svg)
Functors like `List`, allow you to take all such functions (ones that act on simple types) and derive their counterparts that work on list e.g. a function that converts strings to numbers can be used to convert string arrays to number arrays.
Note that not all functions that act on a list of strings can be derived from mere string functions, but some of them can (some are better than nothing, right?)
Functors
===
Constant functor
---
When we think about diagram functors (and even functors in general), our intuition is to think of every object in the source category being mapped to a *different* object in the target. But that is not always the case. An interesting functor that doesn't follow that rule is the *constant functor* - one that maps *all* objects of the source category to a single object in the target (and all morphisms go to the identity morphism.
![Constant functor](constant_functor.svg)
This one that plays a part in some definitions that we will see later.
2021-12-28 15:58:33 +03:00
2023-01-28 23:25:12 +03:00
Endofunctors
---
2023-02-18 13:58:53 +03:00
In the programming example, we acted like different type families belong to different categories. However, that is not the case - they are actually one and the same category - the category of types (which can be seen as similar to the category of sets.) So all functors used in programming are *endofunctors* i.e. ones in which the source and target category is one and the same. This doesn't make any difference when it comes to the above definitions (you can also think of the different type families as belonging to different categories if that's easier for you), but it does make a difference in other situations, for example, you can apply an endofunctor $F$ to a given value $a$ infinitely many times, adding more and more levels of nesting.
2021-12-28 15:58:33 +03:00
2023-01-28 23:25:12 +03:00
![A functor in programming as endofunctor](endofunctor_programming.svg)
2021-12-28 15:58:33 +03:00
2023-02-18 13:58:53 +03:00
This might look weird, but it does not lead to any type of paradox e.g. there is nothing wrong about a list that contains other lists, and you can have a list of lists of lists, or a list of lists of lists of lists etc, and the functor laws would still hold (provided that you `map` the right number of times.)
2021-12-25 19:31:58 +03:00
2023-01-28 23:25:12 +03:00
Identity functors
2021-12-25 19:31:58 +03:00
---
2023-01-28 23:25:12 +03:00
There is one particular endofuctor that will probably look familiar to you - it is the *identity functor* of each category, the one that maps each object and morphism to itself.
2021-12-28 15:58:33 +03:00
2023-01-28 23:25:12 +03:00
![Identity functor](identity_functor.svg)
2021-12-28 15:58:33 +03:00
2023-02-18 13:58:53 +03:00
Identity functors are defined for the same reason as identity morphisms - they allow us to talk about value-related stuff without actually involving values.
2021-12-28 15:58:33 +03:00
2023-01-28 23:25:12 +03:00
Pointed functors
---
2022-09-11 08:56:25 +03:00
2023-02-18 13:58:53 +03:00
An interesting "species" of the endofunctors that we can define using the identity functor are the so-called *pointed* functors. This is a name for the functors that are *isomorphic to the identity functor*.
We still haven't said when two functors are isomorphic, but for now it suffices to say that they are isomorphic when the diagram below commutes for all objects and functions.
2021-12-28 15:58:33 +03:00
2023-01-28 23:25:12 +03:00
![Pointed functor](pointed_functor.svg)
2021-12-28 15:58:33 +03:00
2023-01-28 23:25:12 +03:00
If we concentrate on the category of sets (or the category of types, if you will), then this would mean that there is a function that translates each value of what we called the "simple types" to a value of the functor's generic type, in a way that this diagram commutes (again, the function should make the diagram commute for all types (and not just **string** and **num**) for all functions that exist, not only the four we outlined here.)
2021-12-28 15:58:33 +03:00
2023-01-28 23:25:12 +03:00
![Pointed functor in Set](pointed_functor_set.svg)
2021-12-28 15:58:33 +03:00
2023-01-28 23:25:12 +03:00
The list functor is pointed, because such a function exist for the list functor - it is the function that puts every value in a "singleton" list.
2021-12-28 15:58:33 +03:00
2023-01-28 23:25:12 +03:00
![Pointed functor in Set](pointed_functor_set_internal.svg)
2021-12-28 15:58:33 +03:00
2023-01-28 23:25:12 +03:00
You can see that the definition of a pointed functor looks like an "upgrade" of the definition of a functor - we again have the relationship between a bunch of objects and a bunch of morphisms, such that there is a symmetry between them. The only difference is that with pointed functors we are working in one and the same category, and so the description of the laws is much simpler - the relationship is
2022-09-11 08:56:25 +03:00
2023-01-28 23:25:12 +03:00
And in programming context, the fact that the functor is pointed translates to the following:
2022-09-11 08:56:25 +03:00
2023-01-28 23:25:12 +03:00
```
[a].map(f) = [f(a)]
```
2022-09-11 08:56:25 +03:00
2023-01-28 23:25:12 +03:00
Homomorphism functors
---
2022-09-11 08:56:25 +03:00
2023-01-28 23:25:12 +03:00
Given any category, we can generate the set of the sets of all morphisms that have a specific type signature with respect to a given object from that category. This is called the *Homomorphism set*, denoted $Hom(B, - )$, $B$ being the object that you picked (for example, let's pick the brown ball.)
2021-12-28 15:58:33 +03:00
2023-01-28 23:25:12 +03:00
![Homomorphism set](hom_set.svg)
2021-12-28 15:58:33 +03:00
2023-01-28 23:25:12 +03:00
This set forms a category where the morphism sets are the objects (again morphism sets are *objects*) and the morphisms are the same as in the original category. And between those two categories (the original and the weird morphism-based one) there is a functor, called the homomorphism functor.
2021-12-28 15:58:33 +03:00
2023-01-28 23:25:12 +03:00
![Homomorphism set](hom_functor.svg)
2021-10-21 16:46:26 +03:00
2023-01-28 23:25:12 +03:00
**Question:** Which object should we pick so that the original and the homomorphism categories are isomorphic?
2021-08-23 21:49:05 +03:00
2023-01-28 23:25:12 +03:00
With the homomorphism functors, we can *represent* any category in the category of sets. This is why homomorphism functors and all functors that are isomorphic to them are called *representable* functors.