Notebook
Monads, monoids, categories...oh my
I have this thing where sometimes I want to understand a complex topic, even though it has little relevance to my life at the moment.
I've been looking at Effect.ts which has a somewhat steep learning curve. Trying to understand the theoretical basis of what an Effect is, lead me back to monads. And so here we are...I'm working on writing a proper article about how to think about Monads, from both a category theory and a programmer's perspective.
Like most math topics, it takes a few clicks of insight to fully grasp. Here are some of those for me:
- Categories are "easy" to grasp abstractly: Objects and Arrows.
- Similarly, functors are easy: they map objects to objects, and arrows to arrows, in a way that preserves structure
- A functor $F: \mathcal{C} \to \mathcal{D}$ has to be defined on all of $\mathcal{C}$, but can collapse multiple objects to a single object in $\mathcal{D}$.
- The simple descriptions above get more confusing when you get concrete. Most objects in interesting categories, are actually themselves composed of items. For example, sets and groups. A single set is an object in $\mathbf{Set}$, but there are also elements of that set. You can work at either level of abstraction.
- monoids are just like groups but you don't have inverses.
- A monoidal category: you take a regular category and equip a bifunctor. Given two objects, you need a "natural" way to get out another object. And similarly for two arrows. And you need an identity object.
- There are alot of requirements in category theory that you need to be precise, but, imo, often hinder understanding. For example, in the above, you have coherence relations and a few other things that you need, to make sure that things play nicely together.
- The category $\mathbf{Type}$ is where programming comes in. This is category where objects are $types$ and the arrows are actual functions, in the programmatic sense!
- The category of endofunctors on $\mathbf{Type}$ is where monads come up.
- Monads are actually easier to grasp from a programming perspective. Conceptually, it is the wrapping up of a value in another type! You've probably come across this heavily in Rust with the
Option<T>type. - A monad is a triple:
- a map from types to types, and function to functions.
- a unit operation that lets you enter monad space: $A\to M[A]$
- a flatten operation: given a doubly wrapped monad object, peel back one layer: $M[M[A]]\to M[A]$
- The flatten operation is not at all the same as extract which goes from $M[A]\to A$. Why? Look at
Option<T>. IfTis something, you can getSome<T>, but in the other case, there's noTto return! Sincenilis not aT - For a long time, I was under the impression that a monad was just a function of a certain kind, but no, it's a triple!