less prototype, less bad code implementation of CCHM type theory
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2327 lines
81 KiB

  1. -- We begin by adding some primitive bindings using the PRIMITIVE pragma.
  2. --
  3. -- It goes like this: PRIMITIVE primName varName.
  4. --
  5. -- If the varName is dropped, then it's taken to be the same as primName.
  6. --
  7. -- If there is a previous declaration for the varName, then the type
  8. -- is checked against the internally-known "proper" type for the primitive.
  9. -- Universe of fibrant types
  10. {-# PRIMITIVE Type #-}
  11. -- Universe of non-fibrant types
  12. {-# PRIMITIVE Pretype #-}
  13. -- Fibrant is a fancy word for "has a composition structure". Most types
  14. -- we inherit from MLTT are fibrant:
  15. --
  16. -- Stuff like products Π, sums Σ, naturals, booleans, lists, etc., all
  17. -- have composition structures.
  18. --
  19. -- The non-fibrant types are part of the structure of cubical
  20. -- categories: The interval, partial elements, cubical subtypes, ...
  21. -- The interval
  22. ---------------
  23. -- The interval has two endpoints i0 and i1.
  24. -- These form a de Morgan algebra.
  25. I : Pretype
  26. {-# PRIMITIVE Interval I #-}
  27. i0, i1 : I
  28. {-# PRIMITIVE i0 #-}
  29. {-# PRIMITIVE i1 #-}
  30. -- "minimum" on the interval
  31. iand : I -> I -> I
  32. {-# PRIMITIVE iand #-}
  33. -- "maximum" on the interval.
  34. ior : I -> I -> I
  35. {-# PRIMITIVE ior #-}
  36. -- The interpretation of iand as min and ior as max justifies the fact that
  37. -- ior i (inot i) != i1, since that equality only holds for the endpoints.
  38. -- inot i = 1 - i is a de Morgan involution.
  39. inot : I -> I
  40. {-# PRIMITIVE inot #-}
  41. -- Paths
  42. --------
  43. -- Since every function in type theory is internally continuous,
  44. -- and the two endpoints i0 and i1 are equal, we can take the type of
  45. -- equalities to be continuous functions out of the interval.
  46. -- That is, x ≡ y iff. ∃ f : I -> A, f i0 = x, f i1 = y.
  47. -- The type PathP generalises this to dependent products (i : I) -> A i.
  48. PathP : (A : I -> Type) -> A i0 -> A i1 -> Type
  49. {-# PRIMITIVE PathP #-}
  50. -- By taking the first argument to be constant we get the equality type
  51. -- Path.
  52. Path : {A : Type} -> A -> A -> Type
  53. Path = PathP (\i -> A)
  54. -- reflexivity is given by constant paths
  55. refl : {A : Type} {x : A} -> Path x x
  56. refl i = x
  57. -- Symmetry (for dpeendent paths) is given by inverting the argument to the path, such that
  58. -- sym p i0 = p (inot i0) = p i1
  59. -- sym p i1 = p (inot i1) = p i0
  60. -- This has the correct endpoints.
  61. sym : {A : I -> Type} {x : A i0} {y : A i1} -> PathP A x y -> PathP (\i -> A (inot i)) y x
  62. sym p i = p (inot i)
  63. id : {A : Type} -> A -> A
  64. id x = x
  65. the : (A : Pretype) -> A -> A
  66. the A x = x
  67. -- The eliminator for the interval says that if you have x : A i0 and y : A i1,
  68. -- and x ≡ y, then you can get a proof A i for every element of the interval.
  69. iElim : {A : I -> Type} {x : A i0} {y : A i1} -> PathP A x y -> (i : I) -> A i
  70. iElim p i = p i
  71. -- This corresponds to the elimination principle for the HIT
  72. -- data I : Pretype where
  73. -- i0 i1 : I
  74. -- seg : i0 ≡ i1
  75. -- The singleton subtype of A at x is the type of elements of y which
  76. -- are equal to x.
  77. Singl : (A : Type) -> A -> Type
  78. Singl A x = (y : A) * Path x y
  79. -- Contractible types are those for which there exists an element to which
  80. -- all others are equal.
  81. isContr : Type -> Type
  82. isContr A = (x : A) * ((y : A) -> Path x y)
  83. -- Using the connection \i j -> y.2 (iand i j), we can prove that
  84. -- singletons are contracible. Together with transport later on,
  85. -- we get the J elimination principle of paths.
  86. dropJ : {A : Type} {x : A} {y : A} (p : Path x y)
  87. -> PathP (\i -> Path (p i) (p i)) refl refl
  88. dropJ p i j = p i
  89. dropI : {A : Type} {x : A} {y : A} (p : Path x y)
  90. -> PathP (\i -> Path x y) p p
  91. dropI p i j = p j
  92. and : {A : Type} {x : A} {y : A} (p : Path x y)
  93. -> PathP (\i -> Path x (p i)) refl p
  94. and p i j = p (iand i j)
  95. or : {A : Type} {x : A} {y : A} (p : Path x y)
  96. -> PathP (\i -> Path (p i) y) p refl
  97. or p i j = p (ior i j)
  98. singContr : {A : Type} {a : A} -> isContr (Singl A a)
  99. singContr = ((a, \i -> a), contr) where
  100. contr : (y : Singl A a) -> PathP (\i -> Singl A a) (a, \i -> a) y
  101. contr y i = (y.2 i, and y.2 i)
  102. -- Some more operations on paths. By rearranging parentheses we get a
  103. -- proof that the images of equal elements are themselves equal.
  104. ap : {A : Type} {B : A -> Type} (f : (x : A) -> B x) {x : A} {y : A} (p : Path x y) -> PathP (\i -> B (p i)) (f x) (f y)
  105. ap f p i = f (p i)
  106. -- These satisfy definitional equalities, like apComp and apId, which are
  107. -- propositional in vanilla MLTT.
  108. apComp : {A : Type} {B : Type} {C : Type}
  109. {f : A -> B} {g : B -> C} {x : A} {y : A}
  110. (p : Path x y)
  111. -> Path (ap g (ap f p)) (ap (\x -> g (f x)) p)
  112. apComp p = refl
  113. apId : {A : Type} {x : A} {y : A}
  114. (p : Path x y)
  115. -> Path (ap (id {A}) p) p
  116. apId p = refl
  117. -- Just like rearranging parentheses gives us ap, swapping the value
  118. -- and interval binders gives us function extensionality.
  119. funext : {A : Type} {B : A -> Type} {f : (x : A) -> B x} {g : (x : A) -> B x}
  120. (h : (x : A) -> Path (f x) (g x))
  121. -> Path f g
  122. funext h i x = h x i
  123. -- The proposition associated with an element of the interval
  124. -------------------------------------------------------------
  125. Eq_s : {A : Pretype} -> A -> A -> Pretype
  126. {-# PRIMITIVE Eq_s #-}
  127. refl_s : {A : Pretype} {x : A} -> Eq_s x x
  128. {-# PRIMITIVE refl_s #-}
  129. J_s : {A : Pretype} {x : A} (P : (y : A) -> Eq_s x y -> Pretype) -> P x (refl_s {A} {x}) -> {y : A} -> (p : Eq_s x y) -> P y p
  130. {-# PRIMITIVE J_s #-}
  131. K_s : {A : Pretype} {x : A} (P : Eq_s x x -> Pretype) -> P (refl_s {A} {x}) -> (p : Eq_s x x) -> P p
  132. {-# PRIMITIVE K_s #-}
  133. -- Associated with every element i : I of the interval, we have the type
  134. -- IsOne i which is inhabited only when i = i1. In the model, this
  135. -- corresponds to the map [φ] from the interval cubical set to the
  136. -- subobject classifier.
  137. IsOne : I -> Pretype
  138. IsOne i = Eq_s i i1
  139. -- The value itIs1 witnesses the fact that i1 = i1.
  140. itIs1 : IsOne i1
  141. itIs1 = refl_s
  142. -- Partial elements
  143. -------------------
  144. --
  145. -- Since a function I -> A has two endpoints, and a function I -> I -> A
  146. -- has four endpoints + four functions I -> A as "sides" (obtained by
  147. -- varying argument while holding the other as a bound variable), we
  148. -- refer to elements of I^n -> A as "cubes".
  149. -- This justifies the existence of partial elements, which are, as the
  150. -- name implies, partial cubes. Namely, a Partial φ A is an element of A
  151. -- which depends on a proof that IsOne φ.
  152. Partial : I -> Type -> Pretype
  153. {-# PRIMITIVE Partial #-}
  154. -- There is also a dependent version where the type A is itself a
  155. -- partial element.
  156. PartialP : (phi : I) -> Partial phi Type -> Pretype
  157. {-# PRIMITIVE PartialP #-}
  158. partialExt : {A : Type} (phi : I) (psi : I) -> Partial phi A -> Partial psi A -> Partial (ior phi psi) A
  159. {-# PRIMITIVE partialExt #-}
  160. -- Why is Partial φ A not just defined as φ -> A? The difference is that
  161. -- Partial φ A has an internal representation which definitionally relates
  162. -- any two partial elements which "agree everywhere", that is, have
  163. -- equivalent values for every possible assignment of variables which
  164. -- makes IsOne φ hold.
  165. -- Cubical Subtypes
  166. --------------------
  167. -- Given A : Type, phi : I, and a partial element u : A defined on φ,
  168. -- we have the type Sub A phi u, notated A[phi -> u] in the output of
  169. -- the type checker, whose elements are "extensions" of u.
  170. -- That is, element of A[phi -> u] is an element of A defined everywhere
  171. -- (a total element), which, when IsOne φ, agrees with u.
  172. Sub : (A : Type) (phi : I) -> Partial phi A -> Pretype
  173. {-# PRIMITIVE Sub #-}
  174. -- Every total element u : A can be made partial on φ by ignoring the
  175. -- constraint. Furthermore, this "totally partial" element agrees with
  176. -- the original total element on φ.
  177. inS : {A : Type} {phi : I} (u : A) -> Sub A phi (\x -> u)
  178. {-# PRIMITIVE inS #-}
  179. -- When IsOne φ, outS {A} {φ} {u} x reduces to u itIs1.
  180. -- This implements the fact that x agrees with u on φ.
  181. outS : {A : Type} {phi : I} {u : Partial phi A} -> Sub A phi u -> A
  182. {-# PRIMITIVE outS #-}
  183. -- The composition operation
  184. ----------------------------
  185. -- Now that we have syntax for specifying partial cubes,
  186. -- and specifying that an element agrees with a partial cube,
  187. -- we can describe the composition operation.
  188. primComp : (A : I -> Type) {phi : I} (u : (i : I) -> Partial phi (A i)) -> Sub (A i0) phi (u i0) -> Sub (A i1) phi (u i1)
  189. {-# PRIMITIVE comp primComp #-}
  190. comp : (A : I -> Type) {phi : I} (u : (i : I) -> Partial phi (A i)) -> Sub (A i0) phi (u i0) -> A i1
  191. comp A u a0 = outS (primComp A {phi} u a0)
  192. -- In particular, when φ is a disjunction of the form
  193. -- (j = 0) || (j = 1), we can draw u as being a pair of lines forming a
  194. -- "tube", an open square with no floor or roof:
  195. --
  196. -- Given u = \j [ (i = i0) -> x, (i = i1) -> q j] on the extent i || ~i,
  197. -- we draw:
  198. --
  199. -- x q i1
  200. -- | |
  201. -- \j -> x | | \j -> q j
  202. -- | |
  203. -- x q i0
  204. --
  205. -- The composition operation says that, as long as we can provide a
  206. -- "floor" connecting x -- q i0, as a total element of A which, on
  207. -- phi, extends u i0, then we get the "roof" connecting x and q i1
  208. -- for free.
  209. --
  210. -- If we have a path p : x ≡ y, and q : y ≡ z, then we do get the
  211. -- "floor", and composition gets us the dotted line:
  212. --
  213. -- x..........z
  214. -- | |
  215. -- x | | q j
  216. -- | |
  217. -- x----------y
  218. -- p i
  219. -- In particular when the formula φ = i0 we get the "opposite face" to a
  220. -- single point, which corresponds to transport.
  221. transp : (A : I -> Type) (x : A i0) -> A i1
  222. transp A x = comp A (\i [ ]) (inS x)
  223. subst : {A : Type} (P : A -> Type) {x : A} {y : A} -> Path x y -> P x -> P y
  224. subst P p x = transp (\i -> P (p i)) x
  225. -- Since we have the iand operator, we can also derive the *filler* of a cube,
  226. -- which connects the given face and the output of composition.
  227. fill : (A : I -> Type) {phi : I} (u : (i : I) -> Partial phi (A i)) (a0 : Sub (A i0) phi (u i0))
  228. -> PathP A (outS a0) (comp A {phi} u a0)
  229. fill A u a0 i =
  230. comp (\j -> A (iand i j))
  231. {ior phi (inot i)}
  232. (\j [ (phi = i1) -> u (iand i j) itIs1
  233. , (i = i0) -> outS {A i0} {phi} {u i0} a0
  234. ])
  235. (inS (outS a0))
  236. hcomp : {A : Type} {phi : I} (u : (i : I) -> Partial phi A) -> Sub A phi (u i0) -> A
  237. hcomp u a0 = comp (\i -> A) {phi} u a0
  238. hfill : {A : Type} {phi : I} (u : (i : I) -> Partial phi A) -> (a0 : Sub A phi (u i0)) -> Path (outS a0) (hcomp u a0)
  239. hfill u a0 i = fill (\i -> A) {phi} u a0 i
  240. trans : {A : Type} {x : A} {y : A} {z : A} -> PathP (\i -> A) x y -> PathP (\i -> A) y z -> PathP (\i -> A) x z
  241. trans p q i = comp (\j -> A) {ior i (inot i)} (\k [ (i = i0) -> x, (i = i1) -> q k ]) (inS {A} {ior i (inot i)} (p i))
  242. transFiller : {A : Type} {x : A} {y : A} {z : A}
  243. -> (p : Path x y) (q : Path y z)
  244. -> PathP (\i -> Path x (q i)) p (trans {A} {x} {y} {z} p q)
  245. transFiller p q j i = hfill (\k [ (i = i0) -> x, (i = i1) -> q k ]) (inS (p i)) j
  246. transFiller' : {A : Type} {x : A} {y : A} {z : A}
  247. -> (p : Path x y) (q : Path y z)
  248. -> PathP (\i -> Path (p (inot i)) z) q (trans {A} {x} {y} {z} p q)
  249. transFiller' p q j i = hcomp (\k [ (i = i0) -> p (inot j)
  250. , (i = i1) -> q k
  251. , (j = i0) -> q (iand i k) ])
  252. (inS (p (ior i (inot j))))
  253. transAssoc : {A : Type} {w : A} {x : A} {y : A} {z : A} (p : Path w x) (q : Path x y) (r : Path y z)
  254. -> Path (trans p (trans q r)) (trans (trans p q) r)
  255. transAssoc p q r k = trans (transFiller p q k) (transFiller' q r (inot k))
  256. dubcomp : {A : Type} {a : A} {b : A} {c : A} {d : A}
  257. -> Path a b -> Path b c -> Path c d -> Path a d
  258. dubcomp p q r i = hcomp (\j [ (i = i0) -> p (inot j), (i = i1) -> r j ]) (inS (q i))
  259. -- For instance, the filler of the previous composition square
  260. -- tells us that trans p refl = p:
  261. transRefl : {A : Type} {x : A} {y : A} (p : Path x y) -> Path (trans p refl) p
  262. transRefl p j i = fill (\i -> A) {ior i (inot i)} (\k [ (i = i0) -> x, (i = i1) -> y ]) (inS (p i)) (inot j)
  263. rightCancel : {A : Type} {x : A} {y : A} (p : Path x y) -> Path (trans p (sym p)) refl
  264. rightCancel p j i = cube p i1 j i where
  265. cube : {A : Type} {x : A} {y : A} (p : Path x y) -> I -> I -> I -> A
  266. cube p k j i =
  267. hfill (\ k [ (i = i0) -> x
  268. , (i = i1) -> p (iand (inot k) (inot j))
  269. , (j = i1) -> x
  270. ])
  271. (inS (p (iand i (inot j)))) k
  272. leftCancel : {A : Type} {x : A} {y : A} (p : Path x y) -> Path (trans (sym p) p) refl
  273. leftCancel p = rightCancel (sym p)
  274. transpFill : (A : I -> Type) (x : A i0) -> PathP A x (transp (\i -> A i) x)
  275. transpFill A x i = fill (\i -> A i) (\k []) (inS x) i
  276. -- Reduction of composition
  277. ---------------------------
  278. --
  279. -- Composition reduces on the structure of the family A : I -> Type to create
  280. -- the element a1 : (A i1)[phi -> u i1].
  281. --
  282. -- For instance, when filling a cube of functions, the behaviour is to
  283. -- first transport backwards along the domain, apply the function, then
  284. -- forwards along the codomain.
  285. transpFun : {A : Type} {B : Type} {C : Type} {D : Type} (p : Path A B) (q : Path C D)
  286. -> (f : A -> C) -> Path (transp (\i -> p i -> q i) f)
  287. (\x -> transp (\i -> q i) (f (transp (\i -> p (inot i)) x)))
  288. transpFun p q f = refl
  289. transpDFun : {A : I -> Type} {B : (i : I) -> A i -> Type}
  290. -> (f : (x : A i0) -> B i0 x)
  291. -> Path (transp (\i -> (x : A i) -> B i x) f)
  292. (\x -> transp (\i -> B i (fill (\j -> A (inot j)) (\k []) (inS x) (inot i)))
  293. (f (fill (\j -> A (inot j)) (\k []) (inS x) i1)))
  294. transpDFun f = refl
  295. -- When considering the more general case of a composition respecing sides,
  296. -- the outer transport becomes a composition.
  297. -- Glueing and Univalence
  298. -------------------------
  299. -- First, let's get some definitions out of the way.
  300. --
  301. -- The *fiber* of a function f : A -> B at a point y : B is the type of
  302. -- inputs x : A which f takes to y, that is, for which there exists a
  303. -- path f(x) = y.
  304. fiber : {A : Type} {B : Type} -> (A -> B) -> B -> Type
  305. fiber f y = (x : A) * Path y (f x)
  306. -- An *equivalence* is a function where every fiber is contractible.
  307. -- That is, for every point in the codomain y : B, there is exactly one
  308. -- point in the input which f maps to y.
  309. isEquiv : {A : Type} {B : Type} -> (A -> B) -> Type
  310. isEquiv {A} {B} f = (y : B) -> isContr (fiber {A} {B} f y)
  311. -- By extracting this point, which must exist because the fiber is contractible,
  312. -- we can get an inverse of f:
  313. invert : {A : Type} {B : Type} {f : A -> B} -> isEquiv f -> B -> A
  314. invert eqv y = (eqv y) .1 .1
  315. retract : {A : Type} {B : Type} -> (A -> B) -> (B -> A) -> Type
  316. retract f g = (a : A) -> Path (g (f a)) a
  317. -- Proving that it's also a retraction is left as an exercise to the
  318. -- reader. We can package together a function and a proof that it's an
  319. -- equivalence to get a capital-E Equivalence.
  320. Equiv : (A : Type) (B : Type) -> Type
  321. Equiv A B = (f : A -> B) * isEquiv {A} {B} f
  322. -- The identity function is an equivalence between any type A and
  323. -- itself.
  324. idEquiv : {A : Type} -> Equiv A A
  325. idEquiv = (\x -> x, \y -> ((y, \i -> y), \u i -> (u.2 i, \j -> u.2 (iand i j))))
  326. -- The glue operation expresses that "extensibility is invariant under
  327. -- equivalence". Less concisely, the Glue type and its constructor,
  328. -- glue, let us extend a partial element of a partial type to a total
  329. -- element of a total type, by "gluing" the partial type T using a
  330. -- partial equivalence e onto a total type A.
  331. -- In particular, we have that when φ = i1, Glue A [i1 -> (T, f)] = T.
  332. primGlue : (A : Type) {phi : I}
  333. (T : Partial phi Type)
  334. (e : PartialP phi (\o -> Equiv (T o) A))
  335. -> Type
  336. {-# PRIMITIVE Glue primGlue #-}
  337. -- The glue constructor extends the partial element t : T to a total
  338. -- element of Glue A [φ -> (T, e)] as long as we have a total im : A
  339. -- which is the image of f(t).
  340. --
  341. -- Agreeing with the condition that Glue A [i1 -> (T, e)] = T,
  342. -- we have that glue {A} {i1} t im => t.
  343. prim'glue : {A : Type} {phi : I} {T : Partial phi Type} {e : PartialP phi (\o -> Equiv (T o) A)}
  344. -> (t : PartialP phi (\o -> T o))
  345. -> (im : Sub A phi (\o -> (e o).1 (t o)))
  346. -> primGlue A T e
  347. {-# PRIMITIVE glue prim'glue #-}
  348. glue : {A : Type} {phi : I} {Te : Partial phi ((T : Type) * Equiv T A)}
  349. -> (t : PartialP phi (\o -> (Te o).1))
  350. -> (im : Sub A phi (\o -> (Te o).2.1 (t o)))
  351. -> primGlue A {phi} (\o -> (Te o).1) (\o -> (Te o).2)
  352. glue t im = prim'glue {A} {phi} {\o -> (Te o).1} {\o -> (Te o).2} t im
  353. -- The unglue operation undoes a glueing. Since when φ = i1,
  354. -- Glue A [φ -> (T, f)] = T, the argument to primUnglue {A} {i1} ...
  355. -- will have type T, and so to get back an A we need to apply the
  356. -- partial equivalence f (defined everywhere).
  357. primUnglue : {A : Type} {phi : I} {T : Partial phi Type} {e : PartialP phi (\o -> Equiv (T o) A)}
  358. -> primGlue A {phi} T e -> A
  359. {-# PRIMITIVE unglue primUnglue #-}
  360. unglue : {A : Type} (phi : I) {Te : Partial phi ((T : Type) * Equiv T A)}
  361. -> primGlue A {phi} (\o -> (Te o).1) (\o -> (Te o).2) -> A
  362. unglue phi = primUnglue {A} {phi} {\o -> (Te o).1} {\o -> (Te o).2}
  363. -- Diagramatically, i : I |- Glue A [(i \/ ~i) -> (T, e)] can be drawn
  364. -- as giving us the dotted line in:
  365. --
  366. -- T i0 ......... T i1
  367. -- | |
  368. -- | |
  369. -- e i0 |~ ~| e i1
  370. -- | |
  371. -- | |
  372. -- A i0 --------- A i1
  373. -- A
  374. --
  375. -- Where the the two "e" sides are equivalences, and the Bottom side is
  376. -- the line i : I |- A.
  377. --
  378. -- Thus, by choosing a base type, a set of partial types and partial
  379. -- equivalences, we can make a line between two types (T i0) and (T i1).
  380. Glue : (A : Type) {phi : I} -> Partial phi ((X : Type) * Equiv X A) -> Type
  381. Glue A u = primGlue A {phi} (\o -> (u o).1) (\o -> (u o).2)
  382. -- For example, we can glue together the type A and the type B as long
  383. -- as there exists an Equiv A B.
  384. --
  385. -- A ............ B
  386. -- | |
  387. -- | |
  388. -- equiv |~ ua equiv ~| idEquiv {B}
  389. -- | |
  390. -- | |
  391. -- B ------------ B
  392. -- \i → B
  393. --
  394. ua : {A : Type} {B : Type} -> Equiv A B -> Path A B
  395. ua equiv i =
  396. Glue B (\[ (i = i0) -> (A, equiv)
  397. , (i = i1) -> (B, idEquiv) ])
  398. lineToEquiv : (A : I -> Type) -> Equiv (A i0) (A i1)
  399. {-# PRIMITIVE lineToEquiv #-}
  400. idToEquiv : {A : Type} {B : Type} -> Path A B -> Equiv A B
  401. idToEquiv p = lineToEquiv (\i -> p i)
  402. isEquivTransport : (A : I -> Type) -> isEquiv (transp A)
  403. isEquivTransport A = (lineToEquiv A).2
  404. -- The fact that this diagram has 2 filled-in B sides explains the
  405. -- complication in the proof below.
  406. --
  407. -- In particular, the actual behaviour of transp (\i -> ua f i)
  408. -- (x : A) is not just to apply f x to get a B (the left side), it also
  409. -- needs to:
  410. --
  411. -- * For the Bottom side, compose along (\i -> B) (the Bottom side)
  412. -- * For the right side, apply the inverse of the identity, which
  413. -- is just identity, to get *some* b : B
  414. --
  415. -- But that b : B might not agree with the sides of the composition
  416. -- operation in a more general case, so it composes along (\i -> B)
  417. -- *again*!
  418. --
  419. -- Thus the proof: a simple cubical argument suffices, since
  420. -- for any composition, its filler connects either endpoints. So
  421. -- we need to come up with a filler for the Bottom and right faces.
  422. uaBeta : {A : Type} {B : Type} (f : Equiv A B) -> Path (transp (\i -> ua f i)) f.1
  423. uaBeta f i a = transpFill (\i -> B) (f.1 a) (inot i)
  424. -- The terms ua + uaBeta suffice to prove the "full"
  425. -- ua axiom of Voevodsky, as can be seen in the paper
  426. --
  427. -- Ian Orton, & Andrew M. Pitts. (2017). Decomposing the Univalence Axiom.
  428. --
  429. -- Available freely here: https://arxiv.org/abs/1712.04890v3
  430. J : {A : Type} {x : A}
  431. (P : (y : A) -> Path x y -> Type)
  432. (d : P x (\i -> x))
  433. {y : A} (p : Path x y)
  434. -> P y p
  435. J P d p = transp (\i -> P (p i) (\j -> p (iand i j))) d
  436. JRefl : {A : Type} {x : A}
  437. (P : (y : A) -> Path x y -> Type)
  438. (d : P x (\i -> x))
  439. -> Path (J {A} {x} P d {x} (\i -> x)) d
  440. JRefl P d i = transpFill (\i -> P x (\j -> x)) d (inot i)
  441. Jay : {A : Type} {x : A}
  442. (P : ((y : A) * Path x y) -> Type)
  443. (d : P (x, refl))
  444. (s : (y : A) * Path x y)
  445. -> P s
  446. Jay P d s = transp (\i -> P ((singContr {A} {x}).2 s i)) d
  447. -- Isomorphisms
  448. ---------------
  449. --
  450. -- Since isomorphisms are a much more convenient notion of equivalence
  451. -- than contractible fibers, it's natural to ask why the CCHM paper, and
  452. -- this implementation following that, decided on the latter for our
  453. -- definition of equivalence.
  454. isIso : {A : Type} -> {B : Type} -> (A -> B) -> Type
  455. isIso f = (g : B -> A) * ((y : B) -> Path (f (g y)) y) * ((x : A) -> Path (g (f x)) x)
  456. -- The reason is that the family of types IsIso is not a proposition!
  457. -- This means that there can be more than one way for a function to be
  458. -- an equivalence. This is Lemma 4.1.1 of the HoTT book.
  459. Iso : Type -> Type -> Type
  460. Iso A B = (f : A -> B) * isIso f
  461. -- Nevertheless, we can prove that any function with an isomorphism
  462. -- structure has contractible fibers, using a cubical argument adapted
  463. -- from CCHM's implementation of cubical type theory:
  464. --
  465. -- https://github.com/mortberg/cubicaltt/blob/master/experiments/isoToEquiv.ctt#L7-L55
  466. IsoToEquiv : {A : Type} {B : Type} -> Iso A B -> Equiv A B
  467. IsoToEquiv iso = (f, \y -> (fCenter y, fIsCenter y)) where
  468. f = iso.1
  469. g = iso.2.1
  470. s = iso.2.2.1
  471. t = iso.2.2.2
  472. lemIso : (y : B) (x0 : A) (x1 : A) (p0 : Path y (f x0)) (p1 : Path y (f x1))
  473. -> PathP (\i -> fiber f y) (x0, p0) (x1, p1)
  474. lemIso y x0 x1 p0 p1 =
  475. let
  476. rem0 : Path x0 (g y)
  477. rem0 i = hcomp (\k [ (i = i0) -> t x0 k, (i = i1) -> g y ]) (inS (g (p0 (inot i))))
  478. rem1 : Path x1 (g y)
  479. rem1 i = hcomp (\k [ (i = i0) -> t x1 k, (i = i1) -> g y ]) (inS (g (p1 (inot i))))
  480. p : Path x0 x1
  481. p i = hcomp (\k [ (i = i0) -> rem0 (inot k), (i = i1) -> rem1 (inot k) ]) (inS (g y))
  482. fill0 : I -> I -> A
  483. fill0 i j = hcomp (\k [ (i = i0) -> t x0 (iand j k)
  484. , (i = i1) -> g y
  485. , (j = i0) -> g (p0 (inot i))
  486. ])
  487. (inS (g (p0 (inot i))))
  488. fill1 : I -> I -> A
  489. fill1 i j = hcomp (\k [ (i = i0) -> t x1 (iand j k)
  490. , (i = i1) -> g y
  491. , (j = i0) -> g (p1 (inot i)) ])
  492. (inS (g (p1 (inot i))))
  493. fill2 : I -> I -> A
  494. fill2 i j = hcomp (\k [ (i = i0) -> rem0 (ior j (inot k))
  495. , (i = i1) -> rem1 (ior j (inot k))
  496. , (j = i1) -> g y ])
  497. (inS (g y))
  498. sq : I -> I -> A
  499. sq i j = hcomp (\k [ (i = i0) -> fill0 j (inot k)
  500. , (i = i1) -> fill1 j (inot k)
  501. , (j = i1) -> g y
  502. , (j = i0) -> t (p i) (inot k) ])
  503. (inS (fill2 i j))
  504. sq1 : I -> I -> B
  505. sq1 i j = hcomp (\k [ (i = i0) -> s (p0 (inot j)) k
  506. , (i = i1) -> s (p1 (inot j)) k
  507. , (j = i0) -> s (f (p i)) k
  508. , (j = i1) -> s y k
  509. ])
  510. (inS (f (sq i j)))
  511. in \i -> (p i, \j -> sq1 i (inot j))
  512. fCenter : (y : B) -> fiber f y
  513. fCenter y = (g y, sym (s y))
  514. fIsCenter : (y : B) (w : fiber f y) -> Path (fCenter y) w
  515. fIsCenter y w = lemIso y (fCenter y).1 w.1 (fCenter y).2 w.2
  516. IsoToId : {A : Type} {B : Type} -> Iso A B -> Path A B
  517. IsoToId i = ua (IsoToEquiv i)
  518. -- We can prove that any involutive function is an isomorphism, since
  519. -- such a function is its own inverse.
  520. involToIso : {A : Type} (f : A -> A) -> ((x : A) -> Path (f (f x)) x) -> isIso f
  521. involToIso f inv = (f, inv, inv)
  522. -- An example of ua
  523. ---------------------------
  524. --
  525. -- The classic example of ua is the equivalence
  526. -- not : Bool \simeq Bool.
  527. --
  528. -- We define it here.
  529. data Bool : Type where
  530. true : Bool
  531. false : Bool
  532. not : Bool -> Bool
  533. not = \case
  534. true -> false
  535. false -> true
  536. elimBool : (P : Bool -> Type) -> P true -> P false -> (b : Bool) -> P b
  537. elimBool P x y = \case
  538. true -> x
  539. false -> y
  540. if : {A : Type} -> A -> A -> Bool -> A
  541. if x y = \case
  542. true -> x
  543. false -> y
  544. -- By pattern matching it suffices to prove (not (not true)) ≡ true and
  545. -- not (not false) ≡ false. Since not (not true) computes to true (resp.
  546. -- false), both proofs go through by refl.
  547. notInvol : (x : Bool) -> Path (not (not x)) x
  548. notInvol = elimBool (\b -> Path (not (not b)) b) refl refl
  549. notp : Path Bool Bool
  550. notp = ua (IsoToEquiv (not, involToIso not notInvol))
  551. -- This path actually serves to prove a simple lemma about the universes
  552. -- of HoTT, namely, that any univalent universe is not a 0-type. If we
  553. -- had HITs, we could prove that this fact holds for any n, but for now,
  554. -- proving it's not an h-set is the furthest we can go.
  555. -- First we define what it means for something to be false. In type theory,
  556. -- we take ¬P = P → ⊥, where the Bottom type is the only type satisfying
  557. -- the elimination principle
  558. --
  559. -- elimBottom : (P : Bottom -> Type) -> (b : Bottom) -> P b
  560. --
  561. -- This follows from setting Bottom := ∀ A, A.
  562. data Bottom : Type where {}
  563. elimBottom : (P : Bottom -> Pretype) -> (b : Bottom) -> P b
  564. elimBottom P = \case {}
  565. absurd : {P : Pretype} -> Bottom -> P
  566. absurd = \case {}
  567. -- We prove that true != false by transporting along the path
  568. --
  569. -- \i -> if (Bool -> Bool) A (p i)
  570. -- (Bool -> Bool) ------------------------------------ A
  571. --
  572. -- To verify that this has the correct endpoints, check out the endpoints
  573. -- for p:
  574. --
  575. -- true ------------------------------------ false
  576. --
  577. -- and evaluate the if at either end.
  578. trueNotFalse : Path true false -> Bottom
  579. trueNotFalse p = transp (\i -> if (Bool -> Bool) Bottom (p i)) id
  580. -- To be an h-Set is to have no "higher path information". Alternatively,
  581. --
  582. -- isSet A = (x : A) (y : A) -> isHProp (Path x y)
  583. --
  584. isProp : Type -> Type
  585. isProp A = (x : A) (y : A) -> Path x y
  586. isSet : Type -> Type
  587. isSet A = (x : A) (y : A) -> isProp (Path x y)
  588. -- We can prove *a* contradiction (note: this is a direct proof!) by adversarially
  589. -- choosing two paths p, q that we know are not equal. Since "equal" paths have
  590. -- equal behaviour when transporting, we can choose two paths p, q and a point x
  591. -- such that transporting x along p gives a different result from x along q.
  592. --
  593. -- Since transp notp = not but transp refl = id, that's what we go with. The choice
  594. -- of false as the point x is just from the endpoints of trueNotFalse.
  595. universeNotSet : isSet Type -> Bottom
  596. universeNotSet itIs = trueNotFalse (\i -> transp (\j -> itIs Bool Bool notp refl i j) false)
  597. -- Funext is an inverse of happly
  598. ---------------------------------
  599. --
  600. -- Above we proved function extensionality, namely, that functions
  601. -- pointwise equal everywhere are themselves equal.
  602. -- However, this formulation of the axiom is known as "weak" function
  603. -- extensionality. The strong version is as follows:
  604. Hom : {A : Type} {B : A -> Type} (f : (x : A) -> B x) -> (g : (x : A) -> B x) -> Type
  605. Hom f g = (x : A) -> Path (f x) (g x)
  606. happly : {A : Type} {B : A -> Type} {f : (x : A) -> B x} {g : (x : A) -> B x}
  607. -> (p : Path f g) -> Hom f g
  608. happly p x i = p i x
  609. -- Strong function extensionality: happly is an equivalence.
  610. happlyIsIso : {A : Type} {B : A -> Type} {f : (x : A) -> B x} {g : (x : A) -> B x}
  611. -> isIso {Path f g} {Hom f g} happly
  612. happlyIsIso = (funext {A} {B} {f} {g}, \hom -> refl, \path -> refl)
  613. pathIsHom : {A : Type} {B : A -> Type} {f : (x : A) -> B x} {g : (x : A) -> B x}
  614. -> Path (Path f g) (Hom f g)
  615. pathIsHom =
  616. let
  617. theIso : Iso (Path f g) (Hom f g)
  618. theIso = (happly {A} {B} {f} {g}, happlyIsIso {A} {B} {f} {g})
  619. in ua (IsoToEquiv theIso)
  620. -- Inductive types
  621. -------------------
  622. --
  623. -- An inductive type is a type freely generated by a finite set of
  624. -- constructors. For instance, the type of natural numbers is generated
  625. -- by the constructors for "zero" and "successor".
  626. data Nat : Type where
  627. zero : Nat
  628. succ : Nat -> Nat
  629. -- Pattern matching allows us to prove that these initial types are
  630. -- initial algebras for their corresponding functors.
  631. Nat_elim : (P : Nat -> Type) -> P zero -> ((x : Nat) -> P x -> P (succ x)) -> (x : Nat) -> P x
  632. Nat_elim P pz ps = \case
  633. zero -> pz
  634. succ x -> ps x (Nat_elim P pz ps x)
  635. zeroNotSucc : {x : Nat} -> Path zero (succ x) -> Bottom
  636. zeroNotSucc p = transp (\i -> fun (p i)) (p i0) where
  637. fun : Nat -> Type
  638. fun = \case
  639. zero -> Nat
  640. succ x -> Bottom
  641. pred : Nat -> Nat
  642. pred = \case
  643. zero -> zero
  644. succ x -> x
  645. succInj : {x : Nat} {y : Nat} -> Path (succ x) (succ y) -> Path x y
  646. succInj p i = pred (p i)
  647. -- The type of integers can be defined as A + B, where "pos n" means +n
  648. -- and "neg n" means -(n + 1).
  649. data Int : Type where
  650. pos : Nat -> Int
  651. neg : Nat -> Int
  652. -- On this representation we can define the successor and predecessor
  653. -- functions by (nested) induction.
  654. sucZ : Int -> Int
  655. sucZ = \case
  656. pos n -> pos (succ n)
  657. neg n ->
  658. let suc_neg : Nat -> Int
  659. suc_neg = \case
  660. zero -> pos zero
  661. succ n -> neg n
  662. in suc_neg n
  663. predZ : Int -> Int
  664. predZ = \case
  665. pos n ->
  666. let pred_pos : Nat -> Int
  667. pred_pos = \case
  668. zero -> neg zero
  669. succ n -> pos n
  670. in pred_pos n
  671. neg n -> neg (succ n)
  672. -- And prove that the successor function is an isomorphism, and thus, an
  673. -- equivalence.
  674. sucPredZ : (x : Int) -> Path (sucZ (predZ x)) x
  675. sucPredZ = \case
  676. pos n ->
  677. let k : (n : Nat) -> Path (sucZ (predZ (pos n))) (pos n)
  678. k = \case
  679. zero -> refl
  680. succ n -> refl
  681. in k n
  682. neg n -> refl
  683. predSucZ : (x : Int) -> Path (predZ (sucZ x)) x
  684. predSucZ = \case
  685. pos n -> refl
  686. neg n ->
  687. let k : (n : Nat) -> Path (predZ (sucZ (neg n))) (neg n)
  688. k = \case
  689. zero -> refl
  690. succ n -> refl
  691. in k n
  692. sucEquiv : Equiv Int Int
  693. sucEquiv = IsoToEquiv (sucZ, (predZ, sucPredZ, predSucZ))
  694. -- Univalence gives us a path between integers such that transp intPath
  695. -- x = suc x, transp (sym intPath) x = pred x
  696. intPath : Path Int Int
  697. intPath = ua sucEquiv
  698. -- Higher inductive types
  699. -------------------------
  700. --
  701. -- While inductive types let us generate discrete spaces like the
  702. -- naturals or integers, they do not support defining higher-dimensional
  703. -- structures given by spaces with points and paths.
  704. -- A very simple higher inductive type is the interval, given by
  705. data Interval : Type where
  706. ii0 : Interval
  707. ii1 : Interval
  708. seg i : Interval [ (i = i0) -> ii0, (i = i1) -> ii1 ]
  709. -- This expresses that we have two points ii0 and ii1 and a path (\i ->
  710. -- seg i) with endpoints ii0 and ii1.
  711. -- With this type we can reproduce the proof of Lemma 6.3.2 from the
  712. -- HoTT book:
  713. iFunext : {A : Type} {B : A -> Type} (f : (x : A) -> B x) (g : (x : A) -> B x)
  714. -> ((x : A) -> Path (f x) (g x)) -> Path f g
  715. iFunext f g p i = h' (seg i) where
  716. h : (x : A) -> Interval -> B x
  717. h x = \case
  718. ii0 -> f x
  719. ii1 -> g x
  720. seg i -> p x i
  721. h' : Interval -> (x : A) -> B x
  722. h' i x = h x i
  723. -- Of course, Cubical Type Theory also has an interval (pre)type, but
  724. -- that, unlike the Interval here, is not Kan: it has no composition
  725. -- structure.
  726. -- Another simple higher-inductive type is the circle, with a point and
  727. -- a non-trivial loop, (\i -> loop i).
  728. data S1 : Type where
  729. base : S1
  730. loop i : S1 [ (i = i1) -> base, (i = i0) -> base ]
  731. -- By writing a function from the circle to the universe of types Type,
  732. -- we can calculate winding numbers along the circle.
  733. helix : S1 -> Type
  734. helix = \case
  735. base -> Int
  736. loop i -> intPath i
  737. loopP : Path base base
  738. loopP i = loop i
  739. encode : (x : S1) -> Path base x -> helix x
  740. encode x p = subst helix p (pos zero)
  741. winding : Path base base -> Int
  742. winding = encode base
  743. -- For instance, going around the loop once has a winding number of +1,
  744. windingLoop : Path (winding (\i -> loop i)) (pos (succ zero))
  745. windingLoop = refl
  746. -- Going backwards has a winding number of -1 (remember the
  747. -- representation of integers),
  748. windingSymLoop : Path (winding (\i -> loop (inot i))) (neg zero)
  749. windingSymLoop = refl
  750. -- And going around the trivial loop (\i -> base) goes around the the
  751. -- non-trivial loop (\i -> loop) zero times.
  752. windingBase : Path (winding (\i -> base)) (pos zero)
  753. windingBase = refl
  754. goAround : Int -> Path base base
  755. goAround =
  756. \case
  757. pos n ->
  758. let
  759. forwards : Nat -> Path base base
  760. forwards = \case
  761. zero -> refl
  762. succ n -> trans (goAround (pos n)) (\i -> loop i)
  763. in forwards n
  764. neg n ->
  765. let
  766. backwards : Nat -> Path base base
  767. backwards = \case
  768. zero -> \i -> loop (inot i)
  769. succ n -> trans (goAround (neg n)) (\i -> loop (inot i))
  770. in backwards n
  771. windingGoAround : (n : Int) -> Path (winding (goAround n)) n
  772. windingGoAround =
  773. \case
  774. pos n -> posCase n
  775. neg n -> negCase n
  776. where
  777. posCase : (n : Nat) -> Path (winding (goAround (pos n))) (pos n)
  778. posCase = \case
  779. zero -> refl
  780. succ n -> ap sucZ (posCase n)
  781. negCase : (n : Nat) -> Path (winding (goAround (neg n))) (neg n)
  782. negCase = \case
  783. zero -> refl
  784. succ n -> ap predZ (negCase n)
  785. decode : (x : S1) -> helix x -> Path base x
  786. decode = go decodeSquare where
  787. decodeSquare : (n : Int) -> PathP (\i -> Path base (loop i)) (goAround (predZ n)) (goAround n)
  788. decodeSquare =
  789. \case
  790. pos n -> posCase n
  791. neg n -> \i j -> hfill (\k [ (j = i1) -> loop (inot k), (j = i0) -> base ]) (inS (goAround (neg n) j)) (inot i)
  792. where
  793. posCase : (n : Nat) -> PathP (\i -> Path base (loop i)) (goAround (predZ (pos n))) (goAround (pos n))
  794. posCase = \case
  795. zero -> \i j -> loop (ior i (inot j))
  796. succ n -> \i j -> hfill (\k [ (j = i1) -> loop k, (j = i0) -> base ]) (inS (goAround (pos n) j)) i
  797. go : ((n : Int) -> PathP (\i -> Path base (loop i)) (goAround (predZ n)) (goAround n))
  798. -> (x : S1) -> helix x -> Path base x
  799. go decodeSquare = \case
  800. base -> goAround
  801. loop i -> \y j ->
  802. let n : Int
  803. n = primUnglue {Int} {ior i (inot i)} {\o -> Int} {\[ (i = i1) -> idEquiv, (i = i0) -> sucEquiv ]} y
  804. in hcomp (\k [ (i = i0) -> goAround (predSucZ y k) j
  805. , (i = i1) -> goAround y j
  806. , (j = i0) -> base
  807. , (j = i1) -> loop i ])
  808. (inS (decodeSquare n i j))
  809. decodeWinding : (x : S1) (p : Path base x) -> Path (decode x (encode x p)) p
  810. decodeWinding x p = J (\y q -> Path (decode y (encode y q)) q) (\ i -> refl) p
  811. loopS1IsoInt : Iso (Path base base) Int
  812. loopS1IsoInt = (winding, goAround, windingGoAround, decodeWinding base)
  813. LoopS1IsInt : Path (Path base base) Int
  814. LoopS1IsInt = IsoToId loopS1IsoInt
  815. -- One particularly general higher inductive type is the homotopy pushout,
  816. -- which can be seen as a kind of sum B + C with the extra condition that
  817. -- whenever x and y are in the image of f (resp. g), inl x ≡ inr y.
  818. data Pushout {A : Type} {B : Type} {C : Type} (f : A -> B) (g : A -> C) : Type where
  819. inl : (x : B) -> Pushout f g
  820. inr : (y : C) -> Pushout f g
  821. push i : (a : A) -> Pushout f g [ (i = i0) -> inl (f a), (i = i1) -> inr (g a) ]
  822. Coproduct : Type -> Type -> Type
  823. Coproduct A B = Pushout {Bottom} {A} {B} absurd absurd
  824. Pushout_rec : {A : Type} {B : Type} {C : Type} {f : A -> B} {g : A -> C}
  825. -> (P : Pushout f g -> Type)
  826. -> (fc : (x : B) -> P (inl x))
  827. -> (gc : (x : C) -> P (inr x))
  828. -> ((a : A) -> PathP (\i -> P (push a i)) (fc (f a)) (gc (g a)))
  829. -> (c : Pushout f g) -> P c
  830. Pushout_rec P fc gc pc = \case
  831. inl x -> fc x
  832. inr y -> gc y
  833. push c i -> pc c i
  834. data Susp (A : Type) : Type where
  835. north : Susp A
  836. south : Susp A
  837. merid i : A -> Susp A [ (i = i0) -> north, (i = i1) -> south ]
  838. data Unit : Type where
  839. tt : Unit
  840. unitEta : (x : Unit) -> Path x tt
  841. unitEta = \case tt -> refl
  842. unitContr : isContr Unit
  843. unitContr = (tt, \x -> sym (unitEta x))
  844. unitProp : isProp Unit
  845. unitProp = \case
  846. tt -> \case
  847. tt -> refl
  848. poSusp : Type -> Type
  849. poSusp A = Pushout {A} {Unit} {Unit} (\x -> tt) (\x -> tt)
  850. Susp_is_poSusp : {A : Type} -> Path (Susp A) (poSusp A)
  851. Susp_is_poSusp = ua (IsoToEquiv (Susp_to_poSusp {A}, poSusp_to_Susp {A}, poSusp_to_Susp_to_poSusp {A}, Susp_to_poSusp_to_Susp {A})) where
  852. poSusp_to_Susp : {A : Type} -> poSusp A -> Susp A
  853. poSusp_to_Susp = \case
  854. inl x -> north
  855. inr x -> south
  856. push x i -> merid x i
  857. Susp_to_poSusp : {A : Type} -> Susp A -> poSusp A
  858. Susp_to_poSusp = \case
  859. north -> inl tt
  860. south -> inr tt
  861. merid x i -> push x i
  862. Susp_to_poSusp_to_Susp : {A : Type} -> (x : Susp A) -> Path (poSusp_to_Susp (Susp_to_poSusp x)) x
  863. Susp_to_poSusp_to_Susp = \case
  864. north -> refl
  865. south -> refl
  866. merid x i -> refl
  867. poSusp_to_Susp_to_poSusp : {A : Type} -> (x : poSusp A) -> Path (Susp_to_poSusp (poSusp_to_Susp x)) x
  868. poSusp_to_Susp_to_poSusp {A} = \case
  869. inl x -> ap inl (sym (unitEta x))
  870. inr x -> ap inr (sym (unitEta x))
  871. push x i -> refl
  872. data T2 : Type where
  873. baseT : T2
  874. pathOne i : T2 [ (i = i0) -> baseT, (i = i1) -> baseT ]
  875. pathTwo i : T2 [ (i = i0) -> baseT, (i = i1) -> baseT ]
  876. square i j : T2 [
  877. (j = i0) -> pathTwo i,
  878. (j = i1) -> pathTwo i,
  879. (i = i0) -> pathOne j,
  880. (i = i1) -> pathOne j
  881. ]
  882. TorusIsTwoCircles : Equiv T2 (S1 * S1)
  883. TorusIsTwoCircles = IsoToEquiv theIso where
  884. torusToCircs : T2 -> S1 * S1
  885. torusToCircs = \case
  886. baseT -> (base, base)
  887. pathOne i -> (loop i, base)
  888. pathTwo i -> (base, loop i)
  889. square i j -> (loop i, loop j)
  890. circsToTorus : (S1 * S1) -> T2
  891. circsToTorus pair = go pair.1 pair.2
  892. where
  893. baseCase : S1 -> T2
  894. baseCase = \case
  895. base -> baseT
  896. loop j -> pathTwo j
  897. loopCase : Path baseCase baseCase
  898. loopCase i = \case
  899. base -> pathOne i
  900. loop j -> square i j
  901. go : S1 -> S1 -> T2
  902. go = \case
  903. base -> baseCase
  904. loop i -> loopCase i
  905. torusToCircsToTorus : (x : T2) -> Path (circsToTorus (torusToCircs x)) x
  906. torusToCircsToTorus = \case
  907. baseT -> refl
  908. pathOne i -> refl
  909. pathTwo i -> refl
  910. square i j -> refl
  911. circsToTorusToCircs : (p : S1 * S1) -> Path (torusToCircs (circsToTorus p)) p
  912. circsToTorusToCircs pair = go pair.1 pair.2 where
  913. baseCase : (y : S1) -> Path (torusToCircs (circsToTorus (base, y))) (base, y)
  914. baseCase = \case
  915. base -> refl
  916. loop j -> refl
  917. loopCase : (i : I) (y : S1) -> Path (torusToCircs (circsToTorus (loop i, y))) (loop i, y )
  918. loopCase i = \case
  919. base -> refl
  920. loop j -> refl
  921. go : (x : S1) (y : S1) -> Path (torusToCircs (circsToTorus (x, y))) (x, y)
  922. go = \case
  923. base -> baseCase
  924. loop i -> loopCase i
  925. theIso : Iso T2 (S1 * S1)
  926. theIso = (torusToCircs, circsToTorus, circsToTorusToCircs, torusToCircsToTorus)
  927. abs : Int -> Nat
  928. abs = \case
  929. pos n -> n
  930. neg n -> succ n
  931. sign : Int -> Bool
  932. sign = \case
  933. pos n -> true
  934. neg n -> false
  935. boolAnd : Bool -> Bool -> Bool
  936. boolAnd = \case
  937. true -> \case
  938. true -> true
  939. false -> false
  940. false -> \case
  941. true -> false
  942. false -> false
  943. boolXor : Bool -> Bool -> Bool
  944. boolXor = \case
  945. true -> \case
  946. true -> false
  947. false -> true
  948. false -> \case
  949. false -> false
  950. true -> true
  951. plusNat : Nat -> Nat -> Nat
  952. plusNat = \case
  953. zero -> \x -> x
  954. succ n -> \x -> succ (plusNat n x)
  955. plusZero : (x : Nat) -> Path (plusNat zero x) x
  956. plusZero = \case
  957. zero -> refl
  958. succ n -> \i -> succ (plusZero n i)
  959. multNat : Nat -> Nat -> Nat
  960. multNat = \case
  961. zero -> \x -> zero
  962. succ n -> \x -> plusNat x (multNat n x)
  963. multInt : Int -> Int -> Int
  964. multInt x y = signify (multNat (abs x) (abs y)) (not (boolXor (sign x) (sign y))) where
  965. signify : Nat -> Bool -> Int
  966. signify = \case
  967. zero -> \x -> pos zero
  968. succ n -> \case
  969. true -> pos (succ n)
  970. false -> neg n
  971. two : Int
  972. two = pos (succ (succ zero))
  973. four : Int
  974. four = multInt two two
  975. sixteen : Int
  976. sixteen = multInt four four
  977. Prop : Type
  978. Prop = (A : Type) * isProp A
  979. data Sq (A : Type) : Type where
  980. inc : A -> Sq A
  981. sq i : (x : Sq A) (y : Sq A) -> Sq A [ (i = i0) -> x, (i = i1) -> y ]
  982. isProp_isSet : {A : Type} -> isProp A -> isSet A
  983. isProp_isSet h a b p q j i =
  984. hcomp {A}
  985. (\k [ (i = i0) -> h a a k
  986. , (i = i1) -> h a b k
  987. , (j = i0) -> h a (p i) k
  988. , (j = i1) -> h a (q i) k
  989. ])
  990. (inS a)
  991. unitSet : isSet Unit
  992. unitSet = isProp_isSet unitProp
  993. isProp_isProp : {A : Type} -> isProp (isProp A)
  994. isProp_isProp f g i a b = isProp_isSet f a b (f a b) (g a b) i
  995. isSet_isProp : {A : Type} -> isProp (isSet A)
  996. isSet_isProp f g i x y = isProp_isProp {_} (f x y) (g x y) i
  997. isProp_isContr : {A : Type} -> isProp (isContr A)
  998. isProp_isContr {A} z0 z1 j =
  999. ( z0.2 z1.1 j
  1000. , \x i -> hcomp (\k [ (i = i0) -> z0.2 z1.1 j
  1001. , (i = i1) -> z0.2 x (ior j k)
  1002. , (j = i0) -> z0.2 x (iand i k)
  1003. , (j = i1) -> z1.2 x i ])
  1004. (inS (z0.2 (z1.2 x i) j))
  1005. )
  1006. isContr_isProp : {A : Type} -> isContr A -> isProp A
  1007. isContr_isProp x a b i = hcomp (\k [ (i = i0) -> x.2 a k, (i = i1) -> x.2 b k ]) (inS x.1)
  1008. isSet_prod : {A : Type} {B : Type} -> isSet A -> isSet B -> isSet (A * B)
  1009. isSet_prod a b x y p q i j = (a x.1 y.1 (\i -> (p i).1) (\i -> (q i).1) i j, b x.2 y.2 (\i -> (p i).2) (\i -> (q i).2) i j)
  1010. isSet_pi : {A : Type} {B : A -> Type} -> ((x : A) -> isSet (B x)) -> isSet ((x : A) -> B x)
  1011. isSet_pi rng a b p q i j z = rng z (a z) (b z) (happly p z) (happly q z) i j
  1012. sigmaPath : {A : Type} {B : A -> Type} {s1 : (x : A) * B x} {s2 : (x : A) * B x}
  1013. -> (p : Path s1.1 s2.1)
  1014. -> PathP (\i -> B (p i)) s1.2 s2.2
  1015. -> Path s1 s2
  1016. sigmaPath p q i = (p i, q i)
  1017. propExt : {A : Type} {B : Type}
  1018. -> isProp A -> isProp B
  1019. -> (A -> B)
  1020. -> (B -> A)
  1021. -> Equiv A B
  1022. propExt {A} {B} propA propB f g = (f, contract) where
  1023. contract : (y : B) -> isContr (fiber f y)
  1024. contract y =
  1025. let arg : A
  1026. arg = g y
  1027. in ( (arg, propB y (f arg))
  1028. , \fib -> sigmaPath (propA _ _) (isProp_isSet propB y (f fib.1) _ _))
  1029. Sq_rec : {A : Type} {B : Type}
  1030. -> isProp B
  1031. -> (f : A -> B)
  1032. -> Sq A -> B
  1033. Sq_rec prop f =
  1034. \case
  1035. inc x -> f x
  1036. sq x y i -> prop (work x) (work y) i
  1037. where
  1038. work : Sq A -> B
  1039. work = \case
  1040. inc x -> f x
  1041. Sq_prop : {A : Type} -> isProp (Sq A)
  1042. Sq_prop x y i = sq x y i
  1043. hitTranspExample : Path (inc false) (inc true)
  1044. hitTranspExample i = transp (\i -> Sq (notp i)) (sq (inc true) (inc false) i)
  1045. data S2 : Type where
  1046. base2 : S2
  1047. surf2 i j : S2 [ (i = i0) -> base2, (i = i1) -> base2, (j = i0) -> base2, (j = i1) -> base2]
  1048. S2IsSuspS1 : Path S2 (Susp S1)
  1049. S2IsSuspS1 = ua (IsoToEquiv iso) where
  1050. toS2 : Susp S1 -> S2
  1051. toS2 = \case { north -> base2; south -> base2; merid x i -> sphMerid x i } where
  1052. sphMerid = \case
  1053. base -> \i -> base2
  1054. loop j -> \i -> surf2 i j
  1055. suspSurf : I -> I -> I -> Susp S1
  1056. suspSurf i j = hfill (\k [ (i = i0) -> north {S1}
  1057. , (i = i1) -> merid {S1} base (inot k)
  1058. , (j = i0) -> merid {S1} base (iand (inot k) i)
  1059. , (j = i1) -> merid {S1} base (iand (inot k) i)
  1060. ])
  1061. (inS (merid (loop j) i))
  1062. fromS2 : S2 -> Susp S1
  1063. fromS2 = \case { base2 -> north; surf2 i j -> suspSurf i j i1 }
  1064. toFromS2 : (x : S2) -> Path (toS2 (fromS2 x)) x
  1065. toFromS2 = \case { base2 -> refl; surf2 i j -> \k -> toS2 (suspSurf i j (inot k)) }
  1066. fromToS2 : (x : Susp S1) -> Path (fromS2 (toS2 x)) x
  1067. fromToS2 = \case { north -> refl; south -> \i -> merid base i; merid x i -> meridCase i x } where
  1068. meridCase : (i : I) (x : S1) -> Path (fromS2 (toS2 (merid x i))) (merid x i)
  1069. meridCase i = \case
  1070. base -> \k -> merid base (iand i k)
  1071. loop j -> \k -> suspSurf i j (inot k)
  1072. iso : Iso S2 (Susp S1)
  1073. iso = (fromS2, toS2, fromToS2, toFromS2)
  1074. data S3 : Type where
  1075. base3 : S3
  1076. surf3 i j k : S3 [ (i = i0) -> base3, (i = i1) -> base3, (j = i0) -> base3, (j = i1) -> base3, (k = i0) -> base3, (k = i1) -> base3 ]
  1077. S3IsSuspS2 : Path S3 (Susp S2)
  1078. S3IsSuspS2 = ua (IsoToEquiv iso) where
  1079. toS3 : Susp S2 -> S3
  1080. toS3 = \case { north -> base3; south -> base3; merid x i -> sphMerid x i } where
  1081. sphMerid = \case
  1082. base2 -> \i -> base3
  1083. surf2 j k -> \i -> surf3 i j k
  1084. suspSurf : I -> I -> I -> I -> Susp S2
  1085. suspSurf i j k = hfill (\l [ (i = i0) -> north {S2}
  1086. , (i = i1) -> merid {S2} base2 (inot l)
  1087. , (j = i0) -> merid {S2} base2 (iand (inot l) i)
  1088. , (j = i1) -> merid {S2} base2 (iand (inot l) i)
  1089. , (k = i0) -> merid {S2} base2 (iand (inot l) i)
  1090. , (k = i1) -> merid {S2} base2 (iand (inot l) i)
  1091. ])
  1092. (inS (merid (surf2 j k) i))
  1093. fromS3 : S3 -> Susp S2
  1094. fromS3 = \case { base3 -> north; surf3 i j k -> suspSurf i j k i1 }
  1095. toFromS3 : (x : S3) -> Path (toS3 (fromS3 x)) x
  1096. toFromS3 = \case { base3 -> refl; surf3 i j k -> \l -> toS3 (suspSurf i j k (inot l)) }
  1097. fromToS3 : (x : Susp S2) -> Path (fromS3 (toS3 x)) x
  1098. fromToS3 = \case { north -> refl; south -> \i -> merid base2 i; merid x i -> meridCase i x } where
  1099. meridCase : (i : I) (x : S2) -> Path (fromS3 (toS3 (merid x i))) (merid x i)
  1100. meridCase i = \case
  1101. base2 -> \k -> merid base2 (iand i k)
  1102. surf2 j k -> \l -> suspSurf i j k (inot l)
  1103. iso : Iso S3 (Susp S2)
  1104. iso = (fromS3, toS3, fromToS3, toFromS3)
  1105. ap_s : {A : Pretype} {B : Pretype} (f : A -> B) {x : A} {y : A} -> Eq_s x y -> Eq_s (f x) (f y)
  1106. ap_s f {x} = J_s (\y p -> Eq_s (f x) (f y)) refl_s
  1107. subst_s : {A : Pretype} (P : A -> Pretype) {x : A} {y : A} -> Eq_s x y -> P x -> P y
  1108. subst_s {A} P {x} p px = J_s (\y p -> P x -> P y) id p px
  1109. sym_s : {A : Pretype} {x : A} {y : A} -> Eq_s x y -> Eq_s y x
  1110. sym_s = J_s (\y p -> Eq_s y x) refl_s
  1111. UIP : {A : Pretype} {x : A} {y : A} (p : Eq_s x y) (q : Eq_s x y) -> Eq_s p q
  1112. UIP p q = J_s (\y p -> (q : Eq_s x y) -> Eq_s p q) (uipRefl A x) p q where
  1113. uipRefl : (A : Pretype) (x : A) (p : Eq_s x x) -> Eq_s refl_s p
  1114. uipRefl A x p = K_s (\q -> Eq_s refl_s q) refl_s p
  1115. strictEq_pathEq : {A : Type} {x : A} {y : A} -> Eq_s x y -> Path x y
  1116. strictEq_pathEq eq = J_s {A} {x} (\y p -> Path x y) (\i -> x) {y} eq
  1117. seq_pathRefl : {A : Type} {x : A} (p : Eq_s x x) -> Eq_s (strictEq_pathEq p) (refl {A} {x})
  1118. seq_pathRefl p = K_s (\p -> Eq_s (strictEq_pathEq {A} {x} {x} p) (refl {A} {x})) refl_s p
  1119. Path_nat_strict_nat : (x : Nat) (y : Nat) -> Path x y -> Eq_s x y
  1120. Path_nat_strict_nat = \case { zero -> zeroCase; succ x -> succCase x } where
  1121. zeroCase : (y : Nat) -> Path zero y -> Eq_s zero y
  1122. zeroCase = \case
  1123. zero -> \p -> refl_s
  1124. succ x -> \p -> absurd (zeroNotSucc p)
  1125. succCase : (x : Nat) (y : Nat) -> Path (succ x) y -> Eq_s (succ x) y
  1126. succCase x = \case
  1127. zero -> \p -> absurd (zeroNotSucc (sym p))
  1128. succ y -> \p -> ap_s succ (Path_nat_strict_nat x y (succInj p))
  1129. pathToEqS_K : {A : Type} {x : A}
  1130. -> (s : {x : A} {y : A} -> Path x y -> Eq_s x y)
  1131. -> (P : Path x x -> Type) -> P refl -> (p : Path x x) -> P p
  1132. pathToEqS_K p_to_s P pr loop = transp (\i -> P (inv x loop i)) psloop where
  1133. psloop : P (strictEq_pathEq (p_to_s loop))
  1134. psloop = K_s (\l -> P (strictEq_pathEq {A} {x} {x} l)) pr (p_to_s {x} {x} loop)
  1135. inv : (y : A) (l : Path x y) -> Path (strictEq_pathEq (p_to_s l)) l
  1136. inv y l = J {A} {x} (\y l -> Path (strictEq_pathEq (p_to_s l)) l) (strictEq_pathEq aux) {y} l where
  1137. aux : Eq_s (strictEq_pathEq (p_to_s (\i -> x))) (\i -> x)
  1138. aux = seq_pathRefl (p_to_s (\i -> x))
  1139. axK_to_isSet : {A : Type} -> ({x : A} -> (P : Path x x -> Type) -> P refl -> (p : Path x x) -> P p) -> isSet A
  1140. axK_to_isSet K x y p q = J (\y p -> (q : Path x y) -> Path p q) (uipRefl x) p q where
  1141. uipRefl : (x : A) (p : Path x x) -> Path refl p
  1142. uipRefl x p = K {x} (\q -> Path refl q) refl p
  1143. pathToEq_isSet : {A : Type} -> ({x : A} {y : A} -> Path x y -> Eq_s x y) -> isSet A
  1144. pathToEq_isSet p_to_s = axK_to_isSet {A} (\{x} -> pathToEqS_K {A} {x} p_to_s)
  1145. Nat_isSet : isSet Nat
  1146. Nat_isSet = pathToEq_isSet {Nat} (\{x} {y} -> Path_nat_strict_nat x y)
  1147. Bool_isSet : isSet Bool
  1148. Bool_isSet = pathToEq_isSet {Bool} (\{x} {y} -> p x y) where
  1149. p : (x : Bool) (y : Bool) -> Path x y -> Eq_s x y
  1150. p = \case
  1151. true -> \case
  1152. true -> \p -> refl_s
  1153. false -> \p -> absurd (trueNotFalse p)
  1154. false -> \case
  1155. false -> \p -> refl_s
  1156. true -> \p -> absurd (trueNotFalse (sym p))
  1157. equivCtr : {A : Type} {B : Type} (e : Equiv A B) (y : B) -> fiber e.1 y
  1158. equivCtr e y = (e.2 y).1
  1159. equivCtrPath : {A : Type} {B : Type} (e : Equiv A B) (y : B)
  1160. -> (v : fiber e.1 y) -> Path (equivCtr e y) v
  1161. equivCtrPath e y = (e.2 y).2
  1162. contr : {A : Type} {phi : I} -> isContr A -> (u : Partial phi A) -> Sub A phi u
  1163. contr p u = primComp (\i -> A) (\i [ (phi = i1) -> p.2 (u itIs1) i ]) (inS p.1)
  1164. contr' : {A : Type} -> ({phi : I} -> (u : Partial phi A) -> Sub A phi u) -> isContr A
  1165. contr' contr = (x, \y i -> outS (contr (\ [ (i = i0) -> x, (i = i1) -> y ])) ) where
  1166. x : A
  1167. x = outS (contr (\ []))
  1168. leftIsOne : {a : I} {b : I} -> Eq_s a i1 -> Eq_s (ior a b) i1
  1169. leftIsOne p = J_s {I} {i1} (\i p -> IsOne (ior i b)) refl_s (sym_s p)
  1170. rightIsOne : {a : I} {b : I} -> Eq_s b i1 -> Eq_s (ior a b) i1
  1171. rightIsOne p = J_s {I} {i1} (\i p -> IsOne (ior a i)) refl_s (sym_s p)
  1172. bothAreOne : {a : I} {b : I} -> Eq_s a i1 -> Eq_s b i1 -> Eq_s (iand a b) i1
  1173. bothAreOne p q = J_s {I} {i1} (\i p -> IsOne (iand i b)) q (sym_s p)
  1174. S1Map_to_baseLoop : {X : Type} -> (S1 -> X) -> (a : X) * Path a a
  1175. S1Map_to_baseLoop f = (f base, \i -> f (loop i))
  1176. S1_univ : {X : Type} -> Path (S1 -> X) ((a : X) * Path a a)
  1177. S1_univ = IsoToId {S1 -> X} {(a : X) * Path a a} (S1Map_to_baseLoop {X}, fro, ret, sec) where
  1178. to = S1Map_to_baseLoop
  1179. fro : {X : Type} -> ((a : X) * Path a a) -> S1 -> X
  1180. fro p = \case
  1181. base -> p.1
  1182. loop i -> p.2 i
  1183. sec : (f : S1 -> X) -> Path (fro (to f)) f
  1184. sec f = funext {S1} {\s -> X} {\x -> fro (to f) x} {f} h where
  1185. h : (x : S1) -> Path (fro (to f) x) (f x)
  1186. h = \case
  1187. base -> refl
  1188. loop i -> refl
  1189. ret : {X : Type} -> (x : (a : X) * Path a a) -> Path (to (fro x)) x
  1190. ret x = refl
  1191. -- HoTT book lemma 8.9.1
  1192. encodeDecode : {A : Type} {a0 : A}
  1193. -> (code : A -> Type)
  1194. -> (c0 : code a0)
  1195. -> (decode : (x : A) -> code x -> (Path a0 x))
  1196. -> ((c : code a0) -> Path (transp (\i -> code (decode a0 c i)) c0) c)
  1197. -> Path (decode a0 c0) refl
  1198. -> Path (Path a0 a0) (code a0)
  1199. encodeDecode code c0 decode encDec based = IsoToId (encode {a0}, decode _, encDec, decEnc) where
  1200. encode : {x : A} -> Path a0 x -> code x
  1201. encode alpha = transp (\i -> code (alpha i)) c0
  1202. encodeRefl : Path (encode refl) c0
  1203. encodeRefl = sym (transpFill (\i -> code a0) c0)
  1204. decEnc : {x : A} (p : Path a0 x) -> Path (decode _ (encode p)) p
  1205. decEnc p = J (\x p -> Path (decode _ (encode p)) p) q p where
  1206. q : Path (decode _ (encode refl)) refl
  1207. q = transp (\i -> Path (decode _ (encodeRefl (inot i))) refl) based
  1208. S1_elim : (P : S1 -> Type)
  1209. -> (pb : P base)
  1210. -> PathP (\i -> P (loop i)) pb pb
  1211. -> (x : S1) -> P x
  1212. S1_elim P pb pq = \case
  1213. base -> pb
  1214. loop i -> pq i
  1215. PathP_is_Path : (P : I -> Type) (p : P i0) (q : P i1) -> Path (PathP P p q) (Path {P i1} (transp (\i -> P i) p) q)
  1216. PathP_is_Path P p q i = PathP (\j -> P (ior i j)) (transpFill (\j -> P j) p i) q
  1217. Constant : {A : Type} {B : Type} -> (A -> B) -> Type
  1218. Constant f = (y : B) * (x : A) -> Path y (f x)
  1219. Weakly : {A : Type} {B : Type} -> (A -> B) -> Type
  1220. Weakly f = (x : A) (y : A) -> Path (f x) (f y)
  1221. Conditionally : {A : Type} {B : Type} -> (A -> B) -> Type
  1222. Conditionally f = (f' : Sq A -> B) * Path f (\x -> f' (inc x))
  1223. Constant_weakly : {A : Type} {B : Type} (f : A -> B) -> Constant f -> Weakly f
  1224. Constant_weakly f p x y = trans (sym (p.2 x)) (p.2 y)
  1225. Constant_conditionally : {A : Type} {B : Type} -> (f : A -> B) -> Constant f -> Conditionally f
  1226. Constant_conditionally f p = transp (\i -> Conditionally (c_const (inot i))) (const_c p.1) where
  1227. c_const : Path f (\y -> p.1)
  1228. c_const i x = p.2 x (inot i)
  1229. const_c : (y : B) -> Conditionally {A} (\x -> y)
  1230. const_c y = (\x -> y, refl)
  1231. S1_connected : (f : S1 -> Bool) -> Constant f
  1232. S1_connected f = (f'.1, p) where
  1233. f' : (x : Bool) * Path x x
  1234. f' = S1Map_to_baseLoop f
  1235. p : (y : S1) -> Path f'.1 (f y)
  1236. p = S1_elim P refl loopc where
  1237. P : S1 -> Type
  1238. P = \y -> Path f'.1 (f y)
  1239. rr = refl {Bool} {f base}
  1240. loopc : PathP (\i -> P (loop i)) rr rr
  1241. loopc = transp (\i -> PathP_is_Path (\i -> P (loop i)) rr rr (inot i))
  1242. (Bool_isSet _ _ rr (transp (\i -> P (loop i)) rr))
  1243. isProp_isEquiv : {A : Type} {B : Type} {f : A -> B} -> isProp (isEquiv f)
  1244. isProp_isEquiv p q i y =
  1245. let
  1246. p2 = (p y).2
  1247. q2 = (q y).2
  1248. in
  1249. ( p2 (q y).1 i
  1250. , \w j -> hcomp (\k [ (i = i0) -> p2 w j
  1251. , (i = i1) -> q2 w (ior j (inot k))
  1252. , (j = i0) -> p2 (q2 w (inot k)) i
  1253. , (j = i1) -> w ])
  1254. (inS (p2 w (ior i j)))
  1255. )
  1256. -- isProp_EqvSq : {P : Type} (x : Equiv P (Sq P)) (y : Equiv P (Sq P)) -> Path x y
  1257. -- isProp_EqvSq x y = sigmaPath x1_is_y1 (isProp_isEquiv {P} {Sq P} {y.1} (transp (\i -> isEquiv (x1_is_y1 i)) x.2) y.2) where
  1258. -- x1_is_y1 : Path x.1 y.1
  1259. -- x1_is_y1 i e = sq (x.1 e) (y.1 e) i
  1260. equivLemma : {A : Type} {B : Type} {e : Equiv A B} {e' : Equiv A B}
  1261. -> Path e.1 e'.1
  1262. -> Path e e'
  1263. equivLemma p = sigmaPath {A -> B} {\f -> isEquiv f} p (transp (\i -> PathP_is_Path (\i -> isEquiv (p i)) e.2 e'.2 (inot i)) (isProp_isEquiv {A} {B} {e'.1} _ _))
  1264. isProp_equiv : {P : Type} {Q : Type} -> Equiv P Q -> isProp P -> isProp Q
  1265. isProp_equiv eqv = transp (\i -> isProp (ua eqv i))
  1266. -- isProp_to_Sq_equiv : {P : Type} -> isProp P -> Equiv P (Sq P)
  1267. -- isProp_to_Sq_equiv prop = propExt prop sqProp inc proj where
  1268. -- proj : Sq P -> P
  1269. -- proj = Sq_rec prop (\x -> x)
  1270. -- sqProp : isProp (Sq P)
  1271. -- sqProp x y i = sq x y i
  1272. -- Sq_equiv_to_isProp : {P : Type} -> Equiv P (Sq P) -> isProp P
  1273. -- Sq_equiv_to_isProp eqv = transp (\i -> isProp (ua eqv (inot i))) (\x y i -> sq x y i)
  1274. -- exercise_3_21 : {P : Type} -> Equiv (isProp P) (Equiv P (Sq P))
  1275. -- exercise_3_21 = propExt (isProp_isProp {P}) (isProp_EqvSq {P}) isProp_to_Sq_equiv Sq_equiv_to_isProp
  1276. uaret : {A : Type} {B : Type} -> retract {Equiv A B} {Path A B} (ua {A} {B}) (idToEquiv {A} {B})
  1277. uaret eqv = equivLemma (uaBeta eqv)
  1278. isContrRetract : {A : Type} {B : Type}
  1279. -> (f : A -> B) -> (g : B -> A)
  1280. -> (h : retract f g)
  1281. -> isContr B -> isContr A
  1282. isContrRetract f g h v = (g b, p) where
  1283. b = v.1
  1284. p : (x : A) -> Path (g b) x
  1285. p x i = comp (\i -> A) (\j [ (i = i0) -> g b, (i = i1) -> h x j ]) (inS (g (v.2 (f x) i)))
  1286. contrEquivSingl : {A : Type} -> isContr ((B : Type) * Equiv A B)
  1287. contrEquivSingl = isContrRetract (f1 ua idToEquiv) (f2 ua idToEquiv) (uaretSig ua idToEquiv (uaret {A})) singContr where
  1288. f1 : (ua : {B : Type} -> Equiv A B -> Path A B)
  1289. (idToEquiv : {B : Type} -> Path A B -> Equiv A B)
  1290. (p : (B : Type) * Equiv A B)
  1291. -> (B : Type) * Path A B
  1292. f1 ua idtoequiv p = (p.1, ua p.2)
  1293. f2 : (ua : {B : Type} -> Equiv A B -> Path A B)
  1294. (idToEquiv : {B : Type} -> Path A B -> Equiv A B)
  1295. (p : (B : Type) * Path A B)
  1296. -> (B : Type) * Equiv A B
  1297. f2 ua idtoequiv p = (p.1, idToEquiv p.2)
  1298. uaretSig : (ua : {B : Type} -> Equiv A B -> Path A B)
  1299. (idtoequiv : {B : Type} -> Path A B -> Equiv A B)
  1300. (uaret : {B : Type} (e : Equiv A B) -> Path (idToEquiv (ua e)) e)
  1301. -> (a : (B : Type) * Equiv A B) -> Path (f2 ua idtoequiv (f1 ua idtoequiv a)) a
  1302. uaretSig ua idtoequiv ret p i = (p.1, ret {p.1} p.2 i)
  1303. curry : {A : Type} {B : A -> Type} {C : (x : A) -> B x -> Type}
  1304. -> Path ((x : A) (y : B x) -> C x y) ((p : (x : A) * B x) -> C p.1 p.2)
  1305. curry = IsoToId (to, from, \f -> refl, \g -> refl) where
  1306. to : ((x : A) (y : B x) -> C x y) -> (p : (x : A) * B x) -> C p.1 p.2
  1307. to f p = f p.1 p.2
  1308. from : ((p : (x : A) * B x) -> C p.1 p.2) -> (x : A) (y : B x) -> C x y
  1309. from f x y = f (x, y)
  1310. contrToProp : {A : Type} -> (A -> isContr A) -> isProp A
  1311. contrToProp cont x y = trans (sym (p.2 x)) (p.2 y) where
  1312. p = cont x
  1313. ContractibleIfInhabited : {A : Type} -> isEquiv contrToProp
  1314. ContractibleIfInhabited = (IsoToEquiv (contrToProp, from, toFrom, fromTo)).2 where
  1315. from : isProp A -> A -> isContr A
  1316. from prop x = (x, prop x)
  1317. toFrom : (y : isProp A) -> Path (contrToProp (from y)) y
  1318. toFrom y = isProp_isProp {A} (contrToProp (from y)) y
  1319. fromTo : (y : A -> isContr A) -> Path (from (contrToProp y)) y
  1320. fromTo y i a = isProp_isContr {A} (from (contrToProp y) a) (y a) i
  1321. contrSinglEquiv : {B : Type} -> isContr ((A : Type) * Equiv A B)
  1322. contrSinglEquiv = (center, contract) where
  1323. center : (A : Type) * Equiv A B
  1324. center = (B, idEquiv)
  1325. contract : (p : (A : Type) * Equiv A B) -> Path center p
  1326. contract w i =
  1327. let
  1328. sys : Partial (ior (inot i) i) ((A : Type) * Equiv A B)
  1329. sys = \ [ (i = i0) -> center, (i = i1) -> w ]
  1330. GlueB = Glue B sys
  1331. unglueB : GlueB -> B
  1332. unglueB x = unglue {B} (ior (inot i) i) {sys} x
  1333. unglueEquiv : isEquiv {GlueB} {B} unglueB
  1334. unglueEquiv b =
  1335. let
  1336. ctr : fiber unglueB b
  1337. ctr = ( glue {B} {ior (inot i) i} {sys} (\[ (i = i0) -> b, (i = i1) -> (w.2.2 b).1.1 ])
  1338. (primComp (\i -> B) (\j [ (i = i0) -> b, (i = i1) -> (w.2.2 b).1.2 j ]) (inS b))
  1339. , fill (\i -> B) (\j [ (i = i0) -> b, (i = i1) -> (w.2.2 b).1.2 j ]) (inS b))
  1340. contr : (v : fiber unglueB b) -> Path ctr v
  1341. contr v j = ( glue {B} {ior (inot i) i} {sys}
  1342. (\[ (i = i0) -> v.2 j, (i = i1) -> ((w.2.2 b).2 v j).1 ])
  1343. (inS (hcomp (\k [ (i = i0) -> v.2 (iand j k)
  1344. , (i = i1) -> ((w.2.2 b).2 v j).2 k
  1345. , (j = i0) -> fill (\j -> B)
  1346. {ior i (inot i)}
  1347. (\k [ (i = i0) -> b
  1348. , (i = i1) -> (w.2.2 b).1.2 k ])
  1349. (inS {B} {ior i (inot i)} b) k
  1350. , (j = i1) -> v.2 k
  1351. ])
  1352. (inS b)))
  1353. , hfill (\k [ (i = i0) -> v.2 (iand j k)
  1354. , (i = i1) -> ((w.2.2 b).2 v j).2 k
  1355. , (j = i0) -> fill (\j -> B)
  1356. {ior i (inot i)}
  1357. (\k [ (i = i0) -> b
  1358. , (i = i1) -> (w.2.2 b).1.2 k ])
  1359. (inS {B} {ior i (inot i)} b) k
  1360. , (j = i1) -> v.2 k
  1361. ])
  1362. (inS b)
  1363. )
  1364. in (ctr, contr)
  1365. in (GlueB, unglueB, unglueEquiv)
  1366. uaIdEquiv : {A : Type} -> Path (ua idEquiv) (\i -> A)
  1367. uaIdEquiv i j = Glue A {ior i (ior (inot j) j)} (\o -> (A, idEquiv))
  1368. EquivJ : (P : (X : Type) (Y : Type) -> Equiv X Y -> Type)
  1369. -> ((X : Type) -> P X X idEquiv)
  1370. -> {X : Type} {Y : Type} (E : Equiv X Y)
  1371. -> P X Y E
  1372. EquivJ P p E =
  1373. subst {(X : Type) * Equiv X Y}
  1374. (\x -> P x.1 Y x.2)
  1375. (\i -> isContr_isProp contrSinglEquiv (Y, idEquiv) (X, E) i)
  1376. (p Y)
  1377. EquivJ_domain : {Y : Type} (P : (X : Type) -> Equiv X Y -> Type)
  1378. -> P Y idEquiv
  1379. -> {X : Type} (E : Equiv X Y)
  1380. -> P X E
  1381. EquivJ_domain P p E = subst {(X : Type) * Equiv X Y} (\x -> P x.1 x.2) q p where
  1382. q : Path {(X : Type) * Equiv X Y} (Y, idEquiv) (X, E)
  1383. q = isContr_isProp contrSinglEquiv (Y, idEquiv) (X, E)
  1384. EquivJ_fun : {A : Type} {B : Type} (P : (A : Type) -> (A -> B) -> Type)
  1385. -> P B id -> (e : Equiv A B) -> P A e.1
  1386. EquivJ_fun P r e = EquivJ_domain (\A e -> P A e.1) r e
  1387. EquivJ_range : {X : Type} (P : (Y : Type) -> Equiv X Y -> Type)
  1388. -> P X idEquiv
  1389. -> {Y : Type} (E : Equiv X Y)
  1390. -> P Y E
  1391. EquivJ_range P p E = subst {(Y : Type) * Equiv X Y} (\x -> P x.1 x.2) q p
  1392. where
  1393. q : Path {(Y : Type) * Equiv X Y} (X, idEquiv) (Y, E)
  1394. q = isContr_isProp {(Y : Type) * Equiv X Y} (contrEquivSingl {X}) (X, idEquiv) (Y, E)
  1395. pathToEquiv : {A : Type} {B : Type} -> Path A B -> Equiv A B
  1396. pathToEquiv = J {Type} {A} (\B p -> Equiv A B) idEquiv
  1397. univalence : {A : Type} {B : Type} -> Equiv (Path A B) (Equiv A B)
  1398. univalence = IsoToEquiv (pathToEquiv, ua, pathToEquiv_ua, ua_pathToEquiv) where
  1399. pathToEquiv_refl : {A : Type} -> Path (pathToEquiv (refl {Type} {A})) idEquiv
  1400. pathToEquiv_refl = JRefl (\B p -> Equiv A B) idEquiv
  1401. ua_pathToEquiv : {A : Type} {B : Type} (p : Path A B) -> Path (ua (pathToEquiv p)) p
  1402. ua_pathToEquiv p = J {Type} {A} (\B p -> Path (ua {A} {B} (pathToEquiv {A} {B} p)) p) lemma p where
  1403. lemma : Path (ua (pathToEquiv (\i -> A))) (\i -> A)
  1404. lemma = transp (\i -> Path (ua (pathToEquiv_refl {A} (inot i))) (\i -> A)) uaIdEquiv
  1405. pathToEquiv_ua : {A : Type} {B : Type} (p : Equiv A B) -> Path (pathToEquiv (ua p)) p
  1406. pathToEquiv_ua p = EquivJ (\A B e -> Path (pathToEquiv (ua e)) e) lemma p where
  1407. lemma : (A : Type) -> Path (pathToEquiv (ua idEquiv)) idEquiv
  1408. lemma A = transp (\i -> Path (pathToEquiv (uaIdEquiv {A} (inot i))) idEquiv) pathToEquiv_refl
  1409. IsoJ : {B : Type} -> (Q : {A : Type} -> (A -> B) -> (B -> A) -> Type)
  1410. -> Q id id
  1411. -> {A : Type} (f : A -> B) (g : B -> A)
  1412. -> Path (\x -> g (f x)) id -> Path (\x -> f (g x)) id
  1413. -> Q f g
  1414. IsoJ Q h f g sfg rfg = rem1 f g sfg rfg where
  1415. P : (A : Type) -> (A -> B) -> Type
  1416. P A f = (g : B -> A) -> Path (\x -> g (f x)) id -> Path (\x -> f (g x)) id -> Q f g
  1417. rem : P B id
  1418. rem g sfg rfg = subst (Q id) (\i b -> sfg (inot i) b) h
  1419. rem1 : {A : Type} (f : A -> B) -> P A f
  1420. rem1 f g sfg rfg = EquivJ_fun P rem (IsoToEquiv (f, g, \i x -> rfg x i, \i x -> sfg x i)) g sfg rfg
  1421. total : {A : Type} {P : A -> Type} {Q : A -> Type}
  1422. -> ((x : A) -> P x -> Q x)
  1423. -> ((x : A) * P x) -> ((x : A) * Q x)
  1424. total f p = (p.1, f p.1 p.2)
  1425. total_fibers : {A : Type} {P : A -> Type} {Q : A -> Type}
  1426. -> {xv : (a : A) * Q a}
  1427. -> (f : (el : A) -> P el -> Q el)
  1428. -> Iso (fiber (total f) xv) (fiber (f xv.1) xv.2)
  1429. total_fibers f = (to, fro, toFro {xv}, froTo) where
  1430. to : {xv : (a : A) * Q a} -> fiber (total f) xv -> fiber (f xv.1) xv.2
  1431. to peq = J {(a : A) * Q a} (\xv eq -> fiber (f xv.1) xv.2) (peq.1.2, refl) (sym peq.2)
  1432. fro : {xv : (a : A) * Q a} -> fiber (f xv.1) xv.2 -> fiber (total f) xv
  1433. fro peq = ((xv.1, peq.1), \i -> (_, peq.2 i))
  1434. toFro : {xv : (a : A) * Q a} -> (y : fiber (f xv.1) xv.2) -> Path (to (fro y)) y
  1435. toFro peq =
  1436. J {_} {f xv.1 p}
  1437. (\xv1 eq1 -> Path (to {(xv.1, xv1)} (fro (p, sym eq1))) (p, sym eq1))
  1438. (JRefl {(a : A) * Q a} {(_, _)} (\xv1 eq1 -> fiber (f xv1.1) xv1.2) (p, refl))
  1439. (sym eq)
  1440. where p : P xv.1
  1441. p = peq.1
  1442. eq : Path {Q xv.1} xv.2 (f xv.1 p)
  1443. eq = peq.2
  1444. froTo : {xv : (a : A) * Q a} -> (y : fiber (total f) xv) -> Path (fro {xv} (to {xv} y)) y
  1445. froTo apeq =
  1446. J {(a : A) * Q a} {total f (a, p)}
  1447. (\xv1 eq1 -> Path (fro (to ((a, p), sym eq1))) ((a, p), sym eq1))
  1448. (ap fro (JRefl {(a : A) * Q a} {(a, _)}
  1449. (\xv1 eq1 -> fiber (f xv1.1) xv1.2) (p, refl)))
  1450. (sym eq)
  1451. where a : A
  1452. a = apeq.1.1
  1453. p : P a
  1454. p = apeq.1.2
  1455. eq : Path xv (total f (a, p))
  1456. eq = apeq.2
  1457. fiberEquiv : {A : Type} {P : A -> Type} {Q : A -> Type}
  1458. -> (f : (el : A) -> P el -> Q el)
  1459. -> isEquiv (total f)
  1460. -> (x : A) -> isEquiv (f x)
  1461. fiberEquiv f iseqv x y = isContrRetract {fiber (f x) y} {fiber (total f) (x, y)} eqv.2.1 eqv.1 eqv.2.2.1 (iseqv (x, y)) where
  1462. eqv : Iso (fiber (total f) (x, y)) (fiber (f x) y)
  1463. eqv = total_fibers f
  1464. totalEquiv : {A : Type} {P : A -> Type} {Q : A -> Type}
  1465. -> (f : (el : A) -> P el -> Q el)
  1466. -> ((x : A) -> isEquiv (f x))
  1467. -> isEquiv (total f)
  1468. totalEquiv f iseqv xv = isContrRetract eqv.1 eqv.2.1 eqv.2.2.2 (iseqv xv.1 xv.2) where
  1469. eqv : Iso (fiber (total f) xv) (fiber (f xv.1) xv.2)
  1470. eqv = total_fibers f
  1471. contrIsEquiv : {A : Type} {B : Type} -> isContr A -> isContr B
  1472. -> (f : A -> B) -> isEquiv f
  1473. contrIsEquiv cA cB f y =
  1474. ( (cA.1, isContr_isProp cB _ _)
  1475. , \v -> sigmaPath (isContr_isProp cA _ _)
  1476. (isProp_isSet (isContr_isProp cB) _ _ _ v.2)
  1477. )
  1478. theorem722 : {A : Type} {R : A -> A -> Type}
  1479. -> ((x : A) (y : A) -> isProp (R x y))
  1480. -> ((x : A) -> R x x)
  1481. -> (f : (x : A) (y : A) -> R x y -> Path x y)
  1482. -> {x : A} {y : A} -> isEquiv {R x y} {Path x y} (f x y)
  1483. theorem722 prop rho toId {x} {y} = fiberEquiv (toId x) (totalEquiv x) y where
  1484. rContr : (x : A) -> isContr ((y : A) * R x y)
  1485. rContr x = ((x, rho x), \y -> sigmaPath (toId _ _ y.2) (prop _ _ _ y.2))
  1486. totalEquiv : (x : A) -> isEquiv (total (toId x))
  1487. totalEquiv x = contrIsEquiv (rContr x) singContr (total (toId x))
  1488. isSet_Coproduct : {A : Type} {B : Type} -> isSet A -> isSet B -> isSet (Coproduct A B)
  1489. isSet_Coproduct setA setB = Req_isProp where
  1490. T = Coproduct A B
  1491. R : T -> T -> Type
  1492. R = \case
  1493. inl x -> \case
  1494. inl y -> Path x y
  1495. inr x -> Bottom
  1496. push c i -> absurd c
  1497. inr x -> \case
  1498. inl x -> Bottom
  1499. inr y -> Path x y
  1500. push c i -> absurd c c
  1501. R_prop : (x : T) (y : T) -> isProp (R x y)
  1502. R_prop = \case
  1503. inl x -> \case
  1504. inl y -> setA x y
  1505. inr y -> \p q -> absurd p
  1506. push c i -> absurd c
  1507. inr x -> \case
  1508. inl y -> \p q -> absurd p
  1509. inr y -> setB x y
  1510. push c i -> absurd c
  1511. R_refl : (x : T) -> R x x
  1512. R_refl = \case
  1513. inl x -> refl
  1514. inr x -> refl
  1515. push c i -> absurd c
  1516. R_impliesEq : (x : T) (y : T) -> R x y -> Path x y
  1517. R_impliesEq = \case
  1518. inl x -> \case
  1519. inl y -> \p -> ap inl p
  1520. inr y -> \p -> absurd p
  1521. push c i -> absurd c
  1522. inr x -> \case
  1523. inl y -> \p -> absurd p
  1524. inr y -> \p -> ap inr p
  1525. push c i -> absurd c
  1526. Req_isEquiv : {x : T} {y : T} -> Equiv (R x y) (Path x y)
  1527. Req_isEquiv = (R_impliesEq x y, theorem722 R_prop R_refl R_impliesEq)
  1528. Req_isProp : (x : T) (y : T) -> isProp (Path x y)
  1529. Req_isProp x y = isProp_equiv {R x y} {Path x y} (Req_isEquiv {x} {y}) (R_prop x y)
  1530. lemma492 : {A : Type} {B : Type} {X : Type}
  1531. -> (e : Equiv A B)
  1532. -> isEquiv {X -> A} {X -> B} (\f x -> e.1 (f x))
  1533. lemma492 =
  1534. EquivJ (\A B e -> isEquiv {X -> _} {X -> B} (\f x -> e.1 (f x)))
  1535. (\R -> (idEquiv {X -> R}).2)
  1536. twoOutOfThree_1 : {A : Type} {B : Type} {C : Type} {f : A -> B} {g : B -> C}
  1537. -> isEquiv f
  1538. -> isEquiv g
  1539. -> isEquiv (\x -> g (f x))
  1540. twoOutOfThree_1 feq geq =
  1541. EquivJ_range (\_ g -> isEquiv (\x -> g.1 (f x))) feq (g, geq)
  1542. twoOutOfThree_2 : {A : Type} {B : Type} {C : Type} {f : A -> B} {g : B -> C}
  1543. -> isEquiv f
  1544. -> isEquiv (\x -> g (f x))
  1545. -> isEquiv g
  1546. twoOutOfThree_2 feq gofeq =
  1547. EquivJ_domain (\_ f -> isEquiv (\x -> g (f.1 x)) -> isEquiv g) id (f, feq) gofeq
  1548. twoOutOfThree_3 : {A : Type} {B : Type} {C : Type} {f : A -> B} {g : B -> C}
  1549. -> isEquiv g
  1550. -> isEquiv (\x -> g (f x))
  1551. -> isEquiv f
  1552. twoOutOfThree_3 geq gofeq =
  1553. EquivJ_range (\_ g -> isEquiv (\x -> g.1 (f x)) -> isEquiv f) id (g, geq) gofeq
  1554. equivalence_isEmbedding : {A : Type} {B : Type}
  1555. -> {f : A -> B}
  1556. -> isEquiv f
  1557. -> {x : A} {y : A}
  1558. -> isEquiv (ap f {x} {y})
  1559. equivalence_isEmbedding feqv {x} {y} =
  1560. EquivJ (\A B eq -> (x : A) (y : A) -> isEquiv {_} {Path (eq.1 x) (eq.1 y)} (ap eq.1)) (\X x y -> (idEquiv {Path _ _}).2) (f, feqv) x y
  1561. isOfHLevel : Type -> Nat -> Type
  1562. isOfHLevel A = \case
  1563. zero -> (a : A) (b : A) -> Path a b
  1564. succ n -> (a : A) (b : A) -> isOfHLevel (Path a b) n
  1565. Sphere : Nat -> Type
  1566. Sphere = \case
  1567. zero -> Bottom
  1568. succ n -> Susp (Sphere n)
  1569. sphereFull : {A : Type} {n : Nat} (f : Sphere n -> A) -> Type
  1570. sphereFull f = (top : A) * (x : Sphere n) -> Path top (f x)
  1571. spheresFull : {n : Nat} -> Type -> Type
  1572. spheresFull A = (f : Sphere n -> A) -> sphereFull f
  1573. spheresFull_hLevel : {A : Type} (n : Nat) -> spheresFull {succ n} A -> isOfHLevel A n
  1574. spheresFull_hLevel =
  1575. \case
  1576. zero -> \full a b ->
  1577. let f : Sphere (succ zero) -> A
  1578. f = \case
  1579. north -> a
  1580. south -> b
  1581. merid u i -> absurd u
  1582. p = (full f).2
  1583. in trans (sym (p north)) (p south)
  1584. succ n -> \h x y -> spheresFull_hLevel n (helper h x y)
  1585. where
  1586. helper : {n : Nat} -> spheresFull {succ (succ n)} A -> (x : A) (y : A) -> spheresFull {succ n} (Path x y)
  1587. helper h x y f = (trans p q, r (transFiller p q)) where
  1588. f' : Susp (Sphere (succ n)) -> A
  1589. f' = \case
  1590. north -> x
  1591. south -> y
  1592. merid u i -> f u i
  1593. p : Path x (h f').1
  1594. p i = (h f').2 north (inot i)
  1595. q : Path (h f').1 y
  1596. q = (h f').2 south
  1597. r : (fillpq : PathP (\i -> Path x (q i)) p (trans p q))
  1598. (s : Sphere (succ n))
  1599. -> Path (fillpq i1) (f s)
  1600. r fillpq s i j = hcomp (\k [ (i = i0) -> fillpq k j
  1601. , (i = i1) -> (h f').2 (merid s j) k
  1602. , (j = i0) -> p (iand (inot k) i)
  1603. , (j = i1) -> q k ])
  1604. (inS (p (ior i j)))
  1605. isOfHLevel_hasSpheres : {A : Type} (n : Nat) -> isOfHLevel A n -> spheresFull {succ n} A
  1606. isOfHLevel_hasSpheres =
  1607. \case
  1608. zero -> \prop f -> (f north, \x -> prop (f north) (f x))
  1609. succ n -> \h -> helper {n} (\x y -> isOfHLevel_hasSpheres n (h x y))
  1610. where
  1611. helper : {n : Nat} -> ((a : A) (b : A) -> spheresFull {succ n} (Path a b))
  1612. -> spheresFull {succ (succ n)} A
  1613. helper {n} h f = (f north, r) where
  1614. north' = north {Sphere (succ n)}
  1615. south' = south {Sphere (succ n)}
  1616. merid' = merid {Sphere (succ n)}
  1617. r : (x : Sphere (succ (succ n))) -> Path (f north) (f x)
  1618. r = \case
  1619. north -> refl
  1620. south -> (h (f north') (f south') (\x i -> f (merid x i))).1
  1621. merid x i -> \j ->
  1622. hcomp (\k [ (i = i0) -> f north'
  1623. , (i = i1) -> (h (f north') (f south') (\x i -> f (merid' x i))).2 x (inot k) j
  1624. , (j = i0) -> f north'
  1625. , (j = i1) -> f (merid' x i) ])
  1626. (inS (f (merid' x (iand i j))))
  1627. data nTrunc (A : Type) (n : Nat) : Type where
  1628. incn : A -> nTrunc A n
  1629. hub : (f : Sphere (succ n) -> nTrunc A n) -> nTrunc A n
  1630. spoke i : (f : Sphere (succ n) -> nTrunc A n) (x : Sphere (succ n)) -> nTrunc A n [ (i = i0) -> hub f, (i = i1) -> f x ]
  1631. nTrunc_isOfHLevel : {n : Nat} {A : Type} -> isOfHLevel (nTrunc A n) n
  1632. nTrunc_isOfHLevel = spheresFull_hLevel {nTrunc A n} n (\f -> (hub f, \x i -> spoke f x i))
  1633. nTrunc_rec : {n : Nat} {A : Type} {B : Type}
  1634. -> isOfHLevel B n
  1635. -> (A -> B)
  1636. -> nTrunc A n -> B
  1637. nTrunc_rec bofhl f = go (isOfHLevel_hasSpheres n bofhl) where
  1638. work : (p : spheresFull {succ n} B) -> nTrunc A n -> B
  1639. work p = \case
  1640. hub sph -> (p (\x -> work p (sph x))).1
  1641. incn x -> f x
  1642. go : (p : spheresFull {succ n} B) -> nTrunc A n -> B
  1643. go p = \case
  1644. incn x -> f x
  1645. hub sph -> (p (\x -> work p (sph x))).1
  1646. spoke sph cell i -> (p (\x -> work p (sph x))).2 cell i
  1647. nTrunc_lift : {A : Type} {B : Type} {n : Nat} -> (A -> B) -> nTrunc A n -> nTrunc B n
  1648. nTrunc_lift f = nTrunc_rec (nTrunc_isOfHLevel {n} {B}) (\x -> incn {B} {n} (f x))
  1649. -- data W (A : Type) (B : A -> Type) : Type where
  1650. -- sup : (a : A) -> (B a -> W A B) -> W A B
  1651. -- Welim : {A : Type} {B : A -> Type} (P : W A B -> Type)
  1652. -- -> (sup : (a : A) (f : B a -> W A B) (g : (x : B a) -> P (f x)) -> P (sup a f))
  1653. -- -> (c : W A B) -> P c
  1654. -- Welim P k = \case
  1655. -- sup a f -> k a f (\x -> Welim P k (f x))
  1656. -- wnat : Type
  1657. -- wnat = W Bool (if Unit Bottom)
  1658. -- wzero : wnat
  1659. -- wzero = sup false absurd
  1660. -- wsucc : wnat -> wnat
  1661. -- wsucc n = sup true (\x -> n)
  1662. -- wnat_elim : (P : wnat -> Type) (pz : P wzero) (ps : (c : wnat) -> P c -> P (wsucc c)) -> (x : wnat) -> P x
  1663. -- wnat_elim P pz ps x = Welim P (\a f g -> helper a f g) x where
  1664. -- A = Bool
  1665. -- B = if Unit Bottom
  1666. -- helper : (a : A) (f : B a -> W A B) (g : (x : B a) -> P (f x)) -> P (sup a f)
  1667. -- helper = \case
  1668. -- false -> \f g -> pz
  1669. -- true -> \f g ->
  1670. -- let
  1671. -- t : P (sup true (\x -> f tt))
  1672. -- t = ps (f tt) (g tt)
  1673. -- in transp (\i -> P (sup true (\x -> f (unitEta x (inot i))))) t
  1674. -- nat_is_wnat : Path Nat wnat
  1675. -- nat_is_wnat = IsoToId (to, from, toFrom, fromTo) where
  1676. -- to : Nat -> wnat
  1677. -- to = Nat_elim (\x -> wnat) wzero (\_ x -> wsucc x)
  1678. -- from : wnat -> Nat
  1679. -- from = wnat_elim (\x -> Nat) zero (\_ x -> succ x)
  1680. -- toFrom : (y : wnat) -> Path (to (from y)) y
  1681. -- toFrom = wnat_elim (\x -> Path (to (from x)) x) refl (\x y -> ap wsucc y)
  1682. -- fromTo : (x : Nat) -> Path (from (to x)) x
  1683. -- fromTo = Nat_elim (\x -> Path (from (to x)) x) refl (\x y -> ap succ y)
  1684. -- plusWnat : wnat -> wnat -> wnat
  1685. -- plusWnat = subst (\x -> x -> x -> x) nat_is_wnat plusNat
  1686. -- Pointed : Type
  1687. -- Pointed = (X : Type) * X * isSet X
  1688. -- Set : Type
  1689. -- Set = (X : Type) * isSet X
  1690. -- map : Set -> Set -> Type
  1691. -- map A B = A.1 -> B.1
  1692. -- pmap : Pointed -> Pointed -> Type
  1693. -- pmap A B = (f : A.1 -> B.1) * Path (f A.2.1) B.2.1
  1694. -- Zero : Pointed
  1695. -- Zero = (Unit, tt, isProp_isSet l) where
  1696. -- l : (a : Unit) (b : Unit) -> Path a b
  1697. -- l = \case
  1698. -- tt -> \case
  1699. -- tt -> refl
  1700. -- compose : {A : Pointed} {B : Pointed} {C : Pointed} -> pmap B C -> pmap A B -> pmap A C
  1701. -- compose g f = (\x -> g.1 (f.1 x), subst (\x -> Path (g.1 x) C.2.1) (sym f.2) g.2)
  1702. -- id : {A : Pointed} -> pmap A A
  1703. -- id = (\x -> x, refl)
  1704. -- initial : {A : Pointed} -> pmap Zero A
  1705. -- initial = (\_ -> A.2.1, refl)
  1706. -- terminal : {A : Pointed} -> pmap A Zero
  1707. -- terminal = (\_ -> tt, refl)
  1708. -- cast : {A : Pointed} {B : Pointed} -> pmap A B
  1709. -- cast = compose {A} {Zero} {B} (initial {B}) (terminal {A})
  1710. -- Product : Pointed -> Pointed -> Pointed
  1711. -- Product A B = (A.1 * B.1, (A.2.1, B.2.1), isSet_prod A.2.2 B.2.2)
  1712. -- proj1 : {A : Pointed} {B : Pointed} -> pmap (Product A B) A
  1713. -- proj1 = (\x -> x.1, refl)
  1714. -- proj2 : {A : Pointed} {B : Pointed} -> pmap (Product A B) B
  1715. -- proj2 = (\x -> x.2, refl)
  1716. -- cross : {G : Pointed} {A : Pointed} {B : Pointed} -> pmap G A -> pmap G B -> pmap G (Product A B)
  1717. -- cross f g = (\x -> (f.1 x, g.1 x), \i -> (f.2 i, g.2 i))
  1718. -- inj1 : {A : Pointed} {B : Pointed} -> pmap A (Product A B)
  1719. -- inj1 = cross {A} {A} {B} (id {A}) (cast {A} {B})
  1720. -- inj2 : {A : Pointed} {B : Pointed} -> pmap B (Product A B)
  1721. -- inj2 = cross {B} {A} {B} (cast {B} {A}) (id {B})
  1722. -- pmap_equal : {A : Pointed} {B : Pointed} (f : pmap A B) (g : pmap A B) -> Path f.1 g.1 -> Path f g
  1723. -- pmap_equal f g p = sigmaPath {A.1 -> B.1} {\f -> Path (f A.2.1) B.2.1} p (transp (\i -> PathP_is_Path (\i -> Path (p i A.2.1) B.2.1) f.2 g.2 (inot i)) (B.2.2 _ _ _ _))
  1724. -- zero_comp : {A : Pointed} {B : Pointed} {C : Pointed} (f : pmap B C)
  1725. -- -> Path (compose {A} {B} {C} f (cast {A} {B})) (cast {A} {C})
  1726. -- zero_comp f = pmap_equal {A} {C} _ _ (\i x -> f.2 i)
  1727. -- Forget : Pointed -> Set
  1728. -- Forget P = (P.1, P.2.2)
  1729. -- Free : Set -> Pointed
  1730. -- Free P = (Coproduct P.1 Unit, inr tt, Coproduct_isSet P.2 unitSet)
  1731. Precategory : Type
  1732. Precategory = (Ob : Type)
  1733. * (Hom : Ob -> Ob -> Type)
  1734. * (hset : (A : Ob) (B : Ob) -> isSet (Hom A B))
  1735. * (id : {A : Ob} -> Hom A A)
  1736. * (compose : {A : Ob} {B : Ob} {C : Ob} -> Hom B C -> Hom A B -> Hom A C)
  1737. * (idl : {A : Ob} {B : Ob} (f : Hom A B) -> Path (compose id f) f)
  1738. * (idr : {A : Ob} {B : Ob} (f : Hom A B) -> Path (compose f id) f)
  1739. * ({A : Ob} {B : Ob} {C : Ob} {D : Ob}
  1740. -> (f : Hom C D) (g : Hom B C) (h : Hom A B)
  1741. -> Path (compose f (compose g h)) (compose (compose f g) h))
  1742. Ob : (C : Precategory) -> Type
  1743. Ob C = C.1
  1744. Hom : (C : Precategory) -> Ob C -> Ob C -> Type
  1745. Hom C = C.2.1
  1746. homSet : {C : Precategory} (A : Ob C) (B : Ob C) -> isSet (Hom C A B)
  1747. homSet = C.2.2.1
  1748. Cid : (C : Precategory) {A : Ob C} -> Hom C A A
  1749. Cid C = C.2.2.2.1
  1750. compose : {Cat : Precategory} {A : Ob Cat} {B : Ob Cat} {C : Ob Cat}
  1751. -> Hom Cat B C -> Hom Cat A B -> Hom Cat A C
  1752. compose = Cat.2.2.2.2.1
  1753. leftId : {Cat : Precategory} {A : Ob Cat} {B : Ob Cat}
  1754. -> (f : Hom Cat A B) -> Path (compose {Cat} (Cid Cat) f) f
  1755. leftId = Cat.2.2.2.2.2.1
  1756. rightId : {Cat : Precategory} {A : Ob Cat} {B : Ob Cat}
  1757. -> (f : Hom Cat A B) -> Path (compose {Cat} f (Cid Cat)) f
  1758. rightId = Cat.2.2.2.2.2.2.1
  1759. assocCompose : {Cat : Precategory} {A : Ob Cat} {B : Ob Cat} {C : Ob Cat} {D : Ob Cat}
  1760. -> (f : Hom Cat C D) (g : Hom Cat B C) (h : Hom Cat A B)
  1761. -> Path (compose {Cat} f (compose {Cat} g h)) (compose {Cat} (compose {Cat} f g) h)
  1762. assocCompose = Cat.2.2.2.2.2.2.2
  1763. Opposite : Precategory -> Precategory
  1764. Opposite Cat =
  1765. ( Cat.1
  1766. , \A B -> Cat.2.1 B A
  1767. , \A B -> Cat.2.2.1 B A
  1768. , Cat.2.2.2.1
  1769. , \f g -> compose {Cat} g f
  1770. , \f -> rightId {Cat} f
  1771. , \f -> leftId {Cat} f
  1772. , \f g h i -> assocCompose {Cat} h g f (inot i)
  1773. )
  1774. Coprod : {Cat : Precategory} -> Ob Cat -> Ob Cat -> Type
  1775. Coprod A B = (sum : Ob Cat)
  1776. * (inl : Hom Cat A sum)
  1777. * (inr : Hom Cat B sum)
  1778. * (elim : {S : Ob Cat} -> Hom Cat A S -> Hom Cat B S -> Hom Cat sum S)
  1779. * (eliml : {S : Ob Cat} (f : Hom Cat A S) (g : Hom Cat B S)
  1780. -> Path (compose {Cat} (elim f g) inl) f)
  1781. * ({S : Ob Cat} (f : Hom Cat A S) (g : Hom Cat B S)
  1782. -> Path (compose {Cat} (elim f g) inr) g)
  1783. Product : {Cat : Precategory} -> Ob Cat -> Ob Cat -> Type
  1784. Product = Coprod {Opposite Cat}
  1785. Set : Precategory
  1786. Set = (T, \A B -> A.1 -> B.1, homset, \x -> x, \g f x -> g (f x), \f -> refl, \f -> refl, \f g h -> refl) where
  1787. T = (X : Type) * isSet X
  1788. homset : (A : T) (B : T) -> isSet (A.1 -> B.1)
  1789. homset A B = isSet_pi (\_ -> B.2)
  1790. nat : Ob Set
  1791. nat = (Nat, Nat_isSet)
  1792. setCoprod : (A : Ob Set) (B : Ob Set) -> Coprod {Set} A B
  1793. setCoprod A B = (T, inl, inr, elim, \f g i x -> f x, \f g i x -> g x) where
  1794. T : Ob Set
  1795. T = (Coproduct A.1 B.1, isSet_Coproduct A.2 B.2)
  1796. elim : {S : Ob Set} -> Hom Set A S -> Hom Set B S -> Hom Set T S
  1797. elim f g = \case
  1798. inl x -> f x
  1799. inr x -> g x
  1800. push c i -> absurd c
  1801. setProd : (A : Ob Set) (B : Ob Set) -> Product {Set} A B
  1802. setProd A B = (T, \x -> x.1, \x -> x.2, \{S} -> cross {S}, \f g i -> f, \f g i -> g) where
  1803. T : Ob Set
  1804. T = (A.1 * B.1, isSet_prod A.2 B.2)
  1805. cross : {S : Ob Set} -> Hom Set S A -> Hom Set S B -> Hom Set S T
  1806. cross f g x = (f x, g x)
  1807. isIsoHom : {Cat : Precategory} {A : Ob Cat} {B : Ob Cat} -> Hom Cat A B -> Type
  1808. isIsoHom f = (inv : Hom Cat B A) * Path (compose {Cat} f inv) (Cid Cat) * Path (compose {Cat} inv f) (Cid Cat)
  1809. Isomorphism : {Cat : Precategory} -> Ob Cat -> Ob Cat -> Type
  1810. Isomorphism A B = (f : Hom Cat A B) * isIsoHom {Cat} {A} {B} f
  1811. isCategory : Precategory -> Type
  1812. isCategory Cat = (A : Ob Cat) (B : Ob Cat) -> Equiv (Path A B) (Isomorphism {Cat} A B)
  1813. -- setIsCategory : isCategory Set
  1814. -- setIsCategory A B = IsoToEquiv (pathTo, fromIso, pathTo_fromIso, _) where
  1815. -- pathTo : Path A B -> Isomorphism {Set} A B
  1816. -- pathTo = J {Ob Set} {A} (\B _ -> Isomorphism {Set} A B) (id, id, refl, refl)
  1817. --
  1818. -- augment : Path A.1 B.1 -> Path A B
  1819. --
  1820. -- fromIso : Isomorphism {Set} A B -> Path A B
  1821. -- fromIso iso = augment (IsoJ (\{A} f g -> Path A B.1) refl iso.1 iso.2.1 iso.2.2.2 iso.2.2.1)
  1822. --
  1823. -- augment p = sigmaPath {Type} {isSet} p (transp (\i -> PathP_is_Path (\j -> isSet (p j)) A.2 B.2 (inot i)) (isSet_isProp {B.1} (transp (\i -> isSet (p i)) A.2) B.2))
  1824. --
  1825. -- pathTo_fromIso : (i : Isomorphism {Set} A B) -> Path (pathTo (fromIso i)) i
  1826. -- pathTo_fromIso iso i = (iso.1, iso.2.1, iso.2.2.1, iso.2.2.2)
  1827. sym_subst : {A : Type} {x : A} {y : A} -> Path x y -> Path y x
  1828. sym_subst p = subst (\y -> Path y x) p refl
  1829. trans_subst : {A : Type} {x : A} {y : A} {z : A} -> Path x y -> Path y z -> Path x z
  1830. trans_subst p q = subst (\y -> Path y z -> Path x z) p id q
  1831. data Unlist (A : Type) : Type where
  1832. uncons : A -> Unlist A -> Unlist A
  1833. unelim : {A : Type}
  1834. (P : Unlist A -> Type)
  1835. -> ((x : A) (tail : Unlist A) -> P tail -> P (uncons x tail))
  1836. -> (x : Unlist A) -> P x
  1837. unelim P c = \case
  1838. uncons x xs -> c x xs (unelim P c xs)
  1839. contra : {A : Type} -> Unlist A -> Bottom
  1840. contra = unelim (\x -> Bottom) (\_ _ x -> x)
  1841. plusInt : Int -> Int -> Int
  1842. plusInt x y = winding (trans (goAround x) (goAround y))
  1843. add : Nat -> Nat -> Nat
  1844. add = Nat_elim (\ _ -> Nat -> Nat) (\ x -> x) (\n k x -> succ (k x))
  1845. addAssoc : (i : Nat) (j : Nat) (k : Nat) -> Path (add i (add j k)) (add (add i j) k)
  1846. addAssoc = Nat_elim (\ i -> (j : Nat) (k : Nat) -> Path (add i (add j k)) (add (add i j) k)) (\j k -> refl) (\n assoc j k -> ap succ (assoc j k))
  1847. Jsym : {A : Type} {x : A} {y : A} -> Path x y -> Path y x
  1848. Jsym = J (\y _ -> Path y x) refl
  1849. Vect : Type -> Nat -> Type
  1850. Vect A = \case
  1851. zero -> Unit
  1852. succ n -> A * Vect A n
  1853. Vect_elim : {A : Type} (P : {n : Nat} -> Vect A n -> Type)
  1854. -> P {zero} tt
  1855. -> ({n : Nat} (x : A) (xs : Vect A n) -> P {n} xs -> P {succ n} (x, xs))
  1856. -> {n : Nat} (x : Vect A n) -> P {n} x
  1857. Vect_elim P nil cons {n} x = go n x where
  1858. go : (n : Nat) (x : Vect A n) -> P x
  1859. go = \case
  1860. zero -> \case
  1861. tt -> nil
  1862. succ n -> \xs -> cons {n} xs.1 xs.2 (go n xs.2)
  1863. head : {A : Type} {n : Nat} -> Vect A (succ n) -> A
  1864. head xs = xs.1
  1865. tail : {A : Type} {n : Nat} -> Vect A (succ n) -> Vect A n
  1866. tail xs = xs.2
  1867. equivToIso : {A : Type} {B : Type} (f : A -> B) -> isEquiv f -> isIso f
  1868. equivToIso f e = EquivJ (\X Y f -> isIso f.1) (\x -> (id, \x -> refl, \x -> refl)) (f, e)