definition theorem example program
The dependent product (pi type, dependent function type) is the type of functions whose return type depends on the argument: applied to gives . In sets, an element of selects one element from each — a giant tuple indexed by (for it is , whence “product”). In the fibration picture, a dependent function is a section of the bundle : “like a haircut, it cuts through each fiber”; in physics, a field over spacetime (Sheaf of Sections).
Sources: DaoFP §11.4 (“Dependent Product”: “Dependent product in Haskell”, “Dependent product of sets”, “Dependent product categorically”, “Adding the atlas”, “Universal quantification”), Exercises 11.4.1–11.4.2; 7 Sketches §7.3.3, §7.4.4.
The object of sections
Mimicking the Exponential Object (application ), the object of sections of has a dependent application with — the value lands in the right fiber — i.e. is a morphism in , universal:
Each cuts a horizontal slice of , which a fiberwise map sends to a section of ; so elements of are exactly sections. The counit is dependent function application.
Adding the atlas
Replacing by a base and by the pullback along gives the definition of as the right adjoint of the Base Change Functor:
written . The fiber of over is the set of partial sections of over the patch (DaoFP Exercise 11.4.2); localizes sections to neighbourhoods. Altogether in a Locally Cartesian Closed Category.
- Logic: is — a section proves every is inhabited (Quantification). The induction principle for produces an element of from and (Natural Numbers Object).
- Haskell has no ; one passes the index as a singleton value:
replicateV :: a -> SNat n -> Vec n areturns a different type for eachn— an infinite tuple((), x, (x,x), (x,x,x), ...).
Docs: FinSets
using Catlab
# sections of a finite bundle p : E → B = one element from each fiber (Π_{x:B} p⁻¹(x))
p = FinFunction([1, 1, 2, 3, 3], 3)
fibers = [preimage(p, x) for x in 1:3]
sections = collect(Iterators.product(fibers...)) # 2 · 1 · 2 = 4 sections
length(sections)
# Π_f localizes: for f : B → A, the fiber of Π_f E over y is the sections over f⁻¹(y)
f = FinFunction([1, 1, 2], 2)
[prod(length(fibers[x]) for x in preimage(f, y)) for y in 1:2] # [2, 2]import Mathlib
-- Π types are primitive in Lean: (x : B) → T x
example : (n : ℕ) → Fin (n + 1) := fun n => ⟨0, Nat.succ_pos n⟩ -- a section
#check @CategoryTheory.Over.pullback
-- Π_f is the right adjoint of pullback along f; Mathlib calls f exponentiable when it exists:
#check @CategoryTheory.ExponentiableMorphism
#check @CategoryTheory.ExponentiableMorphism.pushforward -- Π_f : Over I ⥤ Over J{-# LANGUAGE DataKinds, GADTs #-}
data SNat n where -- singletons stand in for the value n at the type level
SZ :: SNat 'Z
SS :: SNat n -> SNat ('S n)
replicateV :: a -> SNat n -> Vec n a -- a dependent function: result type depends on n
replicateV _ SZ = VNil
replicateV x (SS n) = VCons x (replicateV x n)