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.

1689 lines
59 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 {A} = PathP (\i -> A)
  54. -- reflexivity is given by constant paths
  55. refl : {A : Type} {x : A} -> Path x x
  56. refl {A} {x} 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. singContr : {A : Type} {a : A} -> isContr (Singl A a)
  87. singContr {A} {a} = ((a, \i -> a), \y i -> (y.2 i, \j -> y.2 (iand i j)))
  88. -- Some more operations on paths. By rearranging parentheses we get a
  89. -- proof that the images of equal elements are themselves equal.
  90. 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)
  91. ap f p i = f (p i)
  92. -- These satisfy definitional equalities, like apComp and apId, which are
  93. -- propositional in vanilla MLTT.
  94. apComp : {A : Type} {B : Type} {C : Type}
  95. {f : A -> B} {g : B -> C} {x : A} {y : A}
  96. (p : Path x y)
  97. -> Path (ap g (ap f p)) (ap (\x -> g (f x)) p)
  98. apComp p = refl
  99. apId : {A : Type} {x : A} {y : A}
  100. (p : Path x y)
  101. -> Path (ap (id {A}) p) p
  102. apId p = refl
  103. -- Just like rearranging parentheses gives us ap, swapping the value
  104. -- and interval binders gives us function extensionality.
  105. funext : {A : Type} {B : A -> Type} {f : (x : A) -> B x} {g : (x : A) -> B x}
  106. (h : (x : A) -> Path (f x) (g x))
  107. -> Path f g
  108. funext h i x = h x i
  109. -- The proposition associated with an element of the interval
  110. -------------------------------------------------------------
  111. Eq_s : {A : Pretype} -> A -> A -> Pretype
  112. {-# PRIMITIVE Eq_s #-}
  113. refl_s : {A : Pretype} {x : A} -> Eq_s x x
  114. {-# PRIMITIVE refl_s #-}
  115. 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
  116. {-# PRIMITIVE J_s #-}
  117. K_s : {A : Pretype} {x : A} (P : Eq_s x x -> Pretype) -> P (refl_s {A} {x}) -> (p : Eq_s x x) -> P p
  118. {-# PRIMITIVE K_s #-}
  119. -- Associated with every element i : I of the interval, we have the type
  120. -- IsOne i which is inhabited only when i = i1. In the model, this
  121. -- corresponds to the map [φ] from the interval cubical set to the
  122. -- subobject classifier.
  123. IsOne : I -> Pretype
  124. IsOne i = Eq_s i i1
  125. -- The value itIs1 witnesses the fact that i1 = i1.
  126. itIs1 : IsOne i1
  127. itIs1 = refl_s
  128. -- Partial elements
  129. -------------------
  130. --
  131. -- Since a function I -> A has two endpoints, and a function I -> I -> A
  132. -- has four endpoints + four functions I -> A as "sides" (obtained by
  133. -- varying argument while holding the other as a bound variable), we
  134. -- refer to elements of I^n -> A as "cubes".
  135. -- This justifies the existence of partial elements, which are, as the
  136. -- name implies, partial cubes. Namely, a Partial φ A is an element of A
  137. -- which depends on a proof that IsOne φ.
  138. Partial : I -> Type -> Pretype
  139. {-# PRIMITIVE Partial #-}
  140. -- There is also a dependent version where the type A is itself a
  141. -- partial element.
  142. PartialP : (phi : I) -> Partial phi Type -> Pretype
  143. {-# PRIMITIVE PartialP #-}
  144. -- Why is Partial φ A not just defined as φ -> A? The difference is that
  145. -- Partial φ A has an internal representation which definitionally relates
  146. -- any two partial elements which "agree everywhere", that is, have
  147. -- equivalent values for every possible assignment of variables which
  148. -- makes IsOne φ hold.
  149. -- Cubical Subtypes
  150. --------------------
  151. -- Given A : Type, phi : I, and a partial element u : A defined on φ,
  152. -- we have the type Sub A phi u, notated A[phi -> u] in the output of
  153. -- the type checker, whose elements are "extensions" of u.
  154. -- That is, element of A[phi -> u] is an element of A defined everywhere
  155. -- (a total element), which, when IsOne φ, agrees with u.
  156. Sub : (A : Type) (phi : I) -> Partial phi A -> Pretype
  157. {-# PRIMITIVE Sub #-}
  158. -- Every total element u : A can be made partial on φ by ignoring the
  159. -- constraint. Furthermore, this "totally partial" element agrees with
  160. -- the original total element on φ.
  161. inS : {A : Type} {phi : I} (u : A) -> Sub A phi (\x -> u)
  162. {-# PRIMITIVE inS #-}
  163. -- When IsOne φ, outS {A} {φ} {u} x reduces to u itIs1.
  164. -- This implements the fact that x agrees with u on φ.
  165. outS : {A : Type} {phi : I} {u : Partial phi A} -> Sub A phi u -> A
  166. {-# PRIMITIVE outS #-}
  167. -- The composition operation
  168. ----------------------------
  169. -- Now that we have syntax for specifying partial cubes,
  170. -- and specifying that an element agrees with a partial cube,
  171. -- we can describe the composition operation.
  172. 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)
  173. {-# PRIMITIVE comp primComp #-}
  174. comp : (A : I -> Type) {phi : I} (u : (i : I) -> Partial phi (A i)) -> Sub (A i0) phi (u i0) -> A i1
  175. comp A {phi} u a0 = outS (primComp A {phi} u a0)
  176. -- In particular, when φ is a disjunction of the form
  177. -- (j = 0) || (j = 1), we can draw u as being a pair of lines forming a
  178. -- "tube", an open square with no floor or roof:
  179. --
  180. -- Given u = \j [ (i = i0) -> x, (i = i1) -> q j] on the extent i || ~i,
  181. -- we draw:
  182. --
  183. -- x q i1
  184. -- | |
  185. -- \j -> x | | \j -> q j
  186. -- | |
  187. -- x q i0
  188. --
  189. -- The composition operation says that, as long as we can provide a
  190. -- "floor" connecting x -- q i0, as a total element of A which, on
  191. -- phi, extends u i0, then we get the "roof" connecting x and q i1
  192. -- for free.
  193. --
  194. -- If we have a path p : x ≡ y, and q : y ≡ z, then we do get the
  195. -- "floor", and composition gets us the dotted line:
  196. --
  197. -- x..........z
  198. -- | |
  199. -- x | | q j
  200. -- | |
  201. -- x----------y
  202. -- p i
  203. trans : {A : Type} {x : A} {y : A} {z : A} -> PathP (\i -> A) x y -> PathP (\i -> A) y z -> PathP (\i -> A) x z
  204. trans {A} {x} p q i =
  205. comp (\i -> A)
  206. {ior i (inot i)}
  207. (\j [ (i = i0) -> x, (i = i1) -> q j ])
  208. (inS (p i))
  209. -- In particular when the formula φ = i0 we get the "opposite face" to a
  210. -- single point, which corresponds to transport.
  211. transp : (A : I -> Type) (x : A i0) -> A i1
  212. transp A x = comp A {i0} (\i [ ]) (inS x)
  213. subst : {A : Type} (P : A -> Type) {x : A} {y : A} -> Path x y -> P x -> P y
  214. subst P p x = transp (\i -> P (p i)) x
  215. -- Since we have the iand operator, we can also derive the *filler* of a cube,
  216. -- which connects the given face and the output of composition.
  217. fill : (A : I -> Type) {phi : I} (u : (i : I) -> Partial phi (A i)) (a0 : Sub (A i0) phi (u i0))
  218. -> PathP A (outS a0) (comp A {phi} u a0)
  219. fill A {phi} u a0 i =
  220. comp (\j -> A (iand i j))
  221. {ior phi (inot i)}
  222. (\j [ (phi = i1) -> u (iand i j) itIs1
  223. , (i = i0) -> outS a0
  224. ])
  225. (inS (outS a0))
  226. hcomp : {A : Type} {phi : I} (u : (i : I) -> Partial phi A) -> Sub A phi (u i0) -> A
  227. hcomp {A} {phi} u a0 = comp (\i -> A) {phi} u a0
  228. hfill : {A : Type} {phi : I} (u : (i : I) -> Partial phi A) -> (a0 : Sub A phi (u i0)) -> Path (outS a0) (hcomp u a0)
  229. hfill {A} {phi} u a0 i = fill (\i -> A) {phi} u a0 i
  230. -- For instance, the filler of the previous composition square
  231. -- tells us that trans p refl = p:
  232. transRefl : {A : Type} {x : A} {y : A} (p : Path x y) -> Path (trans p refl) p
  233. transRefl p j i = fill (\i -> A) {ior i (inot i)} (\k [ (i = i0) -> x, (i = i1) -> y ]) (inS (p i)) (inot j)
  234. rightCancel : {A : Type} {x : A} {y : A} (p : Path x y) -> Path (trans p (sym p)) refl
  235. rightCancel p j i = cube p i1 j i where
  236. cube : {A : Type} {x : A} {y : A} (p : Path x y) -> I -> I -> I -> A
  237. cube {A} {x} p k j i =
  238. hfill {A} (\ k [ (i = i0) -> x
  239. , (i = i1) -> p (iand (inot k) (inot j))
  240. , (j = i1) -> x
  241. ])
  242. (inS (p (iand i (inot j)))) k
  243. leftCancel : {A : Type} {x : A} {y : A} (p : Path x y) -> Path (trans (sym p) p) refl
  244. leftCancel p = rightCancel (sym p)
  245. transpFill : {A : I -> Type} (x : A i0) -> PathP A x (transp (\i -> A i) x)
  246. transpFill {A} x i = fill (\i -> A i) (\k []) (inS x) i
  247. -- Reduction of composition
  248. ---------------------------
  249. --
  250. -- Composition reduces on the structure of the family A : I -> Type to create
  251. -- the element a1 : (A i1)[phi -> u i1].
  252. --
  253. -- For instance, when filling a cube of functions, the behaviour is to
  254. -- first transport backwards along the domain, apply the function, then
  255. -- forwards along the codomain.
  256. transpFun : {A : Type} {B : Type} {C : Type} {D : Type} (p : Path A B) (q : Path C D)
  257. -> (f : A -> C) -> Path (transp (\i -> p i -> q i) f)
  258. (\x -> transp (\i -> q i) (f (transp (\i -> p (inot i)) x)))
  259. transpFun p q f = refl
  260. transpDFun : {A : I -> Type} {B : (i : I) -> A i -> Type}
  261. -> (f : (x : A i0) -> B i0 x)
  262. -> Path (transp (\i -> (x : A i) -> B i x) f)
  263. (\x -> transp (\i -> B i (fill (\j -> A (inot j)) (\k []) (inS x) (inot i)))
  264. (f (fill (\j -> A (inot j)) (\k []) (inS x) i1)))
  265. transpDFun f = refl
  266. -- When considering the more general case of a composition respecing sides,
  267. -- the outer transport becomes a composition.
  268. -- Glueing and Univalence
  269. -------------------------
  270. -- First, let's get some definitions out of the way.
  271. --
  272. -- The *fiber* of a function f : A -> B at a point y : B is the type of
  273. -- inputs x : A which f takes to y, that is, for which there exists a
  274. -- path f(x) = y.
  275. fiber : {A : Type} {B : Type} -> (A -> B) -> B -> Type
  276. fiber f y = (x : A) * Path y (f x)
  277. -- An *equivalence* is a function where every fiber is contractible.
  278. -- That is, for every point in the codomain y : B, there is exactly one
  279. -- point in the input which f maps to y.
  280. isEquiv : {A : Type} {B : Type} -> (A -> B) -> Type
  281. isEquiv {A} {B} f = (y : B) -> isContr (fiber {A} {B} f y)
  282. -- By extracting this point, which must exist because the fiber is contractible,
  283. -- we can get an inverse of f:
  284. invert : {A : Type} {B : Type} {f : A -> B} -> isEquiv f -> B -> A
  285. invert eqv y = (eqv y) .1 .1
  286. retract : {A : Type} {B : Type} -> (A -> B) -> (B -> A) -> Type
  287. retract {A} {B} f g = (a : A) -> Path (g (f a)) a
  288. -- Proving that it's also a retraction is left as an exercise to the
  289. -- reader. We can package together a function and a proof that it's an
  290. -- equivalence to get a capital-E Equivalence.
  291. Equiv : (A : Type) (B : Type) -> Type
  292. Equiv A B = (f : A -> B) * isEquiv {A} {B} f
  293. -- The identity function is an equivalence between any type A and
  294. -- itself.
  295. idEquiv : {A : Type} -> Equiv A A
  296. idEquiv {A} = (\x -> x, \y -> ((y, \i -> y), \u i -> (u.2 i, \j -> u.2 (iand i j))))
  297. -- The glue operation expresses that "extensibility is invariant under
  298. -- equivalence". Less concisely, the Glue type and its constructor,
  299. -- glue, let us extend a partial element of a partial type to a total
  300. -- element of a total type, by "gluing" the partial type T using a
  301. -- partial equivalence e onto a total type A.
  302. -- In particular, we have that when φ = i1, Glue A [i1 -> (T, f)] = T.
  303. primGlue : (A : Type) {phi : I}
  304. (T : Partial phi Type)
  305. (e : PartialP phi (\o -> Equiv (T o) A))
  306. -> Type
  307. {-# PRIMITIVE Glue primGlue #-}
  308. -- The glue constructor extends the partial element t : T to a total
  309. -- element of Glue A [φ -> (T, e)] as long as we have a total im : A
  310. -- which is the image of f(t).
  311. --
  312. -- Agreeing with the condition that Glue A [i1 -> (T, e)] = T,
  313. -- we have that glue {A} {i1} t im => t.
  314. prim'glue : {A : Type} {phi : I} {T : Partial phi Type} {e : PartialP phi (\o -> Equiv (T o) A)}
  315. -> (t : PartialP phi T)
  316. -> (im : Sub A phi (\o -> (e o).1 (t o)))
  317. -> primGlue A T e
  318. {-# PRIMITIVE glue prim'glue #-}
  319. glue : {A : Type} {phi : I} {Te : Partial phi ((T : Type) * Equiv T A)}
  320. -> (t : PartialP phi (\o -> (Te o).1))
  321. -> (im : Sub A phi (\o -> (Te o).2.1 (t o)))
  322. -> primGlue A {phi} (\o -> (Te o).1) (\o -> (Te o).2)
  323. glue {A} {phi} {Te} t im = prim'glue {A} {phi} {\o -> (Te o).1} {\o -> (Te o).2} t im
  324. -- The unglue operation undoes a glueing. Since when φ = i1,
  325. -- Glue A [φ -> (T, f)] = T, the argument to primUnglue {A} {i1} ...
  326. -- will have type T, and so to get back an A we need to apply the
  327. -- partial equivalence f (defined everywhere).
  328. primUnglue : {A : Type} {phi : I} {T : Partial phi Type} {e : PartialP phi (\o -> Equiv (T o) A)}
  329. -> primGlue A {phi} T e -> A
  330. {-# PRIMITIVE unglue primUnglue #-}
  331. unglue : {A : Type} (phi : I) {Te : Partial phi ((T : Type) * Equiv T A)}
  332. -> primGlue A {phi} (\o -> (Te o).1) (\o -> (Te o).2) -> A
  333. unglue {A} phi {Te} = primUnglue {A} {phi} {\o -> (Te o).1} {\o -> (Te o).2}
  334. -- Diagramatically, i : I |- Glue A [(i \/ ~i) -> (T, e)] can be drawn
  335. -- as giving us the dotted line in:
  336. --
  337. -- T i0 ......... T i1
  338. -- | |
  339. -- | |
  340. -- e i0 |~ ~| e i1
  341. -- | |
  342. -- | |
  343. -- A i0 --------- A i1
  344. -- A
  345. --
  346. -- Where the the two "e" sides are equivalences, and the Bottom side is
  347. -- the line i : I |- A.
  348. --
  349. -- Thus, by choosing a base type, a set of partial types and partial
  350. -- equivalences, we can make a line between two types (T i0) and (T i1).
  351. Glue : (A : Type) {phi : I} -> Partial phi ((X : Type) * Equiv X A) -> Type
  352. Glue A {phi} u = primGlue A {phi} (\o -> (u o).1) (\o -> (u o).2)
  353. -- For example, we can glue together the type A and the type B as long
  354. -- as there exists an Equiv A B.
  355. --
  356. -- A ............ B
  357. -- | |
  358. -- | |
  359. -- equiv |~ ua equiv ~| idEquiv {B}
  360. -- | |
  361. -- | |
  362. -- B ------------ B
  363. -- \i → B
  364. --
  365. ua : {A : Type} {B : Type} -> Equiv A B -> Path A B
  366. ua {A} {B} equiv i =
  367. Glue B (\[ (i = i0) -> (A, equiv),
  368. (i = i1) -> (B, idEquiv) ])
  369. lineToEquiv : (A : I -> Type) -> Equiv (A i0) (A i1)
  370. {-# PRIMITIVE lineToEquiv #-}
  371. idToEquiv : {A : Type} {B : Type} -> Path A B -> Equiv A B
  372. idToEquiv p = lineToEquiv (\i -> p i)
  373. isEquivTransport : (A : I -> Type) -> isEquiv (transp A)
  374. isEquivTransport A = (lineToEquiv A).2
  375. -- The fact that this diagram has 2 filled-in B sides explains the
  376. -- complication in the proof below.
  377. --
  378. -- In particular, the actual behaviour of transp (\i -> ua f i)
  379. -- (x : A) is not just to apply f x to get a B (the left side), it also
  380. -- needs to:
  381. --
  382. -- * For the Bottom side, compose along (\i -> B) (the Bottom side)
  383. -- * For the right side, apply the inverse of the identity, which
  384. -- is just identity, to get *some* b : B
  385. --
  386. -- But that b : B might not agree with the sides of the composition
  387. -- operation in a more general case, so it composes along (\i -> B)
  388. -- *again*!
  389. --
  390. -- Thus the proof: a simple cubical argument suffices, since
  391. -- for any composition, its filler connects either endpoints. So
  392. -- we need to come up with a filler for the Bottom and right faces.
  393. uaBeta : {A : Type} {B : Type} (f : Equiv A B) -> Path (transp (\i -> ua f i)) f.1
  394. uaBeta {A} {B} f i a = transpFill {\i -> B} (f.1 a) (inot i)
  395. -- The terms ua + uaBeta suffice to prove the "full"
  396. -- ua axiom of Voevodsky, as can be seen in the paper
  397. --
  398. -- Ian Orton, & Andrew M. Pitts. (2017). Decomposing the Univalence Axiom.
  399. --
  400. -- Available freely here: https://arxiv.org/abs/1712.04890v3
  401. J : {A : Type} {x : A}
  402. (P : (y : A) -> Path x y -> Type)
  403. (d : P x (\i -> x))
  404. {y : A} (p : Path x y)
  405. -> P y p
  406. J P d p = transp (\i -> P (p i) (\j -> p (iand i j))) d
  407. JRefl : {A : Type} {x : A}
  408. (P : (y : A) -> Path x y -> Type)
  409. (d : P x (\i -> x))
  410. -> Path (J {A} {x} P d {x} (\i -> x)) d
  411. JRefl P d i = transpFill {\i -> P x (\j -> x)} d (inot i)
  412. Jay : {A : Type} {x : A}
  413. (P : ((y : A) * Path x y) -> Type)
  414. (d : P (x, refl))
  415. (s : (y : A) * Path x y)
  416. -> P s
  417. Jay P d s = transp (\i -> P ((singContr {A} {x}).2 s i)) d
  418. -- Isomorphisms
  419. ---------------
  420. --
  421. -- Since isomorphisms are a much more convenient notion of equivalence
  422. -- than contractible fibers, it's natural to ask why the CCHM paper, and
  423. -- this implementation following that, decided on the latter for our
  424. -- definition of equivalence.
  425. isIso : {A : Type} -> {B : Type} -> (A -> B) -> Type
  426. isIso {A} {B} f = (g : B -> A) * ((y : B) -> Path (f (g y)) y) * ((x : A) -> Path (g (f x)) x)
  427. -- The reason is that the family of types IsIso is not a proposition!
  428. -- This means that there can be more than one way for a function to be
  429. -- an equivalence. This is Lemma 4.1.1 of the HoTT book.
  430. Iso : Type -> Type -> Type
  431. Iso A B = (f : A -> B) * isIso f
  432. -- Nevertheless, we can prove that any function with an isomorphism
  433. -- structure has contractible fibers, using a cubical argument adapted
  434. -- from CCHM's implementation of cubical type theory:
  435. --
  436. -- https://github.com/mortberg/cubicaltt/blob/master/experiments/isoToEquiv.ctt#L7-L55
  437. IsoToEquiv : {A : Type} {B : Type} -> Iso A B -> Equiv A B
  438. IsoToEquiv {A} {B} iso = (f, \y -> (fCenter y, fIsCenter y)) where
  439. f = iso.1
  440. g = iso.2.1
  441. s = iso.2.2.1
  442. t = iso.2.2.2
  443. lemIso : (y : B) (x0 : A) (x1 : A) (p0 : Path y (f x0)) (p1 : Path y (f x1))
  444. -> PathP (\i -> fiber f y) (x0, p0) (x1, p1)
  445. lemIso y x0 x1 p0 p1 =
  446. let
  447. rem0 : Path x0 (g y)
  448. rem0 i = comp (\i -> A) (\k [ (i = i0) -> t x0 k, (i = i1) -> g y ]) (inS (g (p0 (inot i))))
  449. rem1 : Path x1 (g y)
  450. rem1 i = comp (\i -> A) (\k [ (i = i0) -> t x1 k, (i = i1) -> g y ]) (inS (g (p1 (inot i))))
  451. p : Path x0 x1
  452. p i = comp (\i -> A) (\k [ (i = i0) -> rem0 (inot k), (i = i1) -> rem1 (inot k) ]) (inS (g y))
  453. fill0 : I -> I -> A
  454. fill0 i j = comp (\i -> A) (\k [ (i = i0) -> t x0 (iand j k)
  455. , (i = i1) -> g y
  456. , (j = i0) -> g (p0 (inot i))
  457. ])
  458. (inS (g (p0 (inot i))))
  459. fill1 : I -> I -> A
  460. fill1 i j = comp (\i -> A) (\k [ (i = i0) -> t x1 (iand j k)
  461. , (i = i1) -> g y
  462. , (j = i0) -> g (p1 (inot i)) ])
  463. (inS (g (p1 (inot i))))
  464. fill2 : I -> I -> A
  465. fill2 i j = comp (\i -> A) (\k [ (i = i0) -> rem0 (ior j (inot k))
  466. , (i = i1) -> rem1 (ior j (inot k))
  467. , (j = i1) -> g y ])
  468. (inS (g y))
  469. sq : I -> I -> A
  470. sq i j = comp (\i -> A) (\k [ (i = i0) -> fill0 j (inot k)
  471. , (i = i1) -> fill1 j (inot k)
  472. , (j = i1) -> g y
  473. , (j = i0) -> t (p i) (inot k) ])
  474. (inS (fill2 i j))
  475. sq1 : I -> I -> B
  476. sq1 i j = comp (\i -> B) (\k [ (i = i0) -> s (p0 (inot j)) k
  477. , (i = i1) -> s (p1 (inot j)) k
  478. , (j = i0) -> s (f (p i)) k
  479. , (j = i1) -> s y k
  480. ])
  481. (inS (f (sq i j)))
  482. in \i -> (p i, \j -> sq1 i (inot j))
  483. fCenter : (y : B) -> fiber f y
  484. fCenter y = (g y, sym (s y))
  485. fIsCenter : (y : B) (w : fiber f y) -> Path (fCenter y) w
  486. fIsCenter y w = lemIso y (fCenter y).1 w.1 (fCenter y).2 w.2
  487. IsoToId : {A : Type} {B : Type} -> Iso A B -> Path A B
  488. IsoToId i = ua (IsoToEquiv i)
  489. -- We can prove that any involutive function is an isomorphism, since
  490. -- such a function is its own inverse.
  491. involToIso : {A : Type} (f : A -> A) -> ((x : A) -> Path (f (f x)) x) -> isIso f
  492. involToIso {A} f inv = (f, inv, inv)
  493. -- An example of ua
  494. ---------------------------
  495. --
  496. -- The classic example of ua is the equivalence
  497. -- not : Bool \simeq Bool.
  498. --
  499. -- We define it here.
  500. data Bool : Type where
  501. true : Bool
  502. false : Bool
  503. not : Bool -> Bool
  504. not = \case
  505. true -> false
  506. false -> true
  507. elimBool : (P : Bool -> Type) -> P true -> P false -> (b : Bool) -> P b
  508. elimBool P x y = \case
  509. true -> x
  510. false -> y
  511. if : {A : Type} -> A -> A -> Bool -> A
  512. if x y = \case
  513. true -> x
  514. false -> y
  515. -- By pattern matching it suffices to prove (not (not true)) ≡ true and
  516. -- not (not false) ≡ false. Since not (not true) computes to true (resp.
  517. -- false), both proofs go through by refl.
  518. notInvol : (x : Bool) -> Path (not (not x)) x
  519. notInvol = elimBool (\b -> Path (not (not b)) b) refl refl
  520. notp : Path Bool Bool
  521. notp = ua (IsoToEquiv (not, involToIso not notInvol))
  522. -- This path actually serves to prove a simple lemma about the universes
  523. -- of HoTT, namely, that any univalent universe is not a 0-type. If we
  524. -- had HITs, we could prove that this fact holds for any n, but for now,
  525. -- proving it's not an h-set is the furthest we can go.
  526. -- First we define what it means for something to be false. In type theory,
  527. -- we take ¬P = P → ⊥, where the Bottom type is the only type satisfying
  528. -- the elimination principle
  529. --
  530. -- elimBottom : (P : Bottom -> Type) -> (b : Bottom) -> P b
  531. --
  532. -- This follows from setting Bottom := ∀ A, A.
  533. data Bottom : Type where {}
  534. elimBottom : (P : Bottom -> Pretype) -> (b : Bottom) -> P b
  535. elimBottom P = \case {}
  536. absurd : {P : Pretype} -> Bottom -> P
  537. absurd = \case {}
  538. -- We prove that true != false by transporting along the path
  539. --
  540. -- \i -> if (Bool -> Bool) A (p i)
  541. -- (Bool -> Bool) ------------------------------------ A
  542. --
  543. -- To verify that this has the correct endpoints, check out the endpoints
  544. -- for p:
  545. --
  546. -- true ------------------------------------ false
  547. --
  548. -- and evaluate the if at either end.
  549. trueNotFalse : Path true false -> Bottom
  550. trueNotFalse p = transp (\i -> if (Bool -> Bool) Bottom (p i)) id
  551. -- To be an h-Set is to have no "higher path information". Alternatively,
  552. --
  553. -- isHSet A = (x : A) (y : A) -> isHProp (Path x y)
  554. --
  555. isProp : Type -> Type
  556. isProp A = (x : A) (y : A) -> Path x y
  557. isHSet : Type -> Type
  558. isHSet A = (x : A) (y : A) -> isProp (Path x y)
  559. -- We can prove *a* contradiction (note: this is a direct proof!) by adversarially
  560. -- choosing two paths p, q that we know are not equal. Since "equal" paths have
  561. -- equal behaviour when transporting, we can choose two paths p, q and a point x
  562. -- such that transporting x along p gives a different result from x along q.
  563. --
  564. -- Since transp notp = not but transp refl = id, that's what we go with. The choice
  565. -- of false as the point x is just from the endpoints of trueNotFalse.
  566. universeNotSet : isHSet Type -> Bottom
  567. universeNotSet itIs = trueNotFalse (\i -> transp (\j -> itIs Bool Bool notp refl i j) false)
  568. -- Funext is an inverse of happly
  569. ---------------------------------
  570. --
  571. -- Above we proved function extensionality, namely, that functions
  572. -- pointwise equal everywhere are themselves equal.
  573. -- However, this formulation of the axiom is known as "weak" function
  574. -- extensionality. The strong version is as follows:
  575. Hom : {A : Type} {B : A -> Type} (f : (x : A) -> B x) -> (g : (x : A) -> B x) -> Type
  576. Hom {A} f g = (x : A) -> Path (f x) (g x)
  577. happly : {A : Type} {B : A -> Type} {f : (x : A) -> B x} {g : (x : A) -> B x}
  578. -> (p : Path f g) -> Hom f g
  579. happly p x i = p i x
  580. -- Strong function extensionality: happly is an equivalence.
  581. happlyIsIso : {A : Type} {B : A -> Type} {f : (x : A) -> B x} {g : (x : A) -> B x}
  582. -> isIso {Path f g} {Hom f g} happly
  583. happlyIsIso {A} {B} {f} {g} = (funext {A} {B} {f} {g}, \hom -> refl, \path -> refl)
  584. pathIsHom : {A : Type} {B : A -> Type} {f : (x : A) -> B x} {g : (x : A) -> B x}
  585. -> Path (Path f g) (Hom f g)
  586. pathIsHom {A} {B} {f} {g} =
  587. let
  588. theIso : Iso (Path f g) (Hom f g)
  589. theIso = (happly {A} {B} {f} {g}, happlyIsIso {A} {B} {f} {g})
  590. in ua (IsoToEquiv theIso)
  591. -- Inductive types
  592. -------------------
  593. --
  594. -- An inductive type is a type freely generated by a finite set of
  595. -- constructors. For instance, the type of natural numbers is generated
  596. -- by the constructors for "zero" and "successor".
  597. data Nat : Type where
  598. zero : Nat
  599. succ : Nat -> Nat
  600. -- Pattern matching allows us to prove that these initial types are
  601. -- initial algebras for their corresponding functors.
  602. Nat_elim : (P : Nat -> Type) -> P zero -> ((x : Nat) -> P x -> P (succ x)) -> (x : Nat) -> P x
  603. Nat_elim P pz ps = \case
  604. zero -> pz
  605. succ x -> ps x (Nat_elim P pz ps x)
  606. zeroNotSucc : {x : Nat} -> Path zero (succ x) -> Bottom
  607. zeroNotSucc p = transp (\i -> fun (p i)) (p i0) where
  608. fun : Nat -> Type
  609. fun = \case
  610. zero -> Nat
  611. succ x -> Bottom
  612. succInj : {x : Nat} {y : Nat} -> Path (succ x) (succ y) -> Path x y
  613. succInj p i = pred (p i) where
  614. pred : Nat -> Nat
  615. pred = \case
  616. zero -> zero
  617. succ x -> x
  618. -- The type of integers can be defined as A + B, where "pos n" means +n
  619. -- and "neg n" means -(n + 1).
  620. data Int : Type where
  621. pos : Nat -> Int
  622. neg : Nat -> Int
  623. -- On this representation we can define the successor and predecessor
  624. -- functions by (nested) induction.
  625. sucZ : Int -> Int
  626. sucZ = \case
  627. pos n -> pos (succ n)
  628. neg n ->
  629. let suc_neg : Nat -> Int
  630. suc_neg = \case
  631. zero -> pos zero
  632. succ n -> neg n
  633. in suc_neg n
  634. predZ : Int -> Int
  635. predZ = \case
  636. pos n ->
  637. let pred_pos : Nat -> Int
  638. pred_pos = \case
  639. zero -> neg zero
  640. succ n -> pos n
  641. in pred_pos n
  642. neg n -> neg (succ n)
  643. -- And prove that the successor function is an isomorphism, and thus, an
  644. -- equivalence.
  645. sucPredZ : (x : Int) -> Path (sucZ (predZ x)) x
  646. sucPredZ = \case
  647. pos n ->
  648. let k : (n : Nat) -> Path (sucZ (predZ (pos n))) (pos n)
  649. k = \case
  650. zero -> refl
  651. succ n -> refl
  652. in k n
  653. neg n -> refl
  654. predSucZ : (x : Int) -> Path (predZ (sucZ x)) x
  655. predSucZ = \case
  656. pos n -> refl
  657. neg n ->
  658. let k : (n : Nat) -> Path (predZ (sucZ (neg n))) (neg n)
  659. k = \case
  660. zero -> refl
  661. succ n -> refl
  662. in k n
  663. sucEquiv : Equiv Int Int
  664. sucEquiv = IsoToEquiv (sucZ, (predZ, sucPredZ, predSucZ))
  665. -- Univalence gives us a path between integers such that transp intPath
  666. -- x = suc x, transp (sym intPath) x = pred x
  667. intPath : Path Int Int
  668. intPath = ua sucEquiv
  669. -- Higher inductive types
  670. -------------------------
  671. --
  672. -- While inductive types let us generate discrete spaces like the
  673. -- naturals or integers, they do not support defining higher-dimensional
  674. -- structures given by spaces with points and paths.
  675. -- A very simple higher inductive type is the interval, given by
  676. data Interval : Type where
  677. ii0 : Interval
  678. ii1 : Interval
  679. seg i : Interval [ (i = i0) -> ii0, (i = i1) -> ii1 ]
  680. -- This expresses that we have two points ii0 and ii1 and a path (\i ->
  681. -- seg i) with endpoints ii0 and ii1.
  682. -- With this type we can reproduce the proof of Lemma 6.3.2 from the
  683. -- HoTT book:
  684. iFunext : {A : Type} {B : A -> Type} (f : (x : A) -> B x) (g : (x : A) -> B x)
  685. -> ((x : A) -> Path (f x) (g x)) -> Path f g
  686. iFunext f g p i = h' (seg i) where
  687. h : (x : A) -> Interval -> B x
  688. h x = \case
  689. ii0 -> f x
  690. ii1 -> g x
  691. seg i -> p x i
  692. h' : Interval -> (x : A) -> B x
  693. h' i x = h x i
  694. -- Of course, Cubical Type Theory also has an interval (pre)type, but
  695. -- that, unlike the Interval here, is not Kan: it has no composition
  696. -- structure.
  697. -- Another simple higher-inductive type is the circle, with a point and
  698. -- a non-trivial loop, (\i -> loop i).
  699. data S1 : Type where
  700. base : S1
  701. loop i : S1 [ (i = i1) -> base, (i = i0) -> base ]
  702. -- By writing a function from the circle to the universe of types Type,
  703. -- we can calculate winding numbers along the circle.
  704. helix : S1 -> Type
  705. helix = \case
  706. base -> Int
  707. loop i -> intPath i
  708. loopP : Path base base
  709. loopP i = loop i
  710. winding : Path base base -> Int
  711. winding p = transp (\i -> helix (p i)) (pos zero)
  712. -- For instance, going around the loop once has a winding number of +1,
  713. windingLoop : Path (winding (\i -> loop i)) (pos (succ zero))
  714. windingLoop = refl
  715. -- Going backwards has a winding number of -1 (remember the
  716. -- representation of integers),
  717. windingSymLoop : Path (winding (\i -> loop (inot i))) (neg zero)
  718. windingSymLoop = refl
  719. -- And going around the trivial loop (\i -> base) goes around the the
  720. -- non-trivial loop (\i -> loop) zero times.
  721. windingBase : Path (winding (\i -> base)) (pos zero)
  722. windingBase = refl
  723. goAround : Int -> Path base base
  724. goAround =
  725. \case
  726. pos n -> forwards n
  727. neg n -> backwards n
  728. where
  729. forwards : Nat -> Path base base
  730. forwards = \case
  731. zero -> refl
  732. succ n -> trans (goAround (pos n)) (\i -> loop i)
  733. backwards : Nat -> Path base base
  734. backwards = \case
  735. zero -> \i -> loop (inot i)
  736. succ n -> trans (goAround (neg n)) (\i -> loop (inot i))
  737. windingGoAround : (n : Int) -> Path (winding (goAround n)) n
  738. windingGoAround =
  739. \case
  740. pos n -> posCase n
  741. neg n -> negCase n
  742. where
  743. posCase : (n : Nat) -> Path (winding (goAround (pos n))) (pos n)
  744. posCase = \case
  745. zero -> refl
  746. succ n -> ap sucZ (posCase n)
  747. negCase : (n : Nat) -> Path (winding (goAround (neg n))) (neg n)
  748. negCase = \case
  749. zero -> refl
  750. succ n -> ap predZ (negCase n)
  751. decodeSquare : (n : Int) -> PathP (\i -> Path base (loop i)) (goAround (predZ n)) (goAround n)
  752. decodeSquare = \case
  753. pos n -> posCase n
  754. neg n -> \i j -> hfill (\k [ (j = i1) -> loop (inot k), (j = i0) -> base ]) (inS (goAround (neg n) j)) (inot i)
  755. where
  756. posCase : (n : Nat) -> PathP (\i -> Path base (loop i)) (goAround (predZ (pos n))) (goAround (pos n))
  757. posCase = \case
  758. zero -> \i j -> loop (ior i (inot j))
  759. succ n -> \i j -> hfill (\k [ (j = i1) -> loop k, (j = i0) -> base ]) (inS (goAround (pos n) j)) i
  760. -- One particularly general higher inductive type is the homotopy pushout,
  761. -- which can be seen as a kind of sum B + C with the extra condition that
  762. -- whenever x and y are in the image of f (resp. g), inl x ≡ inr y.
  763. data Pushout {A : Type} {B : Type} {C : Type} (f : A -> B) (g : A -> C) : Type where
  764. inl : (x : B) -> Pushout f g
  765. inr : (y : C) -> Pushout f g
  766. push i : (a : A) -> Pushout f g [ (i = i0) -> inl (f a), (i = i1) -> inr (g a) ]
  767. -- The name is due to the category-theoretical notion of pushout.
  768. -- TODO: finish writing this tomorrow lol
  769. data Susp (A : Type) : Type where
  770. north : Susp A
  771. south : Susp A
  772. merid i : A -> Susp A [ (i = i0) -> north, (i = i1) -> south ]
  773. data Unit : Type where
  774. tt : Unit
  775. unitEta : (x : Unit) -> Path x tt
  776. unitEta = \case tt -> refl
  777. unitContr : isContr Unit
  778. unitContr = (tt, \x -> sym (unitEta x))
  779. poSusp : Type -> Type
  780. poSusp A = Pushout {A} {Unit} {Unit} (\x -> tt) (\x -> tt)
  781. Susp_is_poSusp : {A : Type} -> Path (Susp A) (poSusp A)
  782. Susp_is_poSusp {A} = ua (IsoToEquiv (Susp_to_poSusp {A}, poSusp_to_Susp {A}, poSusp_to_Susp_to_poSusp {A}, Susp_to_poSusp_to_Susp {A})) where
  783. poSusp_to_Susp : {A : Type} -> poSusp A -> Susp A
  784. poSusp_to_Susp = \case
  785. inl x -> north
  786. inr x -> south
  787. push x i -> merid x i
  788. Susp_to_poSusp : {A : Type} -> Susp A -> poSusp A
  789. Susp_to_poSusp = \case
  790. north -> inl tt
  791. south -> inr tt
  792. merid x i -> push x i
  793. Susp_to_poSusp_to_Susp : {A : Type} -> (x : Susp A) -> Path (poSusp_to_Susp (Susp_to_poSusp x)) x
  794. Susp_to_poSusp_to_Susp = \case
  795. north -> refl
  796. south -> refl
  797. merid x i -> refl
  798. poSusp_to_Susp_to_poSusp : {A : Type} -> (x : poSusp A) -> Path (Susp_to_poSusp (poSusp_to_Susp x)) x
  799. poSusp_to_Susp_to_poSusp {A} = \case
  800. inl x -> ap inl (sym (unitEta x))
  801. inr x -> ap inr (sym (unitEta x))
  802. push x i -> refl
  803. data T2 : Type where
  804. baseT : T2
  805. pathOne i : T2 [ (i = i0) -> baseT, (i = i1) -> baseT ]
  806. pathTwo i : T2 [ (i = i0) -> baseT, (i = i1) -> baseT ]
  807. square i j : T2 [
  808. (j = i0) -> pathTwo i,
  809. (j = i1) -> pathTwo i,
  810. (i = i0) -> pathOne j,
  811. (i = i1) -> pathOne j
  812. ]
  813. TorusIsTwoCircles : Path T2 (S1 * S1)
  814. TorusIsTwoCircles = ua (IsoToEquiv theIso) where
  815. torusToCircs : T2 -> S1 * S1
  816. torusToCircs = \case
  817. baseT -> (base, base)
  818. pathOne i -> (loop i, base)
  819. pathTwo i -> (base, loop i)
  820. square i j -> (loop i, loop j)
  821. circsToTorus : (S1 * S1) -> T2
  822. circsToTorus pair = go pair.1 pair.2
  823. where
  824. baseCase : S1 -> T2
  825. baseCase = \case
  826. base -> baseT
  827. loop j -> pathTwo j
  828. loopCase : Path baseCase baseCase
  829. loopCase i = \case
  830. base -> pathOne i
  831. loop j -> square i j
  832. go : S1 -> S1 -> T2
  833. go = \case
  834. base -> baseCase
  835. loop i -> loopCase i
  836. torusToCircsToTorus : (x : T2) -> Path (circsToTorus (torusToCircs x)) x
  837. torusToCircsToTorus = \case
  838. baseT -> refl
  839. pathOne i -> refl
  840. pathTwo i -> refl
  841. square i j -> refl
  842. circsToTorusToCircs : (p : S1 * S1) -> Path (torusToCircs (circsToTorus p)) p
  843. circsToTorusToCircs pair = go pair.1 pair.2 where
  844. baseCase : (y : S1) -> Path (torusToCircs (circsToTorus (base, y))) (base, y)
  845. baseCase = \case
  846. base -> refl
  847. loop j -> refl
  848. loopCase : (i : I) (y : S1) -> Path (torusToCircs (circsToTorus (loop i, y))) (loop i, y )
  849. loopCase i = \case
  850. base -> refl
  851. loop j -> refl
  852. go : (x : S1) (y : S1) -> Path (torusToCircs (circsToTorus (x, y))) (x, y)
  853. go = \case
  854. base -> baseCase
  855. loop i -> loopCase i
  856. theIso : Iso T2 (S1 * S1)
  857. theIso = (torusToCircs, circsToTorus, circsToTorusToCircs, torusToCircsToTorus)
  858. abs : Int -> Nat
  859. abs = \case
  860. pos n -> n
  861. neg n -> succ n
  862. sign : Int -> Bool
  863. sign = \case
  864. pos n -> true
  865. neg n -> false
  866. boolAnd : Bool -> Bool -> Bool
  867. boolAnd = \case
  868. true -> \case
  869. true -> true
  870. false -> false
  871. false -> \case
  872. true -> false
  873. false -> false
  874. plusNat : Nat -> Nat -> Nat
  875. plusNat = \case
  876. zero -> \x -> x
  877. succ n -> \x -> succ (plusNat n x)
  878. plusZero : (x : Nat) -> Path (plusNat zero x) x
  879. plusZero = \case
  880. zero -> refl
  881. succ n -> \i -> succ (plusZero n i)
  882. multNat : Nat -> Nat -> Nat
  883. multNat = \case
  884. zero -> \x -> zero
  885. succ n -> \x -> plusNat x (multNat n x)
  886. multInt : Int -> Int -> Int
  887. multInt x y = signify (multNat (abs x) (abs y)) (boolAnd (sign x) (sign y)) where
  888. signify : Nat -> Bool -> Int
  889. signify = \case
  890. zero -> \x -> pos zero
  891. succ n -> \case
  892. true -> pos (succ n)
  893. false -> neg n
  894. two : Int
  895. two = pos (succ (succ zero))
  896. four : Int
  897. four = multInt two two
  898. sixteen : Int
  899. sixteen = multInt four four
  900. Prop : Type
  901. Prop = (A : Type) * isProp A
  902. data Sq (A : Type) : Type where
  903. inc : A -> Sq A
  904. sq i : (x : Sq A) (y : Sq A) -> Sq A [ (i = i0) -> x, (i = i1) -> y ]
  905. isProp_isSet : {A : Type} -> isProp A -> isHSet A
  906. isProp_isSet h a b p q j i =
  907. hcomp {A}
  908. (\k [ (i = i0) -> h a a k
  909. , (i = i1) -> h a b k
  910. , (j = i0) -> h a (p i) k
  911. , (j = i1) -> h a (q i) k
  912. ])
  913. (inS a)
  914. isProp_isProp : {A : Type} -> isProp (isProp A)
  915. isProp_isProp f g i a b = isProp_isSet f a b (f a b) (g a b) i
  916. isProp_isContr : {A : Type} -> isProp (isContr A)
  917. isProp_isContr {A} z0 z1 j =
  918. ( z0.2 z1.1 j
  919. , \x i -> hcomp {A} (\k [ (i = i0) -> z0.2 z1.1 j
  920. , (i = i1) -> z0.2 x (ior j k)
  921. , (j = i0) -> z0.2 x (iand i k)
  922. , (j = i1) -> z1.2 x i ])
  923. (inS (z0.2 (z1.2 x i) j))
  924. )
  925. isContr_isProp : {A : Type} -> isContr A -> isProp A
  926. isContr_isProp x a b i = hcomp (\k [ (i = i0) -> x.2 a k, (i = i1) -> x.2 b k ]) (inS x.1)
  927. sigmaPath : {A : Type} {B : A -> Type} {s1 : (x : A) * B x} {s2 : (x : A) * B x}
  928. -> (p : Path s1.1 s2.1)
  929. -> PathP (\i -> B (p i)) s1.2 s2.2
  930. -> Path s1 s2
  931. sigmaPath p q i = (p i, q i)
  932. propExt : {A : Type} {B : Type}
  933. -> isProp A -> isProp B
  934. -> (A -> B)
  935. -> (B -> A)
  936. -> Equiv A B
  937. propExt {A} {B} propA propB f g = (f, contract) where
  938. contract : (y : B) -> isContr (fiber f y)
  939. contract y =
  940. let arg : A
  941. arg = g y
  942. in ( (arg, propB y (f arg))
  943. , \fib -> sigmaPath (propA _ _) (isProp_isSet {B} propB y (f fib.1) _ _))
  944. Sq_rec : {A : Type} {B : Type}
  945. -> isProp B
  946. -> (f : A -> B)
  947. -> Sq A -> B
  948. Sq_rec prop f =
  949. \case
  950. inc x -> f x
  951. sq x y i -> prop (work x) (work y) i
  952. where
  953. work : Sq A -> B
  954. work = \case
  955. inc x -> f x
  956. hitTranspExample : Path (inc false) (inc true)
  957. hitTranspExample i = transp (\i -> Sq (notp i)) (sq (inc true) (inc false) i)
  958. data S2 : Type where
  959. base2 : S2
  960. surf2 i j : S2 [ (i = i0) -> base2, (i = i1) -> base2, (j = i0) -> base2, (j = i1) -> base2]
  961. S2IsSuspS1 : Path S2 (Susp S1)
  962. S2IsSuspS1 = ua (IsoToEquiv iso) where
  963. toS2 : Susp S1 -> S2
  964. toS2 = \case { north -> base2; south -> base2; merid x i -> sphMerid x i } where
  965. sphMerid = \case
  966. base -> \i -> base2
  967. loop j -> \i -> surf2 i j
  968. suspSurf : I -> I -> I -> Susp S1
  969. suspSurf i j = hfill {Susp S1} (\k [ (i = i0) -> north
  970. , (i = i1) -> merid base (inot k)
  971. , (j = i0) -> merid base (iand (inot k) i)
  972. , (j = i1) -> merid {S1} base (iand (inot k) i)
  973. ])
  974. (inS (merid (loop j) i))
  975. fromS2 : S2 -> Susp S1
  976. fromS2 = \case { base2 -> north; surf2 i j -> suspSurf i j i1 }
  977. toFromS2 : (x : S2) -> Path (toS2 (fromS2 x)) x
  978. toFromS2 = \case { base2 -> refl; surf2 i j -> \k -> toS2 (suspSurf i j (inot k)) }
  979. fromToS2 : (x : Susp S1) -> Path (fromS2 (toS2 x)) x
  980. fromToS2 = \case { north -> refl; south -> \i -> merid base i; merid x i -> meridCase i x } where
  981. meridCase : (i : I) (x : S1) -> Path (fromS2 (toS2 (merid x i))) (merid x i)
  982. meridCase i = \case
  983. base -> \k -> merid base (iand i k)
  984. loop j -> \k -> suspSurf i j (inot k)
  985. iso : Iso S2 (Susp S1)
  986. iso = (fromS2, toS2, fromToS2, toFromS2)
  987. data S3 : Type where
  988. base3 : S3
  989. surf3 i j k : S3 [ (i = i0) -> base3, (i = i1) -> base3, (j = i0) -> base3, (j = i1) -> base3, (k = i0) -> base3, (k = i1) -> base3 ]
  990. S3IsSuspS2 : Path S3 (Susp S2)
  991. S3IsSuspS2 = ua (IsoToEquiv iso) where
  992. toS3 : Susp S2 -> S3
  993. toS3 = \case { north -> base3; south -> base3; merid x i -> sphMerid x i } where
  994. sphMerid = \case
  995. base2 -> \i -> base3
  996. surf2 j k -> \i -> surf3 i j k
  997. suspSurf : I -> I -> I -> I -> Susp S2
  998. suspSurf i j k = hfill {Susp S2} (\l [ (i = i0) -> north
  999. , (i = i1) -> merid base2 (inot l)
  1000. , (j = i0) -> merid base2 (iand (inot l) i)
  1001. , (j = i1) -> merid {S2} base2 (iand (inot l) i)
  1002. , (k = i0) -> merid base2 (iand (inot l) i)
  1003. , (k = i1) -> merid {S2} base2 (iand (inot l) i)
  1004. ])
  1005. (inS (merid (surf2 j k) i))
  1006. fromS3 : S3 -> Susp S2
  1007. fromS3 = \case { base3 -> north; surf3 i j k -> suspSurf i j k i1 }
  1008. toFromS3 : (x : S3) -> Path (toS3 (fromS3 x)) x
  1009. toFromS3 = \case { base3 -> refl; surf3 i j k -> \l -> toS3 (suspSurf i j k (inot l)) }
  1010. fromToS3 : (x : Susp S2) -> Path (fromS3 (toS3 x)) x
  1011. fromToS3 = \case { north -> refl; south -> \i -> merid base2 i; merid x i -> meridCase i x } where
  1012. meridCase : (i : I) (x : S2) -> Path (fromS3 (toS3 (merid x i))) (merid x i)
  1013. meridCase i = \case
  1014. base2 -> \k -> merid base2 (iand i k)
  1015. surf2 j k -> \l -> suspSurf i j k (inot l)
  1016. iso : Iso S3 (Susp S2)
  1017. iso = (fromS3, toS3, fromToS3, toFromS3)
  1018. ap_s : {A : Pretype} {B : Pretype} (f : A -> B) {x : A} {y : A} -> Eq_s x y -> Eq_s (f x) (f y)
  1019. ap_s {A} {B} f {x} {y} = J_s (\y p -> Eq_s (f x) (f y)) refl_s
  1020. subst_s : {A : Pretype} (P : A -> Pretype) {x : A} {y : A} -> Eq_s x y -> P x -> P y
  1021. subst_s {A} P {x} {z} p px = J_s {A} {x} (\y p -> P x -> P y) id p px
  1022. sym_s : {A : Pretype} {x : A} {y : A} -> Eq_s x y -> Eq_s y x
  1023. sym_s {A} {x} {y} = J_s {A} {x} (\y p -> Eq_s y x) refl_s
  1024. UIP : {A : Pretype} {x : A} {y : A} (p : Eq_s x y) (q : Eq_s x y) -> Eq_s p q
  1025. UIP {A} {x} {y} p q = J_s (\y p -> (q : Eq_s x y) -> Eq_s p q) (uipRefl A x) p q where
  1026. uipRefl : (A : Pretype) (x : A) (p : Eq_s x x) -> Eq_s refl_s p
  1027. uipRefl A x p = K_s {A} {x} (\q -> Eq_s refl_s q) refl_s p
  1028. strictEq_pathEq : {A : Type} {x : A} {y : A} -> Eq_s x y -> Path x y
  1029. strictEq_pathEq {A} {x} {y} eq = J_s {A} {x} (\y p -> Path x y) (\i -> x) {y} eq
  1030. seq_pathRefl : {A : Type} {x : A} (p : Eq_s x x) -> Eq_s (strictEq_pathEq p) (refl {A} {x})
  1031. seq_pathRefl {A} {x} p = K_s (\p -> Eq_s (strictEq_pathEq {A} {x} {x} p) (refl {A} {x})) refl_s p
  1032. Path_nat_strict_nat : (x : Nat) (y : Nat) -> Path x y -> Eq_s x y
  1033. Path_nat_strict_nat = \case { zero -> zeroCase; succ x -> succCase x } where
  1034. zeroCase : (y : Nat) -> Path zero y -> Eq_s zero y
  1035. zeroCase = \case
  1036. zero -> \p -> refl_s
  1037. succ x -> \p -> absurd (zeroNotSucc p)
  1038. succCase : (x : Nat) (y : Nat) -> Path (succ x) y -> Eq_s (succ x) y
  1039. succCase x = \case
  1040. zero -> \p -> absurd (zeroNotSucc (sym p))
  1041. succ y -> \p -> ap_s succ (Path_nat_strict_nat x y (succInj p))
  1042. pathToEqS_K : {A : Type} {x : A}
  1043. -> (s : {x : A} {y : A} -> Path x y -> Eq_s x y)
  1044. -> (P : Path x x -> Type) -> P refl -> (p : Path x x) -> P p
  1045. pathToEqS_K {A} {x} p_to_s P pr loop = transp (\i -> P (inv x loop i)) psloop where
  1046. psloop : P (strictEq_pathEq (p_to_s loop))
  1047. psloop = K_s (\l -> P (strictEq_pathEq {A} {x} {x} l)) pr (p_to_s {x} {x} loop)
  1048. inv : (y : A) (l : Path x y) -> Path (strictEq_pathEq (p_to_s l)) l
  1049. inv y l = J {A} {x} (\y l -> Path (strictEq_pathEq (p_to_s l)) l) (strictEq_pathEq aux) {y} l where
  1050. aux : Eq_s (strictEq_pathEq (p_to_s (\i -> x))) (\i -> x)
  1051. aux = seq_pathRefl (p_to_s (\i -> x))
  1052. pathToEq_isSet : {A : Type} -> ({x : A} {y : A} -> Path x y -> Eq_s x y) -> isHSet A
  1053. pathToEq_isSet {A} p_to_s = axK_to_isSet {A} (\{x} -> pathToEqS_K {A} {x} p_to_s) where
  1054. axK_to_isSet : {A : Type} -> ({x : A} -> (P : Path x x -> Type) -> P refl -> (p : Path x x) -> P p) -> isHSet A
  1055. axK_to_isSet K x y p q = J (\y p -> (q : Path x y) -> Path p q) (uipRefl x) p q where
  1056. uipRefl : (x : A) (p : Path x x) -> Path refl p
  1057. uipRefl x p = K {x} (\q -> Path refl q) refl p
  1058. Nat_isSet : isHSet Nat
  1059. Nat_isSet = pathToEq_isSet {Nat} (\{x} {y} -> Path_nat_strict_nat x y)
  1060. Bool_isSet : isHSet Bool
  1061. Bool_isSet = pathToEq_isSet {Bool} (\{x} {y} -> p x y) where
  1062. p : (x : Bool) (y : Bool) -> Path x y -> Eq_s x y
  1063. p = \case
  1064. true -> \case
  1065. true -> \p -> refl_s
  1066. false -> \p -> absurd (trueNotFalse p)
  1067. false -> \case
  1068. false -> \p -> refl_s
  1069. true -> \p -> absurd (trueNotFalse (sym p))
  1070. equivCtr : {A : Type} {B : Type} (e : Equiv A B) (y : B) -> fiber e.1 y
  1071. equivCtr e y = (e.2 y).1
  1072. equivCtrPath : {A : Type} {B : Type} (e : Equiv A B) (y : B)
  1073. -> (v : fiber e.1 y) -> Path (equivCtr e y) v
  1074. equivCtrPath e y = (e.2 y).2
  1075. contr : {A : Type} {phi : I} -> isContr A -> (u : Partial phi A) -> Sub A phi u
  1076. contr {A} {phi} p u = primComp (\i -> A) (\i [ (phi = i1) -> p.2 (u itIs1) i ]) (inS p.1)
  1077. contr' : {A : Type} -> ({phi : I} -> (u : Partial phi A) -> Sub A phi u) -> isContr A
  1078. contr' {A} contr = (x, \y i -> outS (contr (\ [ (i = i0) -> x, (i = i1) -> y ])) ) where
  1079. x : A
  1080. x = outS (contr (\ []))
  1081. leftIsOne : {a : I} {b : I} -> Eq_s a i1 -> Eq_s (ior a b) i1
  1082. leftIsOne {a} {b} p = J_s {I} {i1} (\i p -> IsOne (ior i b)) refl_s (sym_s p)
  1083. rightIsOne : {a : I} {b : I} -> Eq_s b i1 -> Eq_s (ior a b) i1
  1084. rightIsOne {a} {b} p = J_s {I} {i1} (\i p -> IsOne (ior a i)) refl_s (sym_s p)
  1085. bothAreOne : {a : I} {b : I} -> Eq_s a i1 -> Eq_s b i1 -> Eq_s (iand a b) i1
  1086. bothAreOne {a} {b} p q = J_s {I} {i1} (\i p -> IsOne (iand i b)) q (sym_s p)
  1087. S1Map_to_baseLoop : {X : Type} -> (S1 -> X) -> (a : X) * Path a a
  1088. S1Map_to_baseLoop {X} f = (f base, \i -> f (loop i))
  1089. baseLoop_to_S1Map : {X : Type} -> ((a : X) * Path a a) -> S1 -> X
  1090. baseLoop_to_S1Map {X} p = \case
  1091. base -> p.1
  1092. loop i -> p.2 i
  1093. S1_univ : {X : Type} -> Path (S1 -> X) ((a : X) * Path a a)
  1094. S1_univ = IsoToId {S1 -> X} {(a : X) * Path a a} (S1Map_to_baseLoop, baseLoop_to_S1Map, ret, sec) where
  1095. to = S1Map_to_baseLoop
  1096. fro = baseLoop_to_S1Map
  1097. sec : {X : Type} -> (f : S1 -> X) -> Path (fro (to f)) f
  1098. sec {X} f = funext {S1} {\s -> X} {\x -> fro (to f) x} {f} h where
  1099. h : (x : S1) -> Path (fro (to f) x) (f x)
  1100. h = \case
  1101. base -> refl
  1102. loop i -> refl
  1103. ret : {X : Type} -> (x : (a : X) * Path a a) -> Path (to (fro x)) x
  1104. ret x = refl
  1105. -- HoTT book lemma 8.9.1
  1106. encodeDecode : {A : Type} {a0 : A}
  1107. -> (code : A -> Type)
  1108. -> (c0 : code a0)
  1109. -> (decode : (x : A) -> code x -> (Path a0 x))
  1110. -> ((c : code a0) -> Path (transp (\i -> code (decode a0 c i)) c0) c)
  1111. -> Path (decode a0 c0) refl
  1112. -> Path (Path a0 a0) (code a0)
  1113. encodeDecode code c0 decode encDec based = IsoToId (encode {a0}, decode _, encDec, decEnc) where
  1114. encode : {x : A} -> Path a0 x -> code x
  1115. encode alpha = transp (\i -> code (alpha i)) c0
  1116. encodeRefl : Path (encode refl) c0
  1117. encodeRefl = sym (transpFill {\i -> code a0} c0)
  1118. decEnc : {x : A} (p : Path a0 x) -> Path (decode _ (encode p)) p
  1119. decEnc p = J (\x p -> Path (decode _ (encode p)) p) q p where
  1120. q : Path (decode _ (encode refl)) refl
  1121. q = transp (\i -> Path (decode _ (encodeRefl (inot i))) refl) based
  1122. S1_elim : (P : S1 -> Type)
  1123. -> (pb : P base)
  1124. -> PathP (\i -> P (loop i)) pb pb
  1125. -> (x : S1) -> P x
  1126. S1_elim P pb pq = \case
  1127. base -> pb
  1128. loop i -> pq i
  1129. 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)
  1130. PathP_is_Path P p q i = PathP (\j -> P (ior i j)) (transpFill {\j -> P j} p i) q
  1131. Constant : {A : Type} {B : Type} -> (A -> B) -> Type
  1132. Constant f = (y : B) * (x : A) -> Path y (f x)
  1133. Weakly : {A : Type} {B : Type} -> (A -> B) -> Type
  1134. Weakly f = (x : A) (y : A) -> Path (f x) (f y)
  1135. Conditionally : {A : Type} {B : Type} -> (A -> B) -> Type
  1136. Conditionally f = (f' : Sq A -> B) * Path f (\x -> f' (inc x))
  1137. Constant_weakly : {A : Type} {B : Type} (f : A -> B) -> Constant f -> Weakly f
  1138. Constant_weakly f p x y = trans (sym (p.2 x)) (p.2 y)
  1139. Constant_conditionally : {A : Type} {B : Type} -> (f : A -> B) -> Constant f -> Conditionally f
  1140. Constant_conditionally {A} {B} f p = transp (\i -> Conditionally (c_const (inot i))) (const_c p.1) where
  1141. c_const : Path f (\y -> p.1)
  1142. c_const i x = p.2 x (inot i)
  1143. const_c : (y : B) -> Conditionally {A} (\x -> y)
  1144. const_c y = (\x -> y, refl)
  1145. S1_connected : (f : S1 -> Bool) -> Constant f
  1146. S1_connected f = (f'.1, p) where
  1147. f' : (x : Bool) * Path x x
  1148. f' = S1Map_to_baseLoop f
  1149. p : (y : S1) -> Path f'.1 (f y)
  1150. p = S1_elim P refl loopc where
  1151. P : S1 -> Type
  1152. P = \y -> Path f'.1 (f y)
  1153. rr = refl {Bool} {f base}
  1154. loopc : PathP (\i -> P (loop i)) rr rr
  1155. loopc = transp (\i -> PathP_is_Path (\i -> P (loop i)) rr rr (inot i))
  1156. (Bool_isSet _ _ rr (transp (\i -> P (loop i)) rr))
  1157. isProp_isEquiv : {A : Type} {B : Type} {f : A -> B} -> isProp (isEquiv f)
  1158. isProp_isEquiv {f} p q i y =
  1159. let
  1160. p2 = (p y).2
  1161. q2 = (q y).2
  1162. in
  1163. ( p2 (q y).1 i
  1164. , \w j -> hcomp (\k [ (i = i0) -> p2 w j
  1165. , (i = i1) -> q2 w (ior j (inot k))
  1166. , (j = i0) -> p2 (q2 w (inot k)) i
  1167. , (j = i1) -> w ])
  1168. (inS (p2 w (ior i j)))
  1169. )
  1170. isProp_EqvSq : {P : Type} (x : Equiv P (Sq P)) (y : Equiv P (Sq P)) -> Path x y
  1171. 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
  1172. x1_is_y1 : Path x.1 y.1
  1173. x1_is_y1 i e = sq (x.1 e) (y.1 e) i
  1174. equivLemma : {A : Type} {B : Type} {e : Equiv A B} {e' : Equiv A B}
  1175. -> Path e.1 e'.1
  1176. -> Path e e'
  1177. equivLemma {A} {B} {e} {e'} p = sigmaPath p (isProp_isEquiv {A} {B} {e'.1} (transp (\i -> isEquiv (p i)) e.2) e'.2)
  1178. isProp_to_Sq_equiv : {P : Type} -> isProp P -> Equiv P (Sq P)
  1179. isProp_to_Sq_equiv {P} prop = propExt prop sqProp inc proj where
  1180. proj : Sq P -> P
  1181. proj = Sq_rec prop (\x -> x)
  1182. sqProp : isProp (Sq P)
  1183. sqProp x y i = sq x y i
  1184. Sq_equiv_to_isProp : {P : Type} -> Equiv P (Sq P) -> isProp P
  1185. Sq_equiv_to_isProp eqv = transp (\i -> isProp (ua eqv (inot i))) (\x y i -> sq x y i)
  1186. exercise_3_21 : {P : Type} -> Equiv (isProp P) (Equiv P (Sq P))
  1187. exercise_3_21 {P} = propExt (isProp_isProp {P}) (isProp_EqvSq {P}) isProp_to_Sq_equiv Sq_equiv_to_isProp
  1188. uaret : {A : Type} {B : Type} -> retract {Equiv A B} {Path A B} (ua {A} {B}) (idToEquiv {A} {B})
  1189. uaret eqv = equivLemma (uaBeta eqv)
  1190. f1 : {A : Type} -> (p : (B : Type) * Equiv A B) -> (B : Type) * Path A B
  1191. f1 {A} p = (p.1, ua p.2)
  1192. f2 : {A : Type} -> (p : (B : Type) * Path A B) -> (B : Type) * Equiv A B
  1193. f2 {A} p = (p.1, idToEquiv p.2)
  1194. uaretSig : {A : Type} (a : (B : Type) * Equiv A B) -> Path (f2 (f1 a)) a
  1195. uaretSig {A} p = sigmaPath (\i -> p.1) (uaret {A} {p.1} p.2)
  1196. isContrRetract : {A : Type} {B : Type}
  1197. -> (f : A -> B) -> (g : B -> A)
  1198. -> (h : retract f g)
  1199. -> isContr B -> isContr A
  1200. isContrRetract {A} {B} f g h v = (g b, p) where
  1201. b = v.1
  1202. p : (x : A) -> Path (g b) x
  1203. p x i = comp (\i -> A) (\j [ (i = i0) -> g b, (i = i1) -> h x j ]) (inS (g (v.2 (f x) i)))
  1204. curry : {A : Type} {B : A -> Type} {C : (x : A) -> B x -> Type}
  1205. -> Path ((x : A) (y : B x) -> C x y) ((p : (x : A) * B x) -> C p.1 p.2)
  1206. curry {A} {B} {C} = IsoToId (to, from, \f -> refl, \g -> refl) where
  1207. to : ((x : A) (y : B x) -> C x y) -> (p : (x : A) * B x) -> C p.1 p.2
  1208. to f p = f p.1 p.2
  1209. from : ((p : (x : A) * B x) -> C p.1 p.2) -> (x : A) (y : B x) -> C x y
  1210. from f x y = f (x, y)
  1211. ContractibleIfInhabited : {A : Type} -> Path (A -> isContr A) (isProp A)
  1212. ContractibleIfInhabited {A} = IsoToId (to, from, toFrom, fromTo) where
  1213. to : (A -> isContr A) -> isProp A
  1214. to cont x y = trans (sym (p.2 x)) (p.2 y) where
  1215. p = cont x
  1216. from : isProp A -> A -> isContr A
  1217. from prop x = (x, prop x)
  1218. toFrom : (y : isProp A) -> Path (to (from y)) y
  1219. toFrom y = isProp_isProp {A} (to (from y)) y
  1220. fromTo : (y : A -> isContr A) -> Path (from (to y)) y
  1221. fromTo y i a = isProp_isContr {A} (from (to y) a) (y a) i
  1222. data cone (A : Type) : Type where
  1223. point : cone A
  1224. base : A -> cone A
  1225. side i : (x : A) -> cone A [ (i = i0) -> point, (i = i1) -> base x ]
  1226. ConeA_contr : {A : Type} -> isContr (cone A)
  1227. ConeA_contr {A} = (point, contr) where
  1228. contr : (y : cone A) -> Path point y
  1229. contr = \case
  1230. point -> refl
  1231. base x -> \i -> side x i
  1232. side x i -> \j -> side x (iand i j)
  1233. contrSinglEquiv : {B : Type} -> isContr ((A : Type) * Equiv A B)
  1234. contrSinglEquiv {B} = (center, contract) where
  1235. center : (A : Type) * Equiv A B
  1236. center = (B, idEquiv)
  1237. contract : (p : (A : Type) * Equiv A B) -> Path center p
  1238. contract w i =
  1239. let
  1240. sys : Partial (ior (inot i) i) ((A : Type) * Equiv A B)
  1241. sys = \ [ (i = i0) -> center, (i = i1) -> w ]
  1242. GlueB = Glue B sys
  1243. unglueB : GlueB -> B
  1244. unglueB x = unglue {B} (ior (inot i) i) {sys} x
  1245. unglueEquiv : isEquiv {GlueB} {B} unglueB
  1246. unglueEquiv b =
  1247. let
  1248. ctr : fiber unglueB b
  1249. ctr = ( glue {B} {ior (inot i) i} {sys} (\[ (i = i0) -> b, (i = i1) -> (w.2.2 b).1.1 ])
  1250. (primComp (\i -> B) (\j [ (i = i0) -> b, (i = i1) -> (w.2.2 b).1.2 j ]) (inS b))
  1251. , fill (\i -> B) (\j [ (i = i0) -> b, (i = i1) -> (w.2.2 b).1.2 j ]) (inS b))
  1252. contr : (v : fiber unglueB b) -> Path ctr v
  1253. contr v j = ( glue {B} {ior (inot i) i} {sys}
  1254. (\[ (i = i0) -> v.2 j, (i = i1) -> ((w.2.2 b).2 v j).1 ])
  1255. (inS (comp (\i -> B)
  1256. (\k [ (i = i0) -> v.2 (iand j k)
  1257. , (i = i1) -> ((w.2.2 b).2 v j).2 k
  1258. , (j = i0) -> fill (\j -> B) (\k [ (i = i0) -> b, (i = i1) -> (w.2.2 b).1.2 k ]) (inS b) k
  1259. , (j = i1) -> v.2 k
  1260. ])
  1261. (inS b)))
  1262. , fill (\j -> B) (\k [ (i = i0) -> v.2 (iand j k)
  1263. , (i = i1) -> ((w.2.2 b).2 v j).2 k
  1264. , (j = i0) -> fill (\j -> B) (\k [ (i = i0) -> b, (i = i1) -> (w.2.2 b).1.2 k ]) (inS b) k
  1265. , (j = i1) -> v.2 k
  1266. ])
  1267. (inS b)
  1268. )
  1269. in (ctr, contr)
  1270. in (GlueB, unglueB, unglueEquiv)
  1271. uaIdEquiv : {A : Type} -> Path (ua idEquiv) (\i -> A)
  1272. uaIdEquiv {A} i j = Glue A {ior i (ior (inot j) j)} (\o -> (A, idEquiv))
  1273. EquivJ : (P : (X : Type) (Y : Type) -> Equiv X Y -> Type)
  1274. -> ((X : Type) -> P X X idEquiv)
  1275. -> {X : Type} {Y : Type} (E : Equiv X Y)
  1276. -> P X Y E
  1277. EquivJ P p {X} {Y} E =
  1278. subst {(X : Type) * Equiv X Y}
  1279. (\x -> P x.1 Y x.2)
  1280. (\i -> isContr_isProp contrSinglEquiv (Y, idEquiv) (X, E) i)
  1281. (p Y)
  1282. pathToEquiv : {A : Type} {B : Type} -> Path A B -> Equiv A B
  1283. pathToEquiv {A} {B} = J {Type} {A} (\B p -> Equiv A B) idEquiv
  1284. univalence : {A : Type} {B : Type} -> Equiv (Path A B) (Equiv A B)
  1285. univalence = IsoToEquiv (pathToEquiv, ua, pathToEquiv_ua, ua_pathToEquiv) where
  1286. pathToEquiv_refl : {A : Type} -> Path (pathToEquiv (refl {Type} {A})) idEquiv
  1287. pathToEquiv_refl {A} = JRefl (\B p -> Equiv A B) idEquiv
  1288. ua_pathToEquiv : {A : Type} {B : Type} (p : Path A B) -> Path (ua (pathToEquiv p)) p
  1289. ua_pathToEquiv {A} {B} p = J {Type} {A} (\B p -> Path (ua {A} {B} (pathToEquiv {A} {B} p)) p) lemma p where
  1290. lemma : Path (ua (pathToEquiv (\i -> A))) (\i -> A)
  1291. lemma = transp (\i -> Path (ua (pathToEquiv_refl {A} (inot i))) (\i -> A)) uaIdEquiv
  1292. pathToEquiv_ua : {A : Type} {B : Type} (p : Equiv A B) -> Path (pathToEquiv (ua p)) p
  1293. pathToEquiv_ua {A} {B} p = EquivJ (\A B e -> Path (pathToEquiv (ua e)) e) lemma p where
  1294. lemma : (A : Type) -> Path (pathToEquiv (ua idEquiv)) idEquiv
  1295. lemma A = transp (\i -> Path (pathToEquiv (uaIdEquiv {A} (inot i))) idEquiv) pathToEquiv_refl
  1296. total : {A : Type} {P : A -> Type} {Q : A -> Type}
  1297. -> ((x : A) -> P x -> Q x)
  1298. -> ((x : A) * P x) -> ((x : A) * Q x)
  1299. total f p = (p.1, f p.1 p.2)
  1300. total_fibers : {A : Type} {P : A -> Type} {Q : A -> Type}
  1301. -> {xv : (a : A) * Q a}
  1302. -> (f : (el : A) -> P el -> Q el)
  1303. -> Iso (fiber (total f) xv) (fiber (f xv.1) xv.2)
  1304. total_fibers {A} {P} {Q} {xv} f = (to, fro, toFro {xv}, froTo) where
  1305. to : {xv : (a : A) * Q a} -> fiber (total f) xv -> fiber (f xv.1) xv.2
  1306. to peq = J {(a : A) * Q a} {_} (\xv eq -> fiber (f xv.1) xv.2) (peq.1.2, refl) (sym peq.2)
  1307. fro : {xv : (a : A) * Q a} -> fiber (f xv.1) xv.2 -> fiber (total f) xv
  1308. fro peq = ((xv.1, peq.1), \i -> (_, peq.2 i))
  1309. toFro : {xv : (a : A) * Q a} -> (y : fiber (f xv.1) xv.2) -> Path (to (fro y)) y
  1310. toFro {xv} peq =
  1311. J {Q xv.1} {f xv.1 p}
  1312. (\xv1 eq1 -> Path (to {(xv.1, xv1)} (fro (p, sym eq1))) (p, sym eq1))
  1313. (JRefl {(a : A) * Q a} {(xv.1, f xv.1 peq.1)}
  1314. (\xv1 eq1 -> fiber (f xv1.1) xv1.2) (p, refl))
  1315. (sym eq)
  1316. where p : P xv.1
  1317. p = peq.1
  1318. eq : Path {Q xv.1} xv.2 (f xv.1 p)
  1319. eq = peq.2
  1320. froTo : {xv : (a : A) * Q a} -> (y : fiber (total f) xv) -> Path (fro {xv} (to {xv} y)) y
  1321. froTo {xv} apeq =
  1322. J {(a : A) * Q a} {total f (a, p)}
  1323. (\xv1 eq1 -> Path (fro {_} (to {_} ((a, p), sym eq1))) ((a, p), sym eq1))
  1324. (ap fro (JRefl {(a : A) * Q a} {(a, _)}
  1325. (\xv1 eq1 -> fiber (f xv1.1) xv1.2) (p, refl)))
  1326. (sym eq)
  1327. where a : A
  1328. a = apeq.1.1
  1329. p : P a
  1330. p = apeq.1.2
  1331. eq : Path xv (total f (a, p))
  1332. eq = apeq.2
  1333. fiberEquiv : {A : Type} {P : A -> Type} {Q : A -> Type}
  1334. -> (f : (el : A) -> P el -> Q el)
  1335. -> isEquiv (total f)
  1336. -> (x : A) -> isEquiv (f x)
  1337. 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
  1338. eqv : Iso (fiber (total f) (x, y)) (fiber (f x) y)
  1339. eqv = total_fibers f
  1340. totalEquiv : {A : Type} {P : A -> Type} {Q : A -> Type}
  1341. -> (f : (el : A) -> P el -> Q el)
  1342. -> ((x : A) -> isEquiv (f x))
  1343. -> isEquiv (total f)
  1344. totalEquiv f iseqv xv = isContrRetract {fiber (total f) xv} {fiber (f xv.1) xv.2} eqv.1 eqv.2.1 eqv.2.2.2 (iseqv xv.1 xv.2) where
  1345. eqv : Iso (fiber (total f) xv) (fiber (f xv.1) xv.2)
  1346. eqv = total_fibers f
  1347. contrIsEquiv : {A : Type} {B : Type} -> isContr A -> isContr B
  1348. -> (f : A -> B) -> isEquiv f
  1349. contrIsEquiv cA cB f y = ((cA.1, isContr_isProp cB _ _), \v -> sigmaPath (isContr_isProp cA _ _) (isProp_isSet (isContr_isProp cB) _ _ _ v.2))
  1350. theorem722 : {A : Type} {R : A -> A -> Type}
  1351. -> ((x : A) (y : A) -> isProp (R x y))
  1352. -> ({x : A} -> R x x)
  1353. -> (f : (x : A) (y : A) -> R x y -> Path x y)
  1354. -> {x : A} {y : A} -> isEquiv {R x y} {Path x y} (f x y)
  1355. theorem722 {A} {R} prop rho toId {x} {y} = fiberEquiv {A} {R x} {Path x} (toId x) (totalEquiv x) y where
  1356. rContr : (x : A) -> isContr ((y : A) * R x y)
  1357. rContr x = ((x, rho {x}), \y -> sigmaPath (toId _ _ y.2) (prop _ _ _ y.2))
  1358. totalEquiv : (x : A) -> isEquiv (total {A} {R x} {Path x} (toId x))
  1359. totalEquiv x = contrIsEquiv (rContr x) singContr (total {A} {R x} {Path x} (toId x))