Limits and Colimits
Tutorial Video
Text description (accessibility)
This video demonstrates the "Limits and Colimits" functional Rust example. Difficulty level: Expert. Key concepts covered: Functional Programming. Limits and colimits are the categorical generalizations of "greatest lower bounds" and "least upper bounds." Products, terminal objects, equalizers, and pullbacks are all limits; coproducts, initial objects, coequalizers, and pushouts are all colimits. Key difference from OCaml: | Concept | Rust | OCaml |
Tutorial
The Problem
Limits and colimits are the categorical generalizations of "greatest lower bounds" and "least upper bounds." Products, terminal objects, equalizers, and pullbacks are all limits; coproducts, initial objects, coequalizers, and pushouts are all colimits. In type theory and functional programming, they correspond to familiar constructs: product types (limits), sum types (colimits), function spaces, and more. This example instantiates categorical limits and colimits as Rust types and shows the universal property that characterizes each.
🎯 Learning Outcomes
(A, B) is the limit of the diagram A ← • → BEither<A, B> is the colimit of the same diagramCode Example
#![allow(clippy::all)]
// Stub — awaiting conversion from OCaml source.Key Differences
| Concept | Rust | OCaml |
|---|---|---|
| Product | (A, B) tuple | record or tuple |
| Coproduct | enum Either<A,B> | type ('a,'b) either |
| Terminal | () unit | unit |
| Initial | ! (never, unstable) | type empty = \| |
| Equalizer | Vec filter | List.filter |
| Pullback | nested filter | List.concat_map |
Limits/colimits are why product types and sum types look the way they do: they are the unique objects satisfying universal properties up to isomorphism.
OCaml Approach
OCaml types directly embody limits and colimits:
(* Product = record/tuple *)
let product_univ fst snd c = (fst c, snd c)
(* Coproduct = variant *)
let coprod_univ inl inr = function
| Left a -> inl a
| Right b -> inr b
(* Equalizer = filtered list via List.filter *)
let equalizer f g xs = List.filter (fun x -> f x = g x) xs
(* Pullback = cartesian product filtered *)
let pullback f g xs ys =
List.concat_map (fun x ->
List.filter_map (fun y ->
if f x = g y then Some (x, y) else None) ys) xs
OCaml's type system makes the connection more transparent; Rust requires more scaffolding to express the same categorical ideas.
Full Source
#![allow(clippy::all)]
// Stub — awaiting conversion from OCaml source.Deep Comparison
OCaml vs Rust: Limits Colimits
Overview
See the example.rs and example.ml files for detailed implementations.
Key Differences
| Aspect | OCaml | Rust |
|---|---|---|
| Type system | Hindley-Milner | Ownership + traits |
| Memory | GC | Zero-cost abstractions |
| Mutability | Explicit ref | mut keyword |
| Error handling | Option/Result | Result<T, E> |
See README.md for detailed comparison.
Exercises
Either<L,R> enum and verify the universal property functions type-check.A <- C -> B, the pushout is a type that merges A and B while identifying the images of C.Option<A> is the coproduct A + () by implementing from_option and to_option witnessing the isomorphism.A₀ <- A₁ <- A₂ <- ... (inverse limit) as a type of compatible sequences.