Tag: functional

Notes

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>. If T is something, you can get Some<T>, but in the other case, there's no T to return! Since nil is not a T
  • 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!