|
|
@ -138,6 +138,10 @@ funext : {A : Type} {B : A -> Type} {f : (x : A) -> B x} {g : (x : A) -> B x} |
|
|
|
-> Path f g |
|
|
|
funext h i x = h x i |
|
|
|
|
|
|
|
happly : {A : Type} {B : A -> Type} {f : (x : A) -> B x} {g : (x : A) -> B x} |
|
|
|
-> (p : Path f g) -> (x : A) -> Path (f x) (g x) |
|
|
|
happly p x i = p i x |
|
|
|
|
|
|
|
-- The proposition associated with an element of the interval |
|
|
|
------------------------------------------------------------- |
|
|
|
|
|
|
@ -251,10 +255,10 @@ comp : (A : I -> Type) {phi : I} (u : (i : I) -> Partial phi (A i)) -> Sub (A i0 |
|
|
|
|
|
|
|
trans : {A : Type} {x : A} {y : A} {z : A} -> PathP (\i -> A) x y -> PathP (\i -> A) y z -> PathP (\i -> A) x z |
|
|
|
trans {A} {x} p q i = |
|
|
|
comp (\i -> A) |
|
|
|
{ior i (inot i)} |
|
|
|
(\j [ (i = i0) -> x, (i = i1) -> q j ]) |
|
|
|
(inS (p i)) |
|
|
|
comp (\i -> A) |
|
|
|
{ior i (inot i)} |
|
|
|
(\j [ (i = i0) -> x, (i = i1) -> q j ]) |
|
|
|
(inS (p i)) |
|
|
|
|
|
|
|
-- In particular when the formula φ = i0 we get the "opposite face" to a |
|
|
|
-- single point, which corresponds to transport. |
|
|
@ -272,6 +276,12 @@ fill A {phi} u a0 i = |
|
|
|
(\j [ (phi = i1) as p -> u (iand i j) p, (i = i0) -> outS a0 ]) |
|
|
|
(inS (outS a0)) |
|
|
|
|
|
|
|
hfill : {A : Type} {phi : I} (u : (i : I) -> Partial phi A) -> Sub A phi (u i0) -> I -> A |
|
|
|
hfill {A} {phi} u a0 i = fill (\i -> A) {phi} u a0 i |
|
|
|
|
|
|
|
hcomp : {A : Type} {phi : I} (u : (i : I) -> Partial phi A) -> Sub A phi (u i0) -> A |
|
|
|
hcomp {A} {phi} u a0 = comp (\i -> A) {phi} u a0 |
|
|
|
|
|
|
|
-- For instance, the filler of the previous composition square |
|
|
|
-- tells us that trans p refl = p: |
|
|
|
|
|
|
@ -464,3 +474,192 @@ univalenceBeta {A} {B} f i a = |
|
|
|
-- Ian Orton, & Andrew M. Pitts. (2017). Decomposing the Univalence Axiom. |
|
|
|
-- |
|
|
|
-- Available freely here: https://arxiv.org/abs/1712.04890v3 |
|
|
|
|
|
|
|
J : {A : Type} {x : A} |
|
|
|
(P : (y : A) -> Path x y -> Type) |
|
|
|
(d : P x (\i -> x)) |
|
|
|
{y : A} (p : Path x y) |
|
|
|
-> P y p |
|
|
|
J P d p = transp (\i -> P (p i) (\j -> p (iand i j))) d |
|
|
|
|
|
|
|
|
|
|
|
-- Isomorphisms |
|
|
|
--------------- |
|
|
|
-- |
|
|
|
-- Since isomorphisms are a much more convenient notion of equivalence |
|
|
|
-- than contractible fibers, it's natural to ask why the CCHM paper, and |
|
|
|
-- this implementation following that, decided on the latter for our |
|
|
|
-- definition of equivalence. |
|
|
|
|
|
|
|
isIso : {A : Type} -> {B : Type} -> (A -> B) -> Type |
|
|
|
isIso {A} {B} f = (g : B -> A) * ((y : B) -> Path (f (g y)) y) * ((x : A) -> Path (g (f x)) x) |
|
|
|
|
|
|
|
-- The reason is that the family of types IsIso is not a proposition! |
|
|
|
-- This means that there can be more than one way for a function to be |
|
|
|
-- an equivalence. This is Lemma 4.1.1 of the HoTT book. |
|
|
|
|
|
|
|
Iso : Type -> Type -> Type |
|
|
|
Iso A B = (f : A -> B) * isIso f |
|
|
|
|
|
|
|
-- Nevertheless, we can prove that any function with an isomorphism |
|
|
|
-- structure has contractible fibers, using a cubical argument adapted |
|
|
|
-- from CCHM's implementation of cubical type theory: |
|
|
|
-- |
|
|
|
-- https://github.com/mortberg/cubicaltt/blob/master/experiments/isoToEquiv.ctt#L7-L55 |
|
|
|
|
|
|
|
IsoToEquiv : {A : Type} {B : Type} -> Iso A B -> Equiv A B |
|
|
|
IsoToEquiv {A} {B} iso = |
|
|
|
let |
|
|
|
f = iso.1 |
|
|
|
g = iso.2.1 |
|
|
|
s = iso.2.2.1 |
|
|
|
t = iso.2.2.2 |
|
|
|
|
|
|
|
lemIso : (y : B) (x0 : A) (x1 : A) (p0 : Path (f x0) y) (p1 : Path (f x1) y) |
|
|
|
-> PathP (\i -> fiber f y) (x0, p0) (x1, p1) |
|
|
|
lemIso y x0 x1 p0 p1 = |
|
|
|
let |
|
|
|
rem0 : Path x0 (g y) |
|
|
|
rem0 i = comp (\i -> A) (\k [ (i = i0) -> t x0 k, (i = i1) -> g y ]) (inS (g (p0 i))) |
|
|
|
|
|
|
|
rem1 : Path x1 (g y) |
|
|
|
rem1 i = comp (\i -> A) (\k [ (i = i0) -> t x1 k, (i = i1) -> g y ]) (inS (g (p1 i))) |
|
|
|
|
|
|
|
p : Path x0 x1 |
|
|
|
p i = comp (\i -> A) (\k [ (i = i0) -> rem0 (inot k), (i = i1) -> rem1 (inot k) ]) (inS (g y)) |
|
|
|
|
|
|
|
fill0 : I -> I -> A |
|
|
|
fill0 i j = comp (\i -> A) (\k [ (i = i0) -> t x0 (iand j k) |
|
|
|
, (i = i1) -> g y |
|
|
|
, (j = i0) -> g (p0 i) |
|
|
|
]) |
|
|
|
(inS (g (p0 i))) |
|
|
|
|
|
|
|
fill1 : I -> I -> A |
|
|
|
fill1 i j = comp (\i -> A) (\k [ (i = i0) -> t x1 (iand j k) |
|
|
|
, (i = i1) -> g y |
|
|
|
, (j = i0) -> g (p1 i) ]) |
|
|
|
(inS (g (p1 i))) |
|
|
|
|
|
|
|
fill2 : I -> I -> A |
|
|
|
fill2 i j = comp (\i -> A) (\k [ (i = i0) -> rem0 (ior j (inot k)) |
|
|
|
, (i = i1) -> rem1 (ior j (inot k)) |
|
|
|
, (j = i1) -> g y ]) |
|
|
|
(inS (g y)) |
|
|
|
|
|
|
|
sq : I -> I -> A |
|
|
|
sq i j = comp (\i -> A) (\k [ (i = i0) -> fill0 j (inot k) |
|
|
|
, (i = i1) -> fill1 j (inot k) |
|
|
|
, (j = i1) -> g y |
|
|
|
, (j = i0) -> t (p i) (inot k) ]) |
|
|
|
(inS (fill2 i j)) |
|
|
|
|
|
|
|
sq1 : I -> I -> B |
|
|
|
sq1 i j = comp (\i -> B) (\k [ (i = i0) -> s (p0 j) k |
|
|
|
, (i = i1) -> s (p1 j) k |
|
|
|
, (j = i0) -> s (f (p i)) k |
|
|
|
, (j = i1) -> s y k |
|
|
|
]) |
|
|
|
(inS (f (sq i j))) |
|
|
|
in \i -> (p i, \j -> sq1 i j) |
|
|
|
|
|
|
|
fCenter : (y : B) -> fiber f y |
|
|
|
fCenter y = (g y, s y) |
|
|
|
|
|
|
|
fIsCenter : (y : B) (w : fiber f y) -> Path (fCenter y) w |
|
|
|
fIsCenter y w = lemIso y (fCenter y).1 w.1 (fCenter y).2 w.2 |
|
|
|
in (f, \y -> (fCenter y, fIsCenter y)) |
|
|
|
|
|
|
|
-- We can prove that any involutive function is an isomorphism, since |
|
|
|
-- such a function is its own inverse. |
|
|
|
|
|
|
|
involToIso : {A : Type} (f : A -> A) -> ((x : A) -> Path (f (f x)) x) -> isIso f |
|
|
|
involToIso {A} f inv = (f, inv, inv) |
|
|
|
|
|
|
|
-- An example of univalence |
|
|
|
--------------------------- |
|
|
|
-- |
|
|
|
-- The classic example of univalence is the equivalence |
|
|
|
-- not : Bool \simeq Bool. |
|
|
|
-- |
|
|
|
-- We define it here. |
|
|
|
|
|
|
|
Bool : Type |
|
|
|
{-# PRIMITIVE Bool #-} |
|
|
|
|
|
|
|
true, false : Bool |
|
|
|
{-# PRIMITIVE true #-} |
|
|
|
{-# PRIMITIVE false #-} |
|
|
|
|
|
|
|
-- Pattern matching for booleans: If a proposition holds for true and |
|
|
|
-- for false, then it holds for every bool. |
|
|
|
elimBool : (P : Bool -> Type) -> P true -> P false -> (b : Bool) -> P b |
|
|
|
{-# PRIMITIVE if elimBool #-} |
|
|
|
|
|
|
|
-- Non-dependent elimination of booleans |
|
|
|
if : {A : Type} -> A -> A -> Bool -> A |
|
|
|
if {A} = elimBool (\b -> A) |
|
|
|
|
|
|
|
not : Bool -> Bool |
|
|
|
not = if false true |
|
|
|
|
|
|
|
-- By pattern matching it suffices to prove (not (not true)) ≡ true and |
|
|
|
-- not (not false) ≡ false. Since not (not true) computes to true (resp. |
|
|
|
-- false), both proofs go through by refl. |
|
|
|
notInvol : (x : Bool) -> Path (not (not x)) x |
|
|
|
notInvol = elimBool (\b -> Path (not (not b)) b) refl refl |
|
|
|
|
|
|
|
notp : Path Bool Bool |
|
|
|
notp = univalence (IsoToEquiv (not, involToIso not notInvol)) |
|
|
|
|
|
|
|
-- This path actually serves to prove a simple lemma about the universes |
|
|
|
-- of HoTT, namely, that any univalent universe is not a 0-type. If we |
|
|
|
-- had HITs, we could prove that this fact holds for any n, but for now, |
|
|
|
-- proving it's not an h-set is the furthest we can go. |
|
|
|
|
|
|
|
-- First we define what it means for something to be false. In type theory, |
|
|
|
-- we take ¬P = P → ⊥, where the bottom type is the only type satisfying |
|
|
|
-- the elimination principle |
|
|
|
-- |
|
|
|
-- elimBottom : (P : bottom -> Type) -> (b : bottom) -> P b |
|
|
|
-- |
|
|
|
-- This follows from setting bottom := ∀ A, A. |
|
|
|
|
|
|
|
bottom : Type |
|
|
|
bottom = {A : Type} -> A |
|
|
|
|
|
|
|
elimBottom : (P : bottom -> Type) -> (b : bottom) -> P b |
|
|
|
elimBottom P x = x |
|
|
|
|
|
|
|
-- We prove that true != false by transporting along the path |
|
|
|
-- |
|
|
|
-- \i -> if (Bool -> Bool) A (p i) |
|
|
|
-- (Bool -> Bool) ------------------------------------ A |
|
|
|
-- |
|
|
|
-- To verify that this has the correct endpoints, check out the endpoints |
|
|
|
-- for p: |
|
|
|
-- |
|
|
|
-- true ------------------------------------ false |
|
|
|
-- |
|
|
|
-- and evaluate the if at either end. |
|
|
|
|
|
|
|
trueNotFalse : Path true false -> bottom |
|
|
|
trueNotFalse p {A} = transp (\i -> if (Bool -> Bool) A (p i)) id |
|
|
|
|
|
|
|
-- To be an h-Set is to have no "higher path information". Alternatively, |
|
|
|
-- |
|
|
|
-- isHSet A = (x : A) (y : A) -> isHProp (Path x y) |
|
|
|
-- |
|
|
|
isHSet : Type -> Type |
|
|
|
isHSet A = {x : A} {y : A} (p : Path x y) (q : Path x y) -> Path p q |
|
|
|
|
|
|
|
-- We can prove *a* contradiction (note: this is a direct proof!) by adversarially |
|
|
|
-- choosing two paths p, q that we know are not equal. Since "equal" paths have |
|
|
|
-- equal behaviour when transporting, we can choose two paths p, q and a point x |
|
|
|
-- such that transporting x along p gives a different result from x along q. |
|
|
|
-- |
|
|
|
-- Since transp notp = not but transp refl = id, that's what we go with. The choice |
|
|
|
-- of false as the point x is just from the endpoints of trueNotFalse. |
|
|
|
|
|
|
|
universeNotSet : isHSet Type -> bottom |
|
|
|
universeNotSet itIs = trueNotFalse (\i -> transp (\j -> itIs notp refl i j) false) |