module 1Lab.Univalence where
Univalence🔗
In Homotopy Type Theory, univalence is the principle stating that equivalent types can be identified. When the book first came out, there was no widely-accepted computational interpretation of this principle, so it was added to the theory as an axiom: the univalence axiom.
Precisely, the axiom as presented in the book consists of the following data (right under remark §2.10.4):
A map which turns equivalences into identifications of types. This map is called
ua
.A rule for eliminating identifications of types, by turning them into equivalences:
path→equiv
The propositional computation rule, stating that transport along
ua(f)
is identical to applyingf
:uaβ
.
In the book, there is an extra postulated datum asserting that ua
is an inverse to path→equiv
. This datum does not have a
name in this development, because it’s proved in-line in the
construction of the term univalence
.
The point of cubical type theory is to give these terms constructive interpretations, i.e., make them definable in the theory, in terms of constructions that have computational behaviour. Let’s see how this is done.
Glue🔗
To even state univalence, we first have to make sure that the concept of “paths between types” makes sense in the first place. In “Book HoTT”, paths between types are a well-formed concept because the path type is uniformly inductively defined for everything — including universes. This is not the case in Cubical type theory, where for paths in to be well-behaved, must be fibrant.
Since there’s no obvious choice for how to interpret hcomp
in Type
, a fine solution is to make hcomp
its own type former. This is the
approach taken by some Cubical type theories in the RedPRL school. Univalence in those type
theories is then achieved by adding a type former, called
V
, which turns an equivalence into a path.
In CCHM (2016)
— and therefore Cubical Agda — a different approach is taken, which
combines proving univalence with defining a fibrancy structure for the
universe. The core idea is to define a new type former, Glue
, which “glues” a partial type, along an
equivalence, to a total type.
private
variable
: Level
ℓ ℓ'
primitive
: (A : Type ℓ) {φ : I}
primGlue → (T : Partial φ (Type ℓ')) → (e : PartialP φ (λ o → T o ≃ A))
→ Type ℓ'
: {A : Type ℓ} {φ : I}
prim^glue → {T : Partial φ (Type ℓ')} → {e : PartialP φ (λ o → T o ≃ A)}
→ PartialP φ T → A → primGlue A T e
: {A : Type ℓ} {φ : I}
prim^unglue → {T : Partial φ (Type ℓ')} → {e : PartialP φ (λ o → T o ≃ A)}
→ primGlue A T e → A
open import Prim.HCompU
open import 1Lab.Equiv.FromPath
: (A : Type ℓ)
Glue → {φ : I}
→ (Te : Partial φ (Σ[ T ∈ Type ℓ' ] T ≃ A))
→ Type ℓ'
The public interface of Glue
demands a type
called the base type, a formula
and a partial type
which is equivalent to
Since the equivalence is defined inside the partial element, it
can also (potentially) vary over the interval, so in reality we have a
family of partial types
and a family of partial equivalences
In the specific case where we set
we can illustrate Glue A (T, f)
as the dashed line in the
square diagram below. The conceptual idea is that by “gluing”
onto a totally defined type, we get a type which extends
= primGlue A (λ x → Te x .fst) (λ x → Te x .snd)
Glue A Te
unglue: {A : Type ℓ} (φ : I) {T : Partial φ (Type ℓ')}
{e : PartialP φ (λ o → T o ≃ A)}
→ primGlue A T e → A
= prim^unglue {φ = φ}
unglue φ
glue-inc: {A : Type ℓ} (φ : I)
→ {Tf : Partial φ (Σ[ B ∈ Type ℓ' ] B ≃ A)}
→ (p : PartialP φ (λ { (φ = i1) → Tf 1=1 .fst }))
→ A [ φ ↦ (λ { (φ = i1) → Tf 1=1 .snd .fst (p 1=1) }) ]
→ Glue A Tf
= prim^glue {φ = φ} p (outS x) glue-inc φ p x
For Glue
to extend
we add a computation rule which could be called a boundary
condition, since it specifies how Glue
behaves on the boundaries of cubes.
Concisely, when
we have that Glue
evaluates to the
partial type. This is exactly what it means for Glue
to extend
module _ {A B : Type} {e : A ≃ B} where
private
: Glue B {i1} (λ x → A , e) ≡ A
Glue-boundary = A Glue-boundary i
Furthermore, since we can turn any family of paths into a family of
equivalences, we can use the Glue
construct to implement something with precisely the same interface as
hcomp
for Type
:
glue-hfill: ∀ {ℓ} φ (u : ∀ i → Partial (φ ∨ ~ i) (Type ℓ))
→ ∀ i → Type ℓ [ _ ↦ (λ { (i = i0) → u i0 1=1
; (φ = i1) → u i 1=1 }) ]
The type of glue-hfill
is the
same as that of hfill
, but the type
is stated much more verbosely — so that we may define it without
previous reference to a hcomp
analogue. Like hfill
, glue-hfill
extends an open box of types
to a totally-defined cube. The type of glue-hfill
expresses this in terms of
extensions: We have a path (that’s the ∀ i →
binder) of
Type
s which agrees with
outS u0
on the left endpoint, and with u
everywhere.
= inS (
glue-hfill φ u i (u i0 1=1) {φ = φ ∨ ~ i}
Glue λ { (φ = i1) → u i 1=1 , line→equiv (λ j → u (i ∧ ~ j) 1=1)
; (i = i0) → u i0 1=1 , line→equiv (λ i → u i0 1=1)
})
In the case for
we must glue
onto itself using the identity equivalence. This guarantees that the
boundary of the stated type for glue-hfill
is satisfied. However, since
different faces of partial elements must agree where they are defined,
we can not use the identity equivalence directly, since
line→equiv refl
is not definitionally the identity
equivalence.
When hence where is defined, we glue the endpoint onto using the equivalence generated by the path provided by itself! It’s a family of partial paths, after all, and that can be turned into a family of partial equivalences.
Using hcomp-unique
and glue-hfill
together, we get a internal
characterisation of the fibrancy structure of the universe. While hcomp-unique
may appear surprising, it is
essentially a generalisation of the uniqueness of path compositions: Any
open box has a contractible space of fillers.
: ∀ {ℓ} {φ} (u : ∀ i → Partial (φ ∨ ~ i) (Type ℓ))
hcomp≡Glue → hcomp φ u
(u i0 1=1)
≡ Glue (λ { (φ = i1) → u i1 1=1 , line→equiv (λ j → u (~ j) 1=1) })
{φ = φ} u = hcomp-unique φ u (glue-hfill φ u) hcomp≡Glue
Paths from Glue🔗
Since Glue
generalises hcomp
by allowing a partial equivalence
as its “tube”, rather than a partial path, it allows us to turn any
equivalence into a path, using a sort of “trick”: We consider the
line with endpoints
and
as an open cube to be filled. A filler for this line is exactly a path
Since Glue
fills open boxes of
types using equivalences, this path exists!
: {A B : Type ℓ} → A ≃ B → A ≡ B
ua {A = A} {B} eqv i = Glue B λ { (i = i0) → A , eqv
ua ; (i = i1) → B , _ , id-equiv
}
Semantically, the explanation of ua
as completing a partial line is
sufficient. But we can also ask ourselves: Why does this definition go
through, syntactically? Because of the boundary condition for
Glue: when i = i0
, the whole thing evaluates to
A
, meaning that the left endpoint of the path is correct.
The same thing happens with the right endpoint.
The action of transporting along
ua(f)
can be described by chasing an element around the
diagram that illustrates Glue in the
case, specialising to ua
. Keep in
mind that, since the right face of the diagram “points in the wrong
direction”, it must be inverted. However, the inverse of the identity
equivalence is the identity equivalence, so nothing changes (for this
example).
- The action that corresponds to the left face of the diagram is to
apply the underlying function of
f
. This contributes thef .fst x
part of theuaβ
term below.
- For the bottom face, we have a path rather than an equivalence, so
we must
transport
along it. In this case, the path is the reflexivity onB
, but in a more generalGlue
construction, it might be a non-trivial path.
To compensate for this extra transport, we use coe1→i
, which connects
f .fst x
and
transport (λ i → B) (f .fst x)
.
- Finally, we apply the inverse of the identity equivalence,
corresponding to the right face in the diagram. This immediately
computes away, and thus contributes nothing to the
uaβ
path.
: {A B : Type ℓ} (f : A ≃ B) (x : A) → transport (ua f) x ≡ f .fst x
uaβ {A = A} {B} f x i = coe1→i (λ _ → B) i (f .fst x) uaβ
Since ua
is a map that turns
equivalences into paths, we can compose it with a function that turns isomorphisms into equivalences to get the
map Iso→Path
.
: {A B : Type ℓ} → Iso A B → A ≡ B
Iso→Path (f , iiso) = ua (f , is-iso→is-equiv iiso) Iso→Path
Paths over ua🔗
The introduction and elimination forms for Glue
can be specialised to the case of
ua
, leading to the definitions of
ua-glue
and ua-unglue
below. Their types are written
in terms of interval variables and extension types, rather than
using Path
s, because these typings
make the structure of Glue
more
explicit.
The first, ua-unglue
, tells us
that if we have some x : ua e i
(varying over an interval
variable i
), then we have an element of B
which agrees with e .fst x
on the left and with
x
on the right.
: ∀ {A B : Type ℓ} (e : A ≃ B) (i : I) (x : ua e i) → B
ua-unglue = unglue (i ∨ ~ i) x ua-unglue e i x
We can factor the interval variable out, to get a type in terms of
PathP
, leading to an explanation of
ua-unglue
without mentioning extensions: A path
x ≡ y
over ua e
induces a path
e .fst x ≡ y
.
: ∀ {A B : Type ℓ} (e : A ≃ B) {x : A} {y : B}
ua-pathp→path → PathP (λ i → ua e i) x y
→ e .fst x ≡ y
= ua-unglue e i (p i) ua-pathp→path e p i
In the other direction, we have ua-glue
, which expresses that a path
e .fst x ≡ y
implies that x ≡ y
over
ua e
. For the type of ua-glue
, suppose that we have a partial
element
defined on the left endpoint of the interval, together with an extension
of
where
is defined. What ua-glue
expresses
is that we can complete this to a path in
which agrees with
and
where these are defined.
: ∀ {A B : Type ℓ} (e : A ≃ B) (i : I)
ua-glue (x : Partial (~ i) A)
(y : B [ _ ↦ (λ { (i = i0) → e .fst (x 1=1) }) ])
→ ua e i [ _ ↦ (λ { (i = i0) → x 1=1
; (i = i1) → outS y
}) ]
= inS (prim^glue {φ = i ∨ ~ i}
ua-glue e i x y (λ { (i = i0) → x 1=1
; (i = i1) → outS y })
(outS y))
Observe that, since
is partially in the image of
this essentially constrains
to be a “partial preimage” of
under the equivalence
Factoring in the type of the interval, we get the promised map between
dependent paths over ua
and paths
in B.
: ∀ {A B : Type ℓ} (e : A ≃ B) {x : A} {y : B}
path→ua-pathp → e .fst x ≡ y
→ PathP (λ i → ua e i) x y
{x = x} p i = outS (ua-glue e i (λ { (i = i0) → x }) (inS (p i))) path→ua-pathp e
The “pathp to path” versions of the above lemmas are definitionally
inverses, so they provide a characterisation of
PathP (ua f)
in terms of non-dependent paths.
: ∀ {A B : Type ℓ} (e : A ≃ B) {x : A} {y : B}
ua-pathp≃path → (e .fst x ≡ y) ≃ (PathP (λ i → ua e i) x y)
.fst = path→ua-pathp eqv
ua-pathp≃path eqv .snd .is-eqv y .centre = strict-fibres (ua-pathp→path eqv) y .fst
ua-pathp≃path eqv .snd .is-eqv y .paths = strict-fibres (ua-pathp→path eqv) y .snd ua-pathp≃path eqv
The “axiom”🔗
The actual “univalence axiom”, as stated in the HoTT book, says that
the canonical map A ≡ B
, defined using J
, is an equivalence. This map is id→equiv
, defined right above. In more
intuitive terms, it’s “casting” the identity equivalence
A ≃ A
along a proof that A ≡ B
to get an
equivalence A ≃ B
.
module _ where private
: {A B : Type ℓ} → A ≡ B → A ≃ B
id→equiv {A = A} {B} = J (λ x _ → A ≃ x) (_ , id-equiv)
id→equiv
: {A : Type ℓ} → id→equiv (λ i → A) ≡ (_ , id-equiv)
id→equiv-refl {A = A} = J-refl (λ x _ → A ≃ x) (_ , id-equiv) id→equiv-refl
However, because of efficiency concerns (Agda is a
programming language, after all), instead of using id→equiv
defined using J, we use path→equiv
, which is defined in an auxiliary module.
: {A B : Type ℓ} → A ≡ B → A ≃ B
path→equiv = line→equiv (λ i → p i) path→equiv p
Since identity of equivalences is determined by identity of their
underlying functions, to show that path→equiv
of refl
is the identity equivalence, we use
coe1→i
to show that transport
by refl
is the identity.
: {A : Type ℓ} → path→equiv (refl {x = A}) ≡ (id , id-equiv)
path→equiv-refl {A = A} =
path→equiv-refl (λ i x → coe1→i (λ i → A) i x)
Σ-path (is-prop→pathp (λ i → is-equiv-is-prop _) _ _)
For the other direction, we must show that ua
of id-equiv
is refl
. We can do this quite efficiently
using Glue
. Since this is a path
between paths, we have two interval variables.
: {A : Type ℓ} → ua (_ , id-equiv {A = A}) ≡ refl
ua-id-equiv {A = A} i j = Glue A {φ = i ∨ ~ j ∨ j} (λ _ → A , _ , id-equiv) ua-id-equiv
We can then prove that the map path→equiv
is an isomorphism, hence an
equivalence. It’s very useful to have explicit names for the proofs that
path→equiv
and ua
are equivalences without referring to
components of Path≃Equiv
, so we
introduce names for them as well.
: {A B : Type ℓ} → Iso (A ≡ B) (A ≃ B)
Path≃Equiv : {A B : Type ℓ} → is-equiv (path→equiv {A = A} {B})
univalence : {A B : Type ℓ} → is-equiv (ua {A = A} {B})
univalence⁻¹
{A = A} {B = B} = path→equiv , iiso where
Path≃Equiv : is-iso path→equiv
iiso .is-iso.inv = ua iiso
We show that path→equiv
inverts ua
, which means proving that one can
recover the original equivalence from the generated path. Because of the
computational nature of Cubical Agda, all we have to do is apply uaβ
:
.is-iso.rinv (f , is-eqv) =
iiso (funext (uaβ (f , is-eqv))) (is-equiv-is-prop f _ _) Σ-path
For the other direction, we use path induction to reduce the
problem from showing that ua
inverts path→equiv
for an arbitrary
path (which is hard) to showing that path→equiv
takes refl
to the identity equivalence (path→equiv-refl
), and that ua
takes the identity equivalence to
refl
(ua-id-equiv
).
.is-iso.linv =
iiso (λ _ p → ua (path→equiv p) ≡ p)
J (ap ua path→equiv-refl ∙ ua-id-equiv)
{A = A} {B} = is-iso→is-equiv (Path≃Equiv .snd)
univalence {A = A} {B} = is-iso→is-equiv (is-iso.inverse (Path≃Equiv .snd)) univalence⁻¹
In some situations, it is helpful to have a proof that path→equiv
followed by an adjustment of levels
is still an equivalence:
: {A B : Type ℓ} → is-equiv (λ e → lift (path→equiv {A = A} {B} e))
univalence-lift {ℓ = ℓ} = is-iso→is-equiv morp where
univalence-lift : is-iso (λ e → lift {ℓ = lsuc ℓ} (path→equiv e))
morp .is-iso.inv x = ua (x .lower)
morp .is-iso.rinv x =
morp (path→equiv (ua (x .lower))) ≡⟨ ap lift (Path≃Equiv .snd .is-iso.rinv _) ⟩
lift
x ∎.is-iso.linv x = Path≃Equiv .snd .is-iso.linv _ morp
Equivalence induction🔗
One useful consequence of 1 is that the type of equivalences satisfies the same induction principle as the type of identifications. By analogy with how path induction can be characterised as contractibility of singletons and transport, “equivalence induction” can be characterised as transport and contractibility of singletons up to equivalence:
: ∀ {ℓ} (A : Type ℓ) → is-contr (Σ[ B ∈ Type ℓ ] A ≃ B)
Equiv-is-contr .centre = A , _ , id-equiv
Equiv-is-contr A .paths (B , A≃B) i = ua A≃B i , p i , q i where
Equiv-is-contr A : PathP (λ i → A → ua A≃B i) id (A≃B .fst)
p = outS (ua-glue A≃B i (λ { (i = i0) → x }) (inS (A≃B .fst x)))
p i x
: PathP (λ i → is-equiv (p i)) id-equiv (A≃B .snd)
q = is-prop→pathp (λ i → is-equiv-is-prop (p i)) _ _ q
Combining Equiv-is-contr
with
subst
, we get an induction
principle for the type of equivalences based at
To prove
for any
it suffices to consider the case where
is
and
is the identity equivalence.
: ∀ {ℓ ℓ'} {A : Type ℓ}
EquivJ → (P : (B : Type ℓ) → A ≃ B → Type ℓ')
→ P A (_ , id-equiv)
→ {B : Type ℓ} (e : A ≃ B)
→ P B e
=
EquivJ P pid eqv (λ e → P (e .fst) (e .snd)) (Equiv-is-contr _ .is-contr.paths (_ , eqv)) pid subst
Equivalence induction simplifies the proofs of many properties about
equivalences. For example, if
is an equivalence, then so is its action on paths
private
: ∀ {ℓ} {A B : Type ℓ}
is-equiv→is-embedding → (f : A → B) → is-equiv f
→ {x y : A}
→ is-equiv (ap f {x = x} {y = y})
=
is-equiv→is-embedding f eqv (λ B e → is-equiv (ap (e .fst))) id-equiv (f , eqv) EquivJ
The proof can be rendered in English roughly as follows:
Suppose
is an equivalence
. We want to show that, for any choice of the map is an equivalence.By
induction
, it suffices to cover the case where is and is the identity function.But then, we have that is definitionally equal to which is known to be
an equivalence
.
Object classifiers🔗
In category theory, the idea of classifiers (or classifying objects) often comes up when categories applied to the study of logic. For example, any elementary topos has a subobject classifier: an object such that maps corresponds to maps with propositional fibres (equivalently, inclusions In higher categorical analyses of logic, classifying objects exist for more maps: an elementary 2-topos has a discrete object classifier, which classify maps with discrete fibres.
Since a has classifiers for maps with fibres, and a has classifiers for maps with fibres, one might expect that an would have classifiers for maps with fibres that are not truncated at all. This is indeed the case! In HoTT, this fact is internalised using the univalent universes, and we can prove that univalent universes are object classifiers.
private variable
: Type ℓ
A B E open is-iso
As an intermediate step, we prove that the value
of a type family
at a point
is equivalent to the fibre of
over
The proof follows from the De Morgan structure on the interval, and the
“spread” operation coe1→i
.
-- HoTT book lemma 4.8.1
: (B : A → Type ℓ') (a : A)
Fibre-equiv → fibre (fst {B = B}) a ≃ B a
= Iso→Equiv isom where
Fibre-equiv B a : Iso _ _
isom .fst ((x , y) , p) = subst B p y
isom .snd .inv x = (a , x) , refl
isom .snd .rinv x i = coe1→i (λ _ → B a) i x
isom .snd .linv ((x , y) , p) i =
isom (p (~ i) , coe1→i (λ j → B (p (~ i ∧ ~ j))) i y) , λ j → p (~ i ∨ j)
Another fact from homotopy theory that we can import into homotopy
type theory is that any map is equivalent to a fibration. More
specifically, given a map
the total space
is equivalent to the dependent sum of the fibres. The theorems Total-equiv
and Fibre-equiv
are what justify referring to
Σ
the “total space” of a type
family.
: (p : E → B) → E ≃ Σ B (fibre p)
Total-equiv = Iso→Equiv isom where
Total-equiv p : Iso _ (Σ _ (fibre p))
isom .fst x = p x , x , refl
isom .snd .inv (_ , x , _) = x
isom .snd .rinv (b , x , q) i = q i , x , λ j → q (i ∧ j)
isom .snd .linv x = refl isom
Putting these together, we get the promised theorem: The space of
maps
is equivalent to the space of fibrations with base space
and variable total space
If we allow
and
to live in different universes, then the maps are classified by the
biggest universe in which they both fit, namely
Type (ℓ ⊔ ℓ')
. Note that the proof of Fibration-equiv
makes fundamental use of
ua
, to construct the witnesses that
taking fibres and taking total spaces are inverses. Without ua
, we could only get an
“isomorphism-up-to-equivalence” of types.
: ∀ {ℓ ℓ'} {B : Type ℓ}
Fibration-equiv → (Σ[ E ∈ Type (ℓ ⊔ ℓ') ] (E → B))
(B → Type (ℓ ⊔ ℓ'))
≃ {B = B} = Iso→Equiv isom where
Fibration-equiv : Iso (Σ[ E ∈ Type _ ] (E → B)) (B → Type _)
isom .fst (E , p) = fibre p
isom .snd .inv p⁻¹ = Σ _ p⁻¹ , fst
isom .snd .rinv prep i x = ua (Fibre-equiv prep x) i
isom .snd .linv (E , p) i
isom = ua e (~ i) , λ x → fst (ua-unglue e (~ i) x)
where e = Total-equiv p
To solidify the explanation that object classifiers generalise the object classifiers you would find in a we prove that any class of maps described by a property which holds of all of its fibres (or even structure on all of its fibres!) has a classifying object — the total space
For instance, if we take
to be the property of being a proposition
, this theorem tells us
that Σ is-prop
classifies subobjects. With the
slight caveat that Σ is-prop
is not closed under
impredicative quantification, this corresponds exactly to the notion of
subobject classifier in a
since the maps with propositional fibres are precisely the injective
maps.
_ = is-prop
Since the type of “maps into B with variable domain and P fibres” has a very unwieldy description — both in words or in Agda syntax — we abbreviate it by The notation is meant to evoke the idea of a slice category: The objects of are objects of the category equipped with choices of maps into Similarly, the objects of are objects of the universe with a choice of map into such that holds for all the fibres of
_/[_]_ : ∀ {ℓ' ℓ''} (ℓ : Level) → (Type (ℓ ⊔ ℓ') → Type ℓ'') → Type ℓ' → Type _
_/[_]_ {ℓ} ℓ' P B =
(Type (ℓ ⊔ ℓ')) λ A →
Σ (A → B) λ f →
Σ (x : B) → P (fibre f x)
The proof that the slice
is classified by
follows from elementary properties of
types (namely: reassociation
, distributivity
of
over
and the classification theorem Fibration-equiv
. Really, the most
complicated part of this proof is rearranging the nested sum and product
types to a form to which we can apply Fibration-equiv
.
Map-classifier: ∀ {ℓ ℓ' ℓ''} {B : Type ℓ'} (P : Type (ℓ ⊔ ℓ') → Type ℓ'')
→ (ℓ /[ P ] B) ≃ (B → Σ _ P)
{ℓ = ℓ} {B = B} P =
Map-classifier (Σ _ λ A → Σ _ λ f → (x : B) → P (fibre f x)) ≃⟨ Σ-assoc ⟩
(Σ _ λ { (x , f) → (x : B) → P (fibre f x) }) ≃⟨ Σ-ap-fst (Fibration-equiv {ℓ' = ℓ}) ⟩
(Σ _ λ A → (x : B) → P (A x)) ≃⟨ Σ-Π-distrib e⁻¹ ⟩
(B → Σ _ P) ≃∎
module ua {ℓ} {A B : Type ℓ} = Equiv (ua {A = A} {B} , univalence⁻¹)
unglue-is-equiv: ∀ {ℓ ℓ'} {A : Type ℓ} (φ : I)
→ {B : Partial φ (Σ (Type ℓ') (_≃ A))}
→ is-equiv {A = Glue A B} (unglue φ)
{A = A} φ {B = B} .is-eqv y = extend→is-contr ctr
unglue-is-equiv where module _ (ψ : I) (par : Partial ψ (fibre (unglue φ) y)) where
: .(p : IsOne φ)
fib → fibre (B p .snd .fst) y
(ψ ∧ φ) ↦ (λ { (ψ = i1) (φ = i1) → par 1=1 }) ]
[ = is-contr→extend (B p .snd .snd .is-eqv y) (ψ ∧ φ) _
fib p
: ∀ j → Partial (φ ∨ ψ ∨ ~ j) A
sys (j = i0) = y
sys j (φ = i1) = outS (fib 1=1) .snd (~ j)
sys j (ψ = i1) = par 1=1 .snd (~ j)
sys j
= inS $ₛ glue-inc φ {Tf = B} (λ { (φ = i1) → outS (fib 1=1) .fst })
ctr (inS (hcomp (φ ∨ ψ) sys))
(λ i → hfill (φ ∨ ψ) (~ i) sys)
,
ua-unglue-is-equiv: ∀ {ℓ} {A B : Type ℓ} (f : A ≃ B)
→ PathP (λ i → is-equiv (ua-unglue f i)) (f .snd) id-equiv
=
ua-unglue-is-equiv f (λ j → is-equiv-is-prop (ua-unglue f j)) (f .snd) id-equiv
is-prop→pathp
: ∀ {ℓ} {A B C : Type ℓ} {f : A ≃ B} {g : B ≃ C} → ua (f ∙e g) ≡ ua f ∙ ua g
ua∙ {ℓ = ℓ} {A} {B} {C} {f} {g} = ∙-unique (ua (f ∙e g)) λ i j → Glue C λ where
ua∙ (i = i0) → ua f j , (λ x → g .fst (ua-unglue f j x)) ,
(λ j → is-equiv-is-prop (λ x → g .fst (ua-unglue f j x)))
is-prop→pathp ((f ∙e g) .snd) (g .snd) j
(i = i1) → ua (f ∙e g) j , ua-unglue (f ∙e g) j , ua-unglue-is-equiv (f ∙e g) j
(j = i0) → A , f ∙e g
(j = i1) → ua g i , ua-unglue g i , ua-unglue-is-equiv g i
: ∀ {ℓ} {A B : Type ℓ} (e : A ≃ B) → sym (ua e) ≡ ua (e e⁻¹)
sym-ua {A = A} {B = B} e i j = Glue B λ where
sym-ua (i = i0) → ua e (~ j) , ua-unglue e (~ j) , ua-unglue-is-equiv e (~ j)
(i = i1) → ua (e e⁻¹) j , (λ x → e .fst (ua-unglue (e e⁻¹) j x)) ,
(λ j → is-equiv-is-prop λ x → e .fst (ua-unglue (e e⁻¹) j x))
is-prop→pathp (((e e⁻¹) ∙e e) .snd) (e .snd) j
(j = i0) → B , (λ x → Equiv.ε e x (~ i)) ,
(λ j → is-equiv-is-prop λ x → Equiv.ε e x (~ j))
is-prop→pathp (((e e⁻¹) ∙e e) .snd) i
id-equiv (j = i1) → A , e
: ∀ {ℓ ℓ'} {A₀ A₁ : Type ℓ} {e : A₀ ≃ A₁} {B : (i : I) → Type ℓ'}
ua→ {f₀ : A₀ → B i0} {f₁ : A₁ → B i1}
→ ((a : A₀) → PathP B (f₀ a) (f₁ (e .fst a)))
→ PathP (λ i → ua e i → B i) f₀ f₁
{B = B} {f₀ = f₀} {f₁} h i a =
ua→ (λ j → B (i ∨ ~ j)) (∂ i) λ where
comp (j = i0) → f₁ (unglue (∂ i) a)
j (i = i0) → h a (~ j)
j (i = i1) → f₁ a
j
: ∀ {ℓ ℓ' ℓ''} {A₀ A₁ : Type ℓ} {e₁ : A₀ ≃ A₁}
ua→2 {B₀ B₁ : Type ℓ'} {e₂ : B₀ ≃ B₁}
{C : (i : I) → Type ℓ''}
{f₀ : A₀ → B₀ → C i0} {f₁ : A₁ → B₁ → C i1}
→ (∀ a b → PathP C (f₀ a b) (f₁ (e₁ .fst a) (e₂ .fst b)))
→ PathP (λ i → ua e₁ i → ua e₂ i → C i) f₀ f₁
= ua→ (ua→ ∘ h)
ua→2 h
: ∀ {ℓ} {A B C : Type ℓ}
transport-∙ → (p : A ≡ B) (q : B ≡ C) (u : A)
→ transport (p ∙ q) u ≡ transport q (transport p u)
=
transport-∙ p q x i (∙-filler' p q (~ i)) (transport-filler-ext p i x)
transport
: ∀ {ℓ ℓ'} {A : Type ℓ} → (B : A → Type ℓ')
subst-∙ → {x y z : A} (p : x ≡ y) (q : y ≡ z) (u : B x)
→ subst B (p ∙ q) u ≡ subst B q (subst B p u)
=
subst-∙ B p q Bx i (ap B (∙-filler' p q (~ i))) (transport-filler-ext (ap B p) i Bx) transport
Not the fundamental theorem of engineering!↩︎
References
- Cohen, Cyril, Thierry Coquand, Simon Huber, and Anders Mörtberg. 2016. “Cubical Type Theory: A Constructive Interpretation of the Univalence Axiom.” https://arxiv.org/abs/1611.02108.