9. Higher inductive types
A higher inductive type has path constructors as well as point constructors. A path constructor takes interval arguments, and its boundary says what it is on the faces.
The circle
The circle has a point base and a loop that starts and ends at base:
loop takes an interval argument; loopP packages it as a path.
Functions out of the circle
A function out of a higher inductive type has a clause for each constructor. The clause for a path constructor must agree with the clauses for its boundary, which Kubus checks. To map the circle to itself, send base somewhere and loop i to a loop there:
A clause that does not respect the boundary is rejected:
clause for loop does not agree with its boundary: clause gives: negsuc zero boundary: pos zero context: i : I
The universal cover and winding numbers
The universal cover of the circle sends base to the integers and loop to the path Int = Int given by the successor equivalence (sucPathInt, made with ua). Transporting pos zero along the lift of a loop counts how often the loop winds around the circle:
and because ua computes, so does winding:
pos (suc zero) : Int
pos (suc (suc (suc zero))) : Int
negsuc (suc zero) : Int
pos (suc (suc zero)) : Int
The loop space of the circle is the integers
lib/loopspace.ktt proves that the type of loops at base is equal to Int, by an encode-decode argument and isoToPath:
loopSpaceS1 : Path U (Path S1 base base) Int
pos (suc (suc zero)) : Int
Transport along this path in the other direction turns an integer into a loop (again with sym^1, chapter 10):
λ i → hcomp k S1 [i = 0 -> base, i = 1 -> base] (hcomp k S1 [i = 0 -> base, i = 1 -> base] (loop ~i)) : Path S1 base base
Truncations and suspensions
Higher inductive types can have parameters. The propositional truncation of A has the elements of A and a path between any two elements; the suspension of A has two points and a path between them for every element of A:
Functions on parameterized higher inductive types are defined the same way:
Kubus does not yet support boundaries that apply functions to the constructor's arguments, so pushouts and general colimits cannot be declared directly yet.