Category Theory
Monads: Endofunctors with Extra Structure
JavaScript's async/await, Rust's Result<T,E>, Haskell's Maybe - all monads. One abstraction, three languages, billions of lines of production code. Promise.then() is bind. async/await is syntactic sugar over a monad. Every time one writes await, that is a Kleisli chain in action.
- Promise/async-await in JavaScript: monad for asynchrony
- fp-ts, cats, Arrow: monads in production TypeScript/Scala/Kotlin
- Haskell IO monad: language purity while working with side effects
- Optional in Java, Result in Rust: variants of the Maybe/Either monad
Monad: the Category-Theoretic Definition
JavaScript's Promise, Rust's Result, Haskell's IO - all share the same mathematical structure: a **monad**. A monad on a category C is a triple (T, η, μ) where T: C → C is an endofunctor, η: Id ⇒ T is a natural transformation (unit, "return"), and μ: T² ⇒ T is a natural transformation (multiplication, "join"). Three diagrams must commute: associativity and two unit laws.
**Historical note:** Monads appeared in mathematics in the 1950s (Grothendieck, Godement), and were introduced into programming by Eugenio Moggi (1991) and Philip Wadler (1992 - 1995). The famous phrase "a monad is just a monoid in the category of endofunctors" (James Iry, 2009) is mathematically precise, though it sounds daunting.
What is μ: T² ⇒ T in a monad?
The Kleisli Category: Composing Effectful Computations
The **Kleisli category** C_T for a monad (T, η, μ) has the same objects as C, but morphisms f: A → B in C_T are arrows A → T(B) in C. These are "effectful" functions: functions returning a wrapped result. The composition of two such arrows implements a chain of effects.
**Monads as "programmable semicolons":** Wadler called monads "programmable semicolons". The bind operator (>>=) is a new form of sequential composition where "something extra" happens between steps (error checking, logging, state management).
How is the composition of two Kleisli arrows f: A → T(B) and g: B → T(C) defined?
Monads in Practice: Maybe, List, IO, State
Monads are a universal pattern for structuring computations with effects. **Maybe** encapsulates partiality, **List** - non-determinism, **IO** - side effects, **State** - mutable state. Each monad is a concrete endofunctor with η and μ.
**Monads in real code:** In fp-ts (TypeScript) and cats (Scala) monads are used in production. Promise in JavaScript is a monad! bind = .then(), unit = Promise.resolve(). Key law: p.then(x => Promise.resolve(f(x))) is equivalent to p.then(f).
What is the type of the join (μ) operation in the List monad?
Key Ideas
- Monad = endofunctor T + η (unit) + μ (join), satisfying three laws
- Kleisli category: morphisms A → T(B) with monadic composition
- bind (>>=) = fmap + join: the tool for chaining effectful computations
- Maybe: partiality; List: non-determinism; IO: effects; State: state
- Monad = "programmable semicolon" (Wadler)
Related Topics
Monads tie together functors, natural transformations, and composition.
- Functors — A monad is a special endofunctor with additional structure
- Natural Transformations — η and μ are natural transformations that define the monad
- Adjoint Functors — Every pair of adjoint functors gives rise to a monad
Вопросы для размышления
- Why does Promise violate one of the monad laws? (Hint: Promise.resolve(Promise.resolve(42)) !== Promise.resolve(42))
- What would a monad for validation with accumulated errors look like? How does it differ from Either?
- Prove that (a) => [a] (listUnit) and flat (listJoin) satisfy the monad laws for List.