The power set monad on sends a set to its Power Set and a function to direct image, . The unit and multiplication are
It is the monad of nondeterminism: a Kleisli arrow returns a set of possible results, and composing two means collecting all results reachable through some intermediate. The List Monad is the same idea with order and multiplicity kept; is the commutative, idempotent quotient.
Sources: CTfS Example 5.3.2.3, Exercises 5.3.3.5–5.3.3.7; Kleisli Category; 7 Sketches §1.4 (Galois connection on power sets).
The monad laws on a small example
For (CTfS Example 5.3.2.3): is , , and has rows, e.g. , , . Unitality says ; associativity says a union of unions can be computed in either order.
Kleisli arrows are relations
Theorem (CTfS Exercise 5.3.3.5). , the Category of Relations.
Proof. A function is the same as the relation , and conversely. Kleisli composition is , i.e. is reachable from iff there is a with and — relational composition. The Kleisli identity is the diagonal relation.
Products and coproducts in are both disjoint unions: for and both are (CTfS Exercises 5.3.3.6–5.3.3.7) — a relation into is a pair of relations into and into . Such simultaneous products and coproducts are biproducts, which makes look like linear algebra over the Booleans: a relation is an Boolean matrix and Kleisli composition is matrix multiplication in the Quantale .
Further structure
- Adjunction. comes from the free–forgetful adjunction between sets and complete join-semilattices (sup-lattices): is the free sup-lattice on , and algebras for are exactly sup-lattices (Join, Monads from Adjunctions).
- Nondeterministic machines. A nondeterministic automaton is a Kleisli action of an alphabet (Finite State Machine); determinization is the subset construction — running the machine on .
- Kleisli instances. A -valued instance on the graph schema lets each arrow have any set of sources and targets (Kleisli Instance).
- The finite power set is also a monad; its algebras are join-semilattices with .
Docs: plain Julia — Catlab has no dedicated API for this; related: Catlab v0.16 docs · GATlab standard library
# the power set monad on finite sets: unit, multiplication, Kleisli composition
η(x) = Set([x])
μ(SS) = isempty(SS) ? Set() : union(SS...)
kleisli(f, g) = a -> μ(Set(g(b) for b in f(a))) # g ∘_P f
# μ on P(P({a, b})): 16 inputs (CTfS Example 5.3.2.3)
P(xs) = [Set(x for (i, x) in enumerate(xs) if isodd(m >> (i - 1))) for m in 0:2^length(xs) - 1]
length(P(P([:a, :b]))), μ(Set([Set([:a]), Set([:a, :b])])) # (16, Set([:a, :b]))
# Kleisli arrows are relations: parent/grandparent
parent = Dict(:ann => [:bob, :cat], :bob => [:dan], :cat => [:eve, :fay])
children(x) = Set(get(parent, x, Symbol[]))
kleisli(children, children)(:ann) # Set([:dan, :eve, :fay])
kleisli(η, children)(:ann) == children(:ann) == kleisli(children, η)(:ann) # unit lawsimport Mathlib
-- Set is a monad in Mathlib (pure = singleton, bind = indexed union)
#check (inferInstance : Monad Set)
example (x : ℕ) : (pure x : Set ℕ) = {x} := rfl
#check @Set.bind -- s.bind f = ⋃ a ∈ s, f a
#check @Rel.comp -- composition of relations = Kleisli compositionimport qualified Data.Set as Set
-- Data.Set is not a Monad instance (it needs Ord), so write the structure directly
unitP :: a -> Set.Set a
unitP = Set.singleton
joinP :: Ord a => Set.Set (Set.Set a) -> Set.Set a
joinP = Set.unions . Set.toList
kleisliP :: (Ord b, Ord c) => (a -> Set.Set b) -> (b -> Set.Set c) -> a -> Set.Set c
kleisliP f g = joinP . Set.map g . f -- relational composition
-- nondeterministic machine: step :: Char -> s -> Set s; a word acts by folding kleisliP