theorem proof example

Theorem. Every Adjunction with unit and counit defines a Monad

the multiplication being the double whiskering of the counit (). Dually is a Comonad. Conversely every monad arises from an adjunction — in fact from a whole category of them, with the Kleisli adjunction initial and the Eilenberg–Moore adjunction terminal.

Sources: DaoFP §15.2 (“Monads from Adjunctions”), §15.3 (“Examples of Monads from Adjunctions”), §15.4–15.5, Exercises 15.2.1, 15.3.1; §10.9; Kittenlab Lecture 7 (free monoid round trip); 7 Sketches §1.4.4 (closure operators from Galois connections, 7S Exercise 1.119).

Proof sketch (string diagrams). The monad laws follow from the triangle identities: replace each -string by the parallel pair ; the unit law becomes a zigzag in the -string, which the first triangle identity straightens; associativity is the statement that two caps can be applied in either order (DaoFP Exercise 15.2.1). In Haskell, when is an endofunctor, join = fmap counit (the left whiskering by is a lifting, the right whiskering by is instantiation done by type inference).

Examples

monadadjunction
List Monadfree monoid , x ↦ [x]foldr mappend memptyconcat
State Monadcurrying \a s -> (a, s)application uncurry runStatefmap counit
Writer Monadfree -set , x ↦ (x, 1)(x, m) ↦ a_m x((x,m),n) ↦ (x, n·m)
Maybe Monadpointed objects , Just[id, p]collapse Just (Just a)
Continuation Monad\a k -> k aevaluation\mm k -> mm (\m -> m k)
closure operatorGalois Connection idempotence

Most of these adjunctions leave the category of Haskell types (into , , ) even though the round trip is an endofunctor, which is why they cannot be written directly in Haskell. Composable adjunctions give monad transformers.

Docs: Kittenlab Lecture 7

using Catlab
# the free-monoid adjunction as a round trip on FinSets: T X = lists over X (Kittenlab lecture 7)
η(x) = [x]                                     # unit: generators
ε(ms::Vector{String}) = join(ms)               # counit at the String monoid: concatenate
μ(xss) = reduce(vcat, xss; init=Any[])         # U ε F = concat: multiplication of the list monad
μ([[1, 2], [3]])                               # [1, 2, 3]
import Mathlib
open CategoryTheory
#check @CategoryTheory.Adjunction.toMonad      -- (L ⊣ R) → Monad C, with μ = R ε L
#check @CategoryTheory.Adjunction.toComonad
#check @CategoryTheory.Monad.adj               -- the Eilenberg–Moore adjunction of a monad
#check @CategoryTheory.Kleisli.adjunction      -- the Kleisli adjunction
-- currying adjunction L s ⊣ R s and the state monad it generates
newtype L s a = L (a, s)
newtype R s c = R (s -> c)
instance Functor (R s) where fmap f (R g) = R (f . g)
unit :: a -> R s (L s a)
unit a = R (\s -> L (a, s))
counit :: L s (R s a) -> a
counit (L (R f, s)) = f s
mu :: R s (L s (R s (L s a))) -> R s (L s a)
mu = fmap counit                                  -- μ = R ∘ ε ∘ L