cubical.lagda.rst 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027
  1. ..
  2. ::
  3. {-# OPTIONS --cubical #-}
  4. module language.cubical where
  5. open import Agda.Primitive
  6. open import Agda.Primitive.Cubical
  7. renaming ( primIMin to _∧_
  8. ; primIMax to _∨_
  9. ; primINeg to ~_
  10. ; primHComp to hcomp
  11. ; primTransp to transp
  12. ; itIsOne to 1=1 )
  13. open import Agda.Builtin.Cubical.Path
  14. open import Agda.Builtin.Cubical.Sub
  15. renaming ( primSubOut to outS
  16. ; inc to inS
  17. )
  18. open import Agda.Builtin.Cubical.Glue public
  19. using ( isEquiv
  20. ; equiv-proof
  21. ; _≃_
  22. ; primGlue )
  23. open import Agda.Builtin.Sigma public
  24. open import Agda.Builtin.Bool public
  25. infix 2 Σ-syntax
  26. Σ-syntax : ∀ {ℓ ℓ'} (A : Set ℓ) (B : A → Set ℓ') → Set (ℓ ⊔ ℓ')
  27. Σ-syntax = Σ
  28. syntax Σ-syntax A (λ x → B) = Σ[ x ∈ A ] B
  29. _×_ : ∀ {ℓ ℓ'} (A : Set ℓ) (B : Set ℓ') → Set (ℓ ⊔ ℓ')
  30. A × B = Σ A (λ _ → B)
  31. infixr 5 _×_
  32. .. _cubical:
  33. *******
  34. Cubical
  35. *******
  36. The Cubical mode extends Agda with a variety of features from Cubical
  37. Type Theory. In particular, computational univalence and higher
  38. inductive types which hence gives computational meaning to `Homotopy
  39. Type Theory and Univalent Foundations
  40. <https://homotopytypetheory.org/>`_. The version of Cubical Type
  41. Theory that Agda implements is a variation of the `CCHM`_ Cubical Type
  42. Theory where the Kan composition operations are decomposed into
  43. homogeneous composition and generalized transport. This is what makes
  44. the general schema for higher inductive types work, following the
  45. `CHM`_ paper.
  46. To use the cubical mode Agda needs to be run with the
  47. :option:`--cubical` command-line-option or with ``{-#
  48. OPTIONS --cubical #-}`` at the top of the file. There is also a
  49. variant of the cubical mode, activated using
  50. :option:`--erased-cubical`, which is described
  51. :ref:`below<erased-cubical>`.
  52. The cubical mode adds the following features to Agda:
  53. 1. An interval type and path types
  54. 2. Generalized transport (``transp``)
  55. 3. Partial elements
  56. 4. Homogeneous composition (``hcomp``)
  57. 5. Glue types
  58. 6. Higher inductive types
  59. 7. Cubical identity types
  60. There is a standard ``agda/cubical`` library for Cubical Agda
  61. available at https://github.com/agda/cubical. This documentation uses
  62. the naming conventions of this library, for a detailed list of all of
  63. the built-in Cubical Agda files and primitives see
  64. :ref:`primitives-ref`. The main design choices of the core part of the
  65. library are explained in
  66. https://homotopytypetheory.org/2018/12/06/cubical-agda/
  67. (lagda rendered version:
  68. https://ice1000.org/2018/12-06-CubicalAgda.html).
  69. The recommended way to get access to the Cubical primitives is to add
  70. the following to the top of a file (this assumes that the
  71. ``agda/cubical`` library is installed and visible to Agda).
  72. .. code-block:: agda
  73. {-# OPTIONS --cubical #-}
  74. open import Cubical.Core.Everything
  75. For detailed install instructions for ``agda/cubical`` see:
  76. https://github.com/agda/cubical/blob/master/INSTALL.md. In order to
  77. make this library visible to Agda add
  78. ``/path/to/cubical/cubical.agda-lib`` to ``.agda/libraries`` and
  79. ``cubical`` to ``.agda/defaults`` (where ``path/to`` is the absolute
  80. path to where the ``agda/cubical`` library has been installed). For
  81. details of Agda's library management see :ref:`package-system`.
  82. Expert users who do not want to rely on ``agda/cubical`` can just add
  83. the relevant import statements at the top of their file (for details
  84. see :ref:`primitives-ref`). However, for beginners it is
  85. recommended that one uses at least the core part of the
  86. ``agda/cubical`` library.
  87. There is also an older version of the library available at
  88. https://github.com/Saizan/cubical-demo/. However this is relying on
  89. deprecated features and is not recommended to use.
  90. The interval and path types
  91. ---------------------------
  92. The key idea of Cubical Type Theory is to add an interval type ``I :
  93. IUniv`` (the reason this is in a special sort ``IUniv`` is because it
  94. doesn't support the ``transp`` and ``hcomp`` operations). A variable
  95. ``i : I`` intuitively corresponds to a point in the `real unit interval
  96. <https://en.wikipedia.org/wiki/Unit_interval>`_. In an empty context,
  97. there are only two values of type ``I``: the two endpoints of the
  98. interval, ``i0`` and ``i1``.
  99. .. code-block:: agda
  100. i0 : I
  101. i1 : I
  102. Elements of the interval form a `De Morgan algebra
  103. <https://en.wikipedia.org/wiki/De_Morgan_algebra>`_, with minimum
  104. (``∧``), maximum (``∨``) and negation (``~``).
  105. .. code-block:: agda
  106. _∧_ : I → I → I
  107. _∨_ : I → I → I
  108. ~_ : I → I
  109. All the properties of De Morgan algebras hold definitionally. The
  110. endpoints of the interval ``i0`` and ``i1`` are the bottom and top
  111. elements, respectively.
  112. .. code-block:: agda
  113. i0 ∨ i = i
  114. i ∨ i1 = i1
  115. i ∨ j = j ∨ i
  116. i0 ∧ i = i0
  117. i1 ∧ i = i
  118. i ∧ j = j ∧ i
  119. ~ (~ i) = i
  120. i0 = ~ i1
  121. ~ (i ∨ j) = ~ i ∧ ~ j
  122. ~ (i ∧ j) = ~ i ∨ ~ j
  123. The core idea of Homotopy Type Theory and Univalent Foundations is a
  124. correspondence between paths (as in topology) and (proof-relevant)
  125. equalities (as in Martin-Löf's identity type). This correspondence is
  126. taken very literally in Cubical Agda where a path in a type ``A`` is
  127. represented like a function out of the interval, ``I → A``. A
  128. path type is in fact a special case of the more general built-in
  129. heterogeneous path types:
  130. ::
  131. -- PathP : ∀ {ℓ} (A : I → Set ℓ) → A i0 → A i1 → Set ℓ
  132. -- Non dependent path types
  133. Path : ∀ {ℓ} (A : Set ℓ) → A → A → Set ℓ
  134. Path A a b = PathP (λ _ → A) a b
  135. The central notion of equality in Cubical Agda is hence heterogeneous
  136. equality (in the sense of ``PathOver`` in HoTT). To define paths we
  137. use λ-abstractions and to apply them we use regular application. For
  138. example, this is the definition of the constant path (or proof of
  139. reflexivity):
  140. ::
  141. refl : ∀ {ℓ} {A : Set ℓ} {x : A} → Path A x x
  142. refl {x = x} = λ i → x
  143. Although they use the same syntax, a path is not exactly the same as a
  144. function. For example, the following is not valid:
  145. .. code-block:: agda
  146. refl : ∀ {ℓ} {A : Set ℓ} {x : A} → Path A x x
  147. refl {x = x} = λ (i : I) → x
  148. Because of the intuition that paths correspond to equality ``PathP (λ
  149. i → A) x y`` gets printed as ``x ≡ y`` when ``A`` does not mention
  150. ``i``. By iterating the path type we can define squares, cubes, and
  151. higher cubes in Agda, making the type theory cubical. For example a
  152. square in ``A`` is built out of 4 points and 4 lines:
  153. ::
  154. Square : ∀ {ℓ} {A : Set ℓ} {x0 x1 y0 y1 : A} →
  155. x0 ≡ x1 → y0 ≡ y1 → x0 ≡ y0 → x1 ≡ y1 → Set ℓ
  156. Square p q r s = PathP (λ i → p i ≡ q i) r s
  157. Viewing equalities as functions out of the interval makes it possible
  158. to do a lot of equality reasoning in a very direct way:
  159. ::
  160. sym : ∀ {ℓ} {A : Set ℓ} {x y : A} → x ≡ y → y ≡ x
  161. sym p = λ i → p (~ i)
  162. cong : ∀ {ℓ} {A : Set ℓ} {x y : A} {B : A → Set ℓ} (f : (a : A) → B a) (p : x ≡ y)
  163. → PathP (λ i → B (p i)) (f x) (f y)
  164. cong f p i = f (p i)
  165. Because of the way functions compute these satisfy some new
  166. definitional equalities compared to the standard Agda definitions:
  167. ::
  168. symInv : ∀ {ℓ} {A : Set ℓ} {x y : A} (p : x ≡ y) → sym (sym p) ≡ p
  169. symInv p = refl
  170. congId : ∀ {ℓ} {A : Set ℓ} {x y : A} (p : x ≡ y) → cong (λ a → a) p ≡ p
  171. congId p = refl
  172. congComp : ∀ {ℓ} {A B C : Set ℓ} (f : A → B) (g : B → C) {x y : A} (p : x ≡ y) →
  173. cong (λ a → g (f a)) p ≡ cong g (cong f p)
  174. congComp f g p = refl
  175. Path types also lets us prove new things are not provable in standard
  176. Agda, for example function extensionality (pointwise equal functions
  177. are equal) has an extremely simple proof:
  178. ::
  179. funExt : ∀ {ℓ} {A : Set ℓ} {B : A → Set ℓ} {f g : (x : A) → B x} →
  180. ((x : A) → f x ≡ g x) → f ≡ g
  181. funExt p i x = p x i
  182. Transport
  183. ---------
  184. While path types are great for reasoning about equality they don't let
  185. us transport along paths between types or even compose paths, which in
  186. particular means that we cannot yet prove the induction principle for
  187. paths. In order to remedy this we also have a built-in (generalized)
  188. transport operation `transp` and homogeneous composition operations `hcomp`. The
  189. transport operation is generalized in the sense that it lets us
  190. specify where it is the identity function.
  191. .. code-block:: agda
  192. transp : ∀ {ℓ} (A : I → Set ℓ) (r : I) (a : A i0) → A i1
  193. There is an additional side condition to be satisfied for a usage of ``transp`` to type-check: ``A`` should be a constant function whenever the constraint ``r = i1`` is satisfied. By constant here we mean that ``A`` is definitionally equal to ``λ _ → A i0``, which in turn requires ``A i0`` and ``A i1`` to be definitionally equal as well.
  194. When ``r`` is ``i1``, ``transp A r`` will compute as the identity function.
  195. .. code-block:: agda
  196. transp A i1 a = a
  197. This is only sound if in such a case ``A`` is a trivial path, as the side condition requires.
  198. It might seems strange that the side condition expects ``r`` and
  199. ``A`` to interact, but both of them can depend on any of the
  200. interval variables in scope, so assuming a specific value for ``r``
  201. can affect what ``A`` looks like.
  202. Some examples of the side condition for different values of ``r``:
  203. * If ``r`` is some in-scope variable ``i``, on which ``A`` may depend as well, then ``A`` only needs to be
  204. a constant function when substituting ``i1`` for ``i``.
  205. * If ``r`` is ``i0`` then there is no restrition on ``A``, since the side
  206. condition is vacuously true.
  207. * If ``r`` is ``i1`` then ``A`` must be a constant function.
  208. We can use ``transp`` to define regular transport:
  209. ::
  210. transport : ∀ {ℓ} {A B : Set ℓ} → A ≡ B → A → B
  211. transport p a = transp (λ i → p i) i0 a
  212. By combining the transport and min operations we can define the
  213. induction principle for paths:
  214. ::
  215. J : ∀ {ℓ} {A : Set ℓ} {x : A} (P : ∀ y → x ≡ y → Set ℓ)
  216. (d : P x refl) {y : A} (p : x ≡ y)
  217. → P y p
  218. J P d p = transport (λ i → P (p i) (λ j → p (i ∧ j))) d
  219. One subtle difference between paths and the propositional equality
  220. type of Agda is that the computation rule for ``J`` does not hold
  221. definitionally. If ``J`` is defined using pattern-matching as in the
  222. Agda standard library then this holds, however as the path types are
  223. not inductively defined this does not hold for the above definition of
  224. ``J``. In particular, transport in a constant family is only the
  225. identity function up to a path which implies that the computation rule
  226. for ``J`` only holds up to a path:
  227. ::
  228. transportRefl : ∀ {ℓ} {A : Set ℓ} (x : A) → transport refl x ≡ x
  229. transportRefl {A = A} x i = transp (λ _ → A) i x
  230. JRefl : ∀ {ℓ} {A : Set ℓ} {x : A} (P : ∀ y → x ≡ y → Set ℓ)
  231. (d : P x refl) → J P d refl ≡ d
  232. JRefl P d = transportRefl d
  233. Internally in Agda the ``transp`` operation computes by cases on the
  234. type, so for example for Σ-types it is computed elementwise. For path
  235. types it is however not yet possible to provide the computation rule
  236. as we need some way to remember the endpoints of the path after
  237. transporting it. Furthermore, this must work for arbitrary higher
  238. dimensional cubes (as we can iterate the path types). For this we
  239. introduce the "homogeneous composition operations" (``hcomp``) that
  240. generalize binary composition of paths to n-ary composition of higher
  241. dimensional cubes.
  242. Partial elements
  243. ----------------
  244. In order to describe the homogeneous composition operations we need to
  245. be able to write partially specified n-dimensional cubes (i.e. cubes
  246. where some faces are missing). Given an element of the interval ``r :
  247. I`` there is a predicate ``IsOne`` which represents the constraint ``r
  248. = i1``. This comes with a proof that ``i1`` is in fact equal to ``i1``
  249. called ``1=1 : IsOne i1``. We use Greek letters like ``φ`` or ``ψ``
  250. when such an ``r`` should be thought of as being in the domain of
  251. ``IsOne``.
  252. Using this we introduce a type of partial elements called ``Partial φ
  253. A``, this is a special version of ``IsOne φ → A`` with a more
  254. extensional judgmental equality (two elements of ``Partial φ A`` are
  255. considered equal if they represent the same subcube, so the faces of
  256. the cubes can for example be given in different order and the two
  257. elements will still be considered the same). The idea is that
  258. ``Partial φ A`` is the type of cubes in ``A`` that are only defined
  259. when ``IsOne φ``. There is also a dependent version of this called
  260. ``PartialP φ A`` which allows ``A`` to be defined only when ``IsOne
  261. φ``.
  262. .. code-block:: agda
  263. Partial : ∀ {ℓ} → I → Set ℓ → SSet ℓ
  264. PartialP : ∀ {ℓ} → (φ : I) → Partial φ (Set ℓ) → SSet ℓ
  265. There is a new form of pattern matching that can be used to introduce partial elements:
  266. ::
  267. partialBool : ∀ i → Partial (i ∨ ~ i) Bool
  268. partialBool i (i = i0) = true
  269. partialBool i (i = i1) = false
  270. The term ``partialBool i`` should be thought of a boolean with different
  271. values when ``(i = i0)`` and ``(i = i1)``. Terms of type ``Partial φ
  272. A`` can also be introduced using a :ref:`pattern-lambda`.
  273. ::
  274. partialBool' : ∀ i → Partial (i ∨ ~ i) Bool
  275. partialBool' i = λ { (i = i0) → true
  276. ; (i = i1) → false }
  277. When the cases overlap they must agree (note that the order of the
  278. cases doesn't have to match the interval formula exactly):
  279. ::
  280. partialBool'' : ∀ i j → Partial (~ i ∨ i ∨ (i ∧ j)) Bool
  281. partialBool'' i j = λ { (i = i1) → true
  282. ; (i = i1) (j = i1) → true
  283. ; (i = i0) → false }
  284. Furthermore ``IsOne i0`` is actually absurd.
  285. ::
  286. empty : {A : Set} → Partial i0 A
  287. empty = λ { () }
  288. Cubical Agda also has cubical subtypes as in the CCHM type theory:
  289. ::
  290. _[_↦_] : ∀ {ℓ} (A : Set ℓ) (φ : I) (u : Partial φ A) → SSet ℓ
  291. A [ φ ↦ u ] = Sub A φ u
  292. A term ``v : A [ φ ↦ u ]`` should be thought of as a term of type
  293. ``A`` which is definitionally equal to ``u : A`` when ``IsOne φ`` is
  294. satisfied. Any term ``u : A`` can be seen as an term of ``A [ φ ↦ u
  295. ]`` which agrees with itself on ``φ``:
  296. .. code-block:: agda
  297. inS : ∀ {ℓ} {A : Set ℓ} {φ : I} (u : A) → A [ φ ↦ (λ _ → u) ]
  298. One can also forget that a partial element agrees with ``u`` on ``φ``:
  299. .. code-block:: agda
  300. outS : ∀ {ℓ} {A : Set ℓ} {φ : I} {u : Partial φ A} → A [ φ ↦ u ] → A
  301. They satisfy the following equalities:
  302. .. code-block:: agda
  303. outS (inS a) = a
  304. inS {φ = φ} (outS {φ = φ} a) = a
  305. outS {φ = i1} {u} _ = u 1=1
  306. Note that given ``a : A [ φ ↦ u ]`` and ``α : IsOne φ``, it is not the case
  307. that ``outS a = u α``; however, underneath the pattern binding ``(φ = i1)``,
  308. one has ``outS a = u 1=1``.
  309. With all of this cubical infrastructure we can now describe the
  310. ``hcomp`` operations.
  311. Homogeneous composition
  312. -----------------------
  313. The homogeneous composition operations generalize binary composition
  314. of paths so that we can compose multiple composable cubes.
  315. .. code-block:: agda
  316. hcomp : ∀ {ℓ} {A : Set ℓ} {φ : I} (u : I → Partial φ A) (u0 : A) → A
  317. When calling ``hcomp {φ = φ} u u0`` Agda makes sure that ``u0`` agrees
  318. with ``u i0`` on ``φ``. The idea is that ``u0`` is the base and ``u``
  319. specifies the sides of an open box. This is hence an open (higher
  320. dimensional) cube where the side opposite of ``u0`` is missing. The
  321. ``hcomp`` operation then gives us the missing side opposite of
  322. ``u0``. For example binary composition of paths can be written as:
  323. ::
  324. compPath : ∀ {ℓ} {A : Set ℓ} {x y z : A} → x ≡ y → y ≡ z → x ≡ z
  325. compPath {x = x} p q i = hcomp (λ j → λ { (i = i0) → x
  326. ; (i = i1) → q j })
  327. (p i)
  328. Pictorially we are given ``p : x ≡ y`` and ``q : y ≡ z``, and the
  329. composite of the two paths is obtained by computing the missing lid of
  330. this open square:
  331. .. code-block:: text
  332. x z
  333. ^ ^
  334. | |
  335. x | | q j
  336. | |
  337. x ----------> y
  338. p i
  339. In the drawing the direction ``i`` goes left-to-right and ``j`` goes
  340. bottom-to-top. As we are constructing a path from ``x`` to ``z`` along
  341. ``i`` we have ``i : I`` in the context already and we put ``p i`` as
  342. bottom. The direction ``j`` that we are doing the composition in is
  343. abstracted in the first argument to ``hcomp``.
  344. Note that the partial element ``u`` does not have to specify
  345. all the sides of the open box, giving more sides simply gives you
  346. more control on the result of ``hcomp``.
  347. For example if we omit the ``(i = i0) → x`` side in the
  348. definition of ``compPath`` we still get a valid term of type
  349. ``A``. However, that term would reduce to ``hcomp (\ j → \ { () }) x``
  350. when ``i = i0`` and so that definition would not build
  351. a path that starts from ``x``.
  352. We can also define homogeneous filling of cubes as
  353. ::
  354. hfill : ∀ {ℓ} {A : Set ℓ} {φ : I}
  355. (u : ∀ i → Partial φ A) (u0 : A [ φ ↦ u i0 ])
  356. (i : I) → A
  357. hfill {φ = φ} u u0 i = hcomp (λ j → λ { (φ = i1) → u (i ∧ j) 1=1
  358. ; (i = i0) → outS u0 })
  359. (outS u0)
  360. When ``i`` is ``i0`` this is ``u0`` and when ``i`` is ``i1`` this is
  361. ``hcomp u u0``. This can hence be seen as giving us the interior of an
  362. open box. In the special case of the square above ``hfill`` gives us a
  363. direct cubical proof that composing ``p`` with ``refl`` is ``p``.
  364. ::
  365. compPathRefl : ∀ {ℓ} {A : Set ℓ} {x y : A} (p : x ≡ y) → compPath p refl ≡ p
  366. compPathRefl {x = x} {y = y} p j i = hfill (λ _ → λ { (i = i0) → x
  367. ; (i = i1) → y })
  368. (inS (p i))
  369. (~ j)
  370. Glue types
  371. ----------
  372. In order to be able to prove the univalence theorem we also have to
  373. add "Glue" types. These lets us turn equivalences between types into
  374. paths between types. An equivalence of types ``A`` and ``B`` is
  375. defined as a map ``f : A → B`` such that its fibers are contractible.
  376. .. code-block:: agda
  377. fiber : ∀ {ℓ} {A B : Set ℓ} (f : A → B) (y : B) → Set ℓ
  378. fiber {A = A} f y = Σ[ x ∈ A ] f x ≡ y
  379. isContr : ∀ {ℓ} → Set ℓ → Set ℓ
  380. isContr A = Σ[ x ∈ A ] (∀ y → x ≡ y)
  381. record isEquiv {ℓ} {A B : Set ℓ} (f : A → B) : Set ℓ where
  382. field
  383. equiv-proof : (y : B) → isContr (fiber f y)
  384. _≃_ : ∀ {ℓ} (A B : Set ℓ) → Set ℓ
  385. A ≃ B = Σ[ f ∈ (A → B) ] (isEquiv f)
  386. The simplest example of an equivalence is the identity function.
  387. ::
  388. idfun : ∀ {ℓ} → (A : Set ℓ) → A → A
  389. idfun _ x = x
  390. idIsEquiv : ∀ {ℓ} (A : Set ℓ) → isEquiv (idfun A)
  391. equiv-proof (idIsEquiv A) y =
  392. ((y , refl) , λ z i → z .snd (~ i) , λ j → z .snd (~ i ∨ j))
  393. idEquiv : ∀ {ℓ} (A : Set ℓ) → A ≃ A
  394. idEquiv A = (idfun A , idIsEquiv A)
  395. An important special case of equivalent types are isomorphic types
  396. (i.e. types with maps going back and forth which are mutually
  397. inverse): https://github.com/agda/cubical/blob/master/Cubical/Foundations/Isomorphism.agda.
  398. As everything has to work up to higher dimensions the Glue types take
  399. a partial family of types that are equivalent to the base type ``A``:
  400. ::
  401. Glue : ∀ {ℓ ℓ'} (A : Set ℓ) {φ : I}
  402. → Partial φ (Σ[ T ∈ Set ℓ' ] T ≃ A) → Set ℓ'
  403. ..
  404. ::
  405. Glue A Te = primGlue A (λ x → Te x .fst) (λ x → Te x .snd)
  406. These come with a constructor and eliminator:
  407. .. code-block:: agda
  408. glue : ∀ {ℓ ℓ'} {A : Set ℓ} {φ : I} {Te : Partial φ (Σ[ T ∈ Set ℓ' ] T ≃ A)}
  409. → PartialP φ T → A → Glue A Te
  410. unglue : ∀ {ℓ ℓ'} {A : Set ℓ} (φ : I) {Te : Partial φ (Σ[ T ∈ Set ℓ' ] T ≃ A)}
  411. → Glue A Te → A
  412. Using Glue types we can turn an equivalence of types into a path as
  413. follows:
  414. ::
  415. ua : ∀ {ℓ} {A B : Set ℓ} → A ≃ B → A ≡ B
  416. ua {_} {A} {B} e i = Glue B (λ { (i = i0) → (A , e)
  417. ; (i = i1) → (B , idEquiv B) })
  418. The idea is that we glue ``A`` together with ``B`` when ``i = i0``
  419. using ``e`` and ``B`` with itself when ``i = i1`` using the identity
  420. equivalence. This hence gives us the key part of univalence: a
  421. function for turning equivalences into paths. The other part of
  422. univalence is that this map itself is an equivalence which follows
  423. from the computation rule for ``ua``:
  424. ::
  425. uaβ : ∀ {ℓ} {A B : Set ℓ} (e : A ≃ B) (x : A) → transport (ua e) x ≡ e .fst x
  426. uaβ e x = transportRefl (e .fst x)
  427. Transporting along the path that we get from applying ``ua`` to an
  428. equivalence is hence the same as applying the equivalence. This is
  429. what makes it possible to use the univalence axiom computationally in
  430. Cubical Agda: we can package up our equivalences as paths, do equality
  431. reasoning using these paths, and in the end transport along the paths
  432. in order to compute with the equivalences.
  433. We have the following equalities:
  434. .. code-block:: agda
  435. Glue A {i1} Te = Te 1=1 .fst
  436. unglue φ (glue t a) = a
  437. glue (\ { (φ = i1) -> g}) (unglue φ g) = g
  438. unglue i1 {Te} g = Te 1=1 .snd .fst g
  439. glue {φ = i1} t a = t 1=1
  440. For more results about Glue types and univalence see
  441. https://github.com/agda/cubical/blob/master/Cubical/Core/Glue.agda and
  442. https://github.com/agda/cubical/blob/master/Cubical/Foundations/Univalence.agda. For
  443. some examples of what can be done with this for working with binary
  444. and unary numbers see
  445. https://github.com/agda/cubical/blob/master/Cubical/Data/BinNat/BinNat.agda.
  446. Higher inductive types
  447. ----------------------
  448. Cubical Agda also lets us directly define higher inductive types as
  449. datatypes with path constructors. For example the circle and `torus
  450. <https://en.wikipedia.org/wiki/Torus>`_ can be defined as:
  451. ::
  452. data S¹ : Set where
  453. base : S¹
  454. loop : base ≡ base
  455. data Torus : Set where
  456. point : Torus
  457. line1 : point ≡ point
  458. line2 : point ≡ point
  459. square : PathP (λ i → line1 i ≡ line1 i) line2 line2
  460. Functions out of higher inductive types can then be defined using
  461. pattern-matching:
  462. ::
  463. t2c : Torus → S¹ × S¹
  464. t2c point = (base , base)
  465. t2c (line1 i) = (loop i , base)
  466. t2c (line2 j) = (base , loop j)
  467. t2c (square i j) = (loop i , loop j)
  468. c2t : S¹ × S¹ → Torus
  469. c2t (base , base) = point
  470. c2t (loop i , base) = line1 i
  471. c2t (base , loop j) = line2 j
  472. c2t (loop i , loop j) = square i j
  473. When giving the cases for the path and square constructors we have to
  474. make sure that the function maps the boundary to the right thing. For
  475. instance the following definition does not pass Agda's typechecker as
  476. the boundary of the last case does not match up with the expected
  477. boundary of the square constructor (as the ``line1`` and ``line2``
  478. cases are mixed up).
  479. .. code-block:: agda
  480. c2t_bad : S¹ × S¹ → Torus
  481. c2t_bad (base , base) = point
  482. c2t_bad (loop i , base) = line2 i
  483. c2t_bad (base , loop j) = line1 j
  484. c2t_bad (loop i , loop j) = square i j
  485. Functions defined by pattern-matching on higher inductive types
  486. compute definitionally, for all constructors.
  487. ::
  488. c2t-t2c : ∀ (t : Torus) → c2t (t2c t) ≡ t
  489. c2t-t2c point = refl
  490. c2t-t2c (line1 _) = refl
  491. c2t-t2c (line2 _) = refl
  492. c2t-t2c (square _ _) = refl
  493. t2c-c2t : ∀ (p : S¹ × S¹) → t2c (c2t p) ≡ p
  494. t2c-c2t (base , base) = refl
  495. t2c-c2t (base , loop _) = refl
  496. t2c-c2t (loop _ , base) = refl
  497. t2c-c2t (loop _ , loop _) = refl
  498. By turning this isomorphism into an equivalence we get a direct proof
  499. that the torus is equal to two circles.
  500. .. code-block:: agda
  501. Torus≡S¹×S¹ : Torus ≡ S¹ × S¹
  502. Torus≡S¹×S¹ = isoToPath (iso t2c c2t t2c-c2t c2t-t2c)
  503. Cubical Agda also supports parameterized and recursive higher
  504. inductive types, for example propositional truncation (squash types)
  505. is defined as:
  506. ::
  507. data ∥_∥ {ℓ} (A : Set ℓ) : Set ℓ where
  508. ∣_∣ : A → ∥ A ∥
  509. squash : ∀ (x y : ∥ A ∥) → x ≡ y
  510. isProp : ∀ {ℓ} → Set ℓ → Set ℓ
  511. isProp A = (x y : A) → x ≡ y
  512. recPropTrunc : ∀ {ℓ} {A : Set ℓ} {P : Set ℓ} → isProp P → (A → P) → ∥ A ∥ → P
  513. recPropTrunc Pprop f ∣ x ∣ = f x
  514. recPropTrunc Pprop f (squash x y i) =
  515. Pprop (recPropTrunc Pprop f x) (recPropTrunc Pprop f y) i
  516. For many more examples of higher inductive types see:
  517. https://github.com/agda/cubical/tree/master/Cubical/HITs.
  518. Cubical identity types and computational HoTT/UF
  519. ------------------------------------------------
  520. As mentioned above the computation rule for ``J`` does not hold
  521. definitionally for path types. Cubical Agda solves this by introducing
  522. a cubical identity type. The
  523. https://github.com/agda/cubical/blob/master/Cubical/Core/Id.agda file
  524. exports all of the primitives for this type, including the notation
  525. ``_≡_`` and a ``J`` eliminator that computes definitionally on
  526. ``refl``.
  527. The cubical identity type and the path type are equivalent, so all of
  528. the results for one can be transported to the other one (using
  529. univalence). Using this we have implemented an `interface to HoTT/UF <https://github.com/agda/cubical/blob/5de11df25b79ee49d5c084fbbe6dfc66e4147a2e/Cubical/Experiments/HoTT-UF.agda>`_
  530. which provides the user with the key primitives of Homotopy Type
  531. Theory and Univalent Foundations implemented using cubical primitives
  532. under the hood. This hence gives an axiom free version of HoTT/UF
  533. which computes properly.
  534. .. code-block:: agda
  535. module Cubical.Core.HoTT-UF where
  536. open import Cubical.Core.Id public
  537. using ( _≡_ -- The identity type.
  538. ; refl -- Unfortunately, pattern matching on refl is not available.
  539. ; J -- Until it is, you have to use the induction principle J.
  540. ; transport -- As in the HoTT Book.
  541. ; ap
  542. ; _∙_
  543. ; _⁻¹
  544. ; _≡⟨_⟩_ -- Standard equational reasoning.
  545. ; _∎
  546. ; funExt -- Function extensionality
  547. -- (can also be derived from univalence).
  548. ; Σ -- Sum type. Needed to define contractible types, equivalences
  549. ; _,_ -- and univalence.
  550. ; pr₁ -- The eta rule is available.
  551. ; pr₂
  552. ; isProp -- The usual notions of proposition, contractible type, set.
  553. ; isContr
  554. ; isSet
  555. ; isEquiv -- A map with contractible fibers
  556. -- (Voevodsky's version of the notion).
  557. ; _≃_ -- The type of equivalences between two given types.
  558. ; EquivContr -- A formulation of univalence.
  559. ; ∥_∥ -- Propositional truncation.
  560. ; ∣_∣ -- Map into the propositional truncation.
  561. ; ∥∥-isProp -- A truncated type is a proposition.
  562. ; ∥∥-recursion -- Non-dependent elimination.
  563. ; ∥∥-induction -- Dependent elimination.
  564. )
  565. In order to get access to only the HoTT/UF primitives start a file as
  566. follows:
  567. .. code-block:: agda
  568. {-# OPTIONS --cubical #-}
  569. open import Cubical.Core.HoTT-UF
  570. However, even though this interface exists it is still recommended
  571. that one uses the cubical identity types unless one really need ``J``
  572. to compute on ``refl``. The reason for this is that the syntax for
  573. path types does not work for the identity types, making many proofs
  574. more involved as the only way to reason about them is using ``J``.
  575. Furthermore, the path types satisfy many useful definitional
  576. equalities that the identity types don't.
  577. .. _erased-cubical:
  578. Cubical Agda with erased glue
  579. -----------------------------
  580. The option :option:`--erased-cubical` enables a variant of Cubical
  581. Agda in which glue (and the other builtins defined in
  582. ``Agda.Builtin.Cubical.Glue``) must only be used in
  583. :ref:`erased<runtime-irrelevance>` settings.
  584. Regular Cubical Agda code can import code that uses
  585. :option:`--erased-cubical`. Regular Cubical Agda code can also be
  586. imported from code that uses :option:`--erased-cubical`, but names
  587. defined using Cubical Agda are treated as if they had been marked as
  588. erased, with some exceptions related to pattern matching:
  589. - Matching on a non-erased imported constructor does not, on its own,
  590. make Agda treat the right-hand side as erased.
  591. - Non-erased imported constructors count as non-erased for the
  592. purposes of the run-time mode
  593. :ref:`rule<run-time-irrelevance-rules>` that one "cannot pattern
  594. match on erased arguments, unless there is at most one valid case
  595. (not counting erased constructors)".
  596. The reason for these exceptions is that it should be possible to
  597. import the code from modules that use :option:`--cubical`, in which
  598. the non-erased constructors are not treated as erased.
  599. Note that names that are re-exported from a Cubical Agda module using
  600. ``open import M args public`` are seen as defined using Cubical Agda.
  601. References
  602. ----------
  603. .. _`CCHM`:
  604. Cyril Cohen, Thierry Coquand, Simon Huber and Anders Mörtberg;
  605. `“Cubical Type Theory: a constructive interpretation of the
  606. univalence axiom” <https://arxiv.org/abs/1611.02108>`_.
  607. .. _`CHM`:
  608. Thierry Coquand, Simon Huber, Anders Mörtberg; `"On Higher Inductive
  609. Types in Cubical Type Theory" <https://arxiv.org/abs/1802.01170>`_.
  610. .. _primitives-ref:
  611. Appendix: Cubical Agda primitives
  612. ---------------------------------
  613. The Cubical Agda primitives and internals are exported by a series of
  614. files found in the ``lib/prim/Agda/Builtin/Cubical`` directory of
  615. Agda. The ``agda/cubical`` library exports all of these primitives
  616. with the names used throughout this document. Experts might find it
  617. useful to know what is actually exported as there are quite a few
  618. primitives available that are not really exported by ``agda/cubical``,
  619. so the goal of this section is to list the contents of these
  620. files. However, for regular users and beginners the ``agda/cubical``
  621. library should be sufficient and this section can safely be ignored.
  622. The key file with primitives is ``Agda.Primitive.Cubical``. It exports
  623. the following ``BUILTIN``, primitives and postulates:
  624. .. code-block:: agda
  625. {-# BUILTIN CUBEINTERVALUNIV IUniv #-} -- IUniv : SSet₁
  626. {-# BUILTIN INTERVAL I #-} -- I : IUniv
  627. {-# BUILTIN IZERO i0 #-}
  628. {-# BUILTIN IONE i1 #-}
  629. infix 30 primINeg
  630. infixr 20 primIMin primIMax
  631. primitive
  632. primIMin : I → I → I -- _∧_
  633. primIMax : I → I → I -- _∨_
  634. primINeg : I → I -- ~_
  635. {-# BUILTIN ISONE IsOne #-} -- IsOne : I → SSet
  636. postulate
  637. itIsOne : IsOne i1 -- 1=1
  638. IsOne1 : ∀ i j → IsOne i → IsOne (primIMax i j)
  639. IsOne2 : ∀ i j → IsOne j → IsOne (primIMax i j)
  640. {-# BUILTIN ITISONE itIsOne #-}
  641. {-# BUILTIN ISONE1 IsOne1 #-}
  642. {-# BUILTIN ISONE2 IsOne2 #-}
  643. {-# BUILTIN PARTIAL Partial #-}
  644. {-# BUILTIN PARTIALP PartialP #-}
  645. postulate
  646. isOneEmpty : ∀ {a} {A : Partial i0 (Set a)} → PartialP i0 A
  647. {-# BUILTIN ISONEEMPTY isOneEmpty #-}
  648. primitive
  649. primPOr : ∀ {a} (i j : I) {A : Partial (primIMax i j) (Set a)}
  650. → PartialP i (λ z → A (IsOne1 i j z)) → PartialP j (λ z → A (IsOne2 i j z))
  651. → PartialP (primIMax i j) A
  652. -- Computes in terms of primHComp and primTransp
  653. primComp : ∀ {a} (A : (i : I) → Set (a i)) {φ : I} → (∀ i → Partial φ (A i)) → (a : A i0) → A i1
  654. syntax primPOr p q u t = [ p ↦ u , q ↦ t ]
  655. primitive
  656. primTransp : ∀ {a} (A : (i : I) → Set (a i)) (φ : I) → (a : A i0) → A i1
  657. primHComp : ∀ {a} {A : Set a} {φ : I} → (∀ i → Partial φ A) → A → A
  658. The interval ``I`` belongs to its own sort, ``IUniv``. Types in this sort
  659. do not support composition and transport (unlike ``Set``), but function
  660. types from types in this sort to types in ``Set`` do (unlike `SSet`).
  661. The Path types are exported by ``Agda.Builtin.Cubical.Path``:
  662. .. code-block:: agda
  663. postulate
  664. PathP : ∀ {ℓ} (A : I → Set ℓ) → A i0 → A i1 → Set ℓ
  665. {-# BUILTIN PATHP PathP #-}
  666. infix 4 _≡_
  667. _≡_ : ∀ {ℓ} {A : Set ℓ} → A → A → Set ℓ
  668. _≡_ {A = A} = PathP (λ _ → A)
  669. {-# BUILTIN PATH _≡_ #-}
  670. The Cubical subtypes are exported by ``Agda.Builtin.Cubical.Sub``:
  671. .. code-block:: agda
  672. {-# BUILTIN SUB Sub #-}
  673. postulate
  674. inc : ∀ {ℓ} {A : Set ℓ} {φ} (x : A) → Sub A φ (λ _ → x)
  675. {-# BUILTIN SUBIN inS #-}
  676. primitive
  677. primSubOut : ∀ {ℓ} {A : Set ℓ} {φ : I} {u : Partial φ A} → Sub _ φ u → A
  678. The Glue types are exported by ``Agda.Builtin.Cubical.Glue``:
  679. .. code-block:: agda
  680. record isEquiv {ℓ ℓ'} {A : Set ℓ} {B : Set ℓ'} (f : A → B) : Set (ℓ ⊔ ℓ') where
  681. field
  682. equiv-proof : (y : B) → isContr (fiber f y)
  683. infix 4 _≃_
  684. _≃_ : ∀ {ℓ ℓ'} (A : Set ℓ) (B : Set ℓ') → Set (ℓ ⊔ ℓ')
  685. A ≃ B = Σ (A → B) \ f → (isEquiv f)
  686. equivFun : ∀ {ℓ ℓ'} {A : Set ℓ} {B : Set ℓ'} → A ≃ B → A → B
  687. equivFun e = fst e
  688. equivProof : ∀ {la lt} (T : Set la) (A : Set lt) → (w : T ≃ A) → (a : A)
  689. → ∀ ψ → (Partial ψ (fiber (w .fst) a)) → fiber (w .fst) a
  690. equivProof A B w a ψ fb = contr' {A = fiber (w .fst) a} (w .snd .equiv-proof a) ψ fb
  691. where
  692. contr' : ∀ {ℓ} {A : Set ℓ} → isContr A → (φ : I) → (u : Partial φ A) → A
  693. contr' {A = A} (c , p) φ u = hcomp (λ i → λ { (φ = i1) → p (u 1=1) i
  694. ; (φ = i0) → c }) c
  695. {-# BUILTIN EQUIV _≃_ #-}
  696. {-# BUILTIN EQUIVFUN equivFun #-}
  697. {-# BUILTIN EQUIVPROOF equivProof #-}
  698. primitive
  699. primGlue : ∀ {ℓ ℓ'} (A : Set ℓ) {φ : I}
  700. → (T : Partial φ (Set ℓ')) → (e : PartialP φ (λ o → T o ≃ A))
  701. → Set ℓ'
  702. prim^glue : ∀ {ℓ ℓ'} {A : Set ℓ} {φ : I}
  703. → {T : Partial φ (Set ℓ')} → {e : PartialP φ (λ o → T o ≃ A)}
  704. → PartialP φ T → A → primGlue A T e
  705. prim^unglue : ∀ {ℓ ℓ'} {A : Set ℓ} {φ : I}
  706. → {T : Partial φ (Set ℓ')} → {e : PartialP φ (λ o → T o ≃ A)}
  707. → primGlue A T e → A
  708. primFaceForall : (I → I) → I
  709. -- pathToEquiv proves that transport is an equivalence (for details
  710. -- see Agda.Builtin.Cubical.Glue). This is needed internally.
  711. {-# BUILTIN PATHTOEQUIV pathToEquiv #-}
  712. Note that the Glue types are uncurried in ``agda/cubical`` to make
  713. them more pleasant to use:
  714. .. code-block:: agda
  715. Glue : ∀ {ℓ ℓ'} (A : Set ℓ) {φ : I}
  716. → (Te : Partial φ (Σ[ T ∈ Set ℓ' ] T ≃ A))
  717. → Set ℓ'
  718. Glue A Te = primGlue A (λ x → Te x .fst) (λ x → Te x .snd)
  719. The ``Agda.Builtin.Cubical.Id`` exports the cubical identity types:
  720. .. code-block:: agda
  721. postulate
  722. Id : ∀ {ℓ} {A : Set ℓ} → A → A → Set ℓ
  723. {-# BUILTIN ID Id #-}
  724. {-# BUILTIN CONID conid #-}
  725. primitive
  726. primDepIMin : _
  727. primIdFace : ∀ {ℓ} {A : Set ℓ} {x y : A} → Id x y → I
  728. primIdPath : ∀ {ℓ} {A : Set ℓ} {x y : A} → Id x y → x ≡ y
  729. primitive
  730. primIdJ : ∀ {ℓ ℓ'} {A : Set ℓ} {x : A} (P : ∀ y → Id x y → Set ℓ') →
  731. P x (conid i1 (λ i → x)) → ∀ {y} (p : Id x y) → P y p
  732. primitive
  733. primIdElim : ∀ {a c} {A : Set a} {x : A}
  734. (C : (y : A) → Id x y → Set c) →
  735. ((φ : I) (y : A [ φ ↦ (λ _ → x) ])
  736. (w : (x ≡ outS y) [ φ ↦ (λ { (φ = i1) → \ _ → x}) ]) →
  737. C (outS y) (conid φ (outS w))) →
  738. {y : A} (p : Id x y) → C y p