-- SOURCE URL: `https://agda.github.io/cubical/Agda.Builtin.Cubical.Equiv.html`
{-# OPTIONS --erased-cubical --safe --no-sized-types --no-guardedness #-}
module Agda.Builtin.Cubical.Equiv where
open import Agda.Primitive
open import Agda.Builtin.Sigma
open import Agda.Primitive.Cubical renaming (primINeg to ~_; primIMax to _∨_; primIMin to _∧_;
primHComp to hcomp; primTransp to transp; primComp to comp;
itIsOne to 1=1)
open import Agda.Builtin.Cubical.Path
open import Agda.Builtin.Cubical.Sub renaming (Sub to _[_↦_])
import Agda.Builtin.Cubical.HCompU as HCompU
module Helpers = HCompU.Helpers
open Helpers
-- We make this a record so that isEquiv can be proved using
-- copatterns. This is good because copatterns don't get unfolded
-- unless a projection is applied so it should be more efficient.
record isEquiv {ℓ ℓ'} {A : Set ℓ} {B : Set ℓ'} (f : A → B) : Set (ℓ ⊔ ℓ') where
no-eta-equality
field
equiv-proof : (y : B) → isContr (fiber f y)
open isEquiv public
infix 4 _≃_
_≃_ : ∀ {ℓ ℓ'} (A : Set ℓ) (B : Set ℓ') → Set (ℓ ⊔ ℓ')
A ≃ B = Σ (A → B) \ f → (isEquiv f)
equivFun : ∀ {ℓ ℓ'} {A : Set ℓ} {B : Set ℓ'} → A ≃ B → A → B
equivFun e = fst e
-- Improved version of equivProof compared to Lemma 5 in CCHM. We put
-- the (φ = i0) face in contr' making it be definitionally c in this
-- case. This makes the computational behavior better, in particular
-- for transp in Glue.
equivProof : ∀ {la lt} (T : Set la) (A : Set lt) → (w : T ≃ A) → (a : A)
→ ∀ ψ (f : Partial ψ (fiber (w .fst) a)) → fiber (w .fst) a [ ψ ↦ f ]
equivProof A B w a ψ fb =
inS (contr' {A = fiber (w .fst) a} (w .snd .equiv-proof a) ψ fb)
where
contr' : ∀ {ℓ} {A : Set ℓ} → isContr A → (φ : I) → (u : Partial φ A) → A
contr' {A = A} (c , p) φ u = hcomp (λ i → λ { (φ = i1) → p (u 1=1) i
; (φ = i0) → c }) c
{-# BUILTIN EQUIV _≃_ #-}
{-# BUILTIN EQUIVFUN equivFun #-}
{-# BUILTIN EQUIVPROOF equivProof #-}
module _ {ℓ : I → Level} (P : (i : I) → Set (ℓ i)) where
private
E : (i : I) → Set (ℓ i)
E = λ i → P i
~E : (i : I) → Set (ℓ (~ i))
~E = λ i → P (~ i)
A = P i0
B = P i1
f : A → B
f x = transp E i0 x
g : B → A
g y = transp ~E i0 y
u : ∀ i → A → E i
u i x = transp (λ j → E (i ∧ j)) (~ i) x
v : ∀ i → B → E i
v i y = transp (λ j → ~E ( ~ i ∧ j)) i y
fiberPath : (y : B) → (xβ0 xβ1 : fiber f y) → xβ0 ≡ xβ1
fiberPath y (x0 , β0) (x1 , β1) k = ω , λ j → δ (~ j) where
module _ (j : I) where
private
sys : A → ∀ i → PartialP (~ j ∨ j) (λ _ → E (~ i))
sys x i (j = i0) = v (~ i) y
sys x i (j = i1) = u (~ i) x
ω0 = comp ~E (sys x0) ((β0 (~ j)))
ω1 = comp ~E (sys x1) ((β1 (~ j)))
θ0 = fill ~E (sys x0) (inS (β0 (~ j)))
θ1 = fill ~E (sys x1) (inS (β1 (~ j)))
sys = λ {j (k = i0) → ω0 j ; j (k = i1) → ω1 j}
ω = hcomp sys (g y)
θ = hfill sys (inS (g y))
δ = λ (j : I) → comp E
(λ i → λ { (j = i0) → v i y ; (k = i0) → θ0 j (~ i)
; (j = i1) → u i ω ; (k = i1) → θ1 j (~ i) })
(θ j)
γ : (y : B) → y ≡ f (g y)
γ y j = comp E (λ i → λ { (j = i0) → v i y
; (j = i1) → u i (g y) }) (g y)
pathToisEquiv : isEquiv f
pathToisEquiv .equiv-proof y .fst .fst = g y
pathToisEquiv .equiv-proof y .fst .snd = sym (γ y)
pathToisEquiv .equiv-proof y .snd = fiberPath y _
pathToEquiv : A ≃ B
pathToEquiv .fst = f
pathToEquiv .snd = pathToisEquiv-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Axiom.Omniscience.html`
{-# OPTIONS --cubical --no-import-sorts #-}
module Cubical.Axiom.Omniscience where
open import Cubical.Foundations.Function
open import Cubical.Foundations.HLevels
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Transport
open import Cubical.Data.Bool
renaming (Bool to 𝟚; Bool→Type to ⟨_⟩)
open import Cubical.Data.Empty as Empty
open import Cubical.Data.Sum as Sum
open import Cubical.HITs.PropositionalTruncation as PT
open import Cubical.Relation.Nullary
private
variable
ℓ ℓ' : Level
A : Type ℓ
-- Lesser limited principle of omniscience
--
-- If two decidable predicates cannot both be satisfied, we can
-- determine that one predicate cannot be satisfied.
LLPO : Type ℓ → Type ℓ
LLPO A
= ∀(P Q : A → 𝟚)
→ (∀ x y → ⟨ P x ⟩ → ⟨ Q y ⟩ → ⊥)
→ ∥ (∀ x → ¬ ⟨ P x ⟩) ⊎ (∀ y → ¬ ⟨ Q y ⟩) ∥₁
isPropLLPO : isProp (LLPO A)
isPropLLPO = isPropΠ3 λ _ _ _ → squash₁
-- As above, but without ensuring propositionality
LLPO∞ : Type ℓ → Type ℓ
LLPO∞ A
= ∀(P Q : A → 𝟚)
→ (∀ x y → ⟨ P x ⟩ → ⟨ Q y ⟩ → ⊥)
→ (∀ x → ¬ ⟨ P x ⟩) ⊎ (∀ y → ¬ ⟨ Q y ⟩)
LLPO∞→LLPO : LLPO∞ A → LLPO A
LLPO∞→LLPO llpo' P Q ¬both = ∣ llpo' P Q ¬both ∣₁
-- Weak limited principle of omniscience
--
-- It is decidable whether or not a decidable predicate never holds.
WLPO : Type ℓ → Type ℓ
WLPO A = ∀(P : A → 𝟚) → Dec (∀ x → ¬ ⟨ P x ⟩)
WLPO' : Type ℓ → Type ℓ
WLPO' A = ∀(P : A → 𝟚) → Dec (P ≡ const false)
isPropWLPO : isProp (WLPO A)
isPropWLPO = isPropΠ λ P → isPropDec (isPropΠ λ x → isProp¬ ⟨ P x ⟩)
isPropWLPO' : isProp (WLPO' A)
isPropWLPO' = isPropΠ λ P → isPropDec (isSet→ isSetBool P (const false))
module WLPO≃ where
points : (P : A → 𝟚) → P ≡ const false → ∀ x → ¬ ⟨ P x ⟩
points P p x = subst (λ Q → ⟨ Q x ⟩) p
total : (P : A → 𝟚) → (∀ x → ¬ ⟨ P x ⟩) → P ≡ const false
total P never i x with P x | never x
... | false | _ = false
... | true | ¬⊤ = Empty.rec {A = true ≡ false} (¬⊤ _) i
open Iso
total≡points : ∀(P : A → 𝟚) → (P ≡ const false) ≡ (∀ x → ¬ ⟨ P x ⟩)
total≡points P = isoToPath λ where
.fun → points P
.inv → total P
.sec never → isPropΠ (λ x → isProp¬ ⟨ P x ⟩) _ never
.ret α≡f → isSet→ isSetBool P (const false) _ α≡f
WLPO≡WLPO' : WLPO A ≡ WLPO' A
WLPO≡WLPO' {A = A} i = (P : A → 𝟚) → Dec (WLPO≃.total≡points P (~ i))
WLPO→LLPO∞ : WLPO A → LLPO∞ A
WLPO→LLPO∞ {A = A} womn P Q ¬both with womn P
... | yes ∀¬P = inl ∀¬P
... | no ¬∀¬P = inr ∀¬Q where
∀¬Q : ∀ y → ¬ ⟨ Q y ⟩
∀¬Q y Qy = ¬∀¬P (λ x Px → ¬both x y Px Qy)
-- Limited principle of omniscience
--
-- Either a decidable predicate never holds, or it does
LPO : Type ℓ → Type ℓ
LPO A = ∀(P : A → 𝟚) → (∀ x → ¬ ⟨ P x ⟩) ⊎ ∥ Σ[ x ∈ A ] ⟨ P x ⟩ ∥₁
LPO→WLPO : LPO A → WLPO A
LPO→WLPO omn P with omn P
... | inl ∀¬P = yes ∀¬P
... | inr ∃P = no λ ∀¬P → PT.rec isProp⊥ (uncurry ∀¬P) ∃P
-- As above, but without truncation.
LPO∞ : Type ℓ → Type ℓ
LPO∞ A = ∀(P : A → 𝟚) → (∀ x → ¬ ⟨ P x ⟩) ⊎ (Σ[ x ∈ A ] ⟨ P x ⟩)
LPO∞→LPO : LPO∞ A → LPO A
LPO∞→LPO omn P = Sum.map (idfun _) ∣_∣₁ (omn P)-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Categories.Category.Base`
module Cubical.Categories.Category.Base where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.HLevels
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Powerset
open import Cubical.Data.Sigma
private
variable
ℓ ℓ' : Level
-- Categories with hom-sets
record Category ℓ ℓ' : Type (ℓ-suc (ℓ-max ℓ ℓ')) where
-- TODO: document the impetus for this change
no-eta-equality
field
ob : Type ℓ
Hom[_,_] : ob → ob → Type ℓ'
id : ∀ {x} → Hom[ x , x ]
_⋆_ : ∀ {x y z} (f : Hom[ x , y ]) (g : Hom[ y , z ]) → Hom[ x , z ]
⋆IdL : ∀ {x y} (f : Hom[ x , y ]) → id ⋆ f ≡ f
⋆IdR : ∀ {x y} (f : Hom[ x , y ]) → f ⋆ id ≡ f
⋆Assoc : ∀ {x y z w} (f : Hom[ x , y ]) (g : Hom[ y , z ]) (h : Hom[ z , w ])
→ (f ⋆ g) ⋆ h ≡ f ⋆ (g ⋆ h)
isSetHom : ∀ {x y} → isSet Hom[ x , y ]
-- composition: alternative to diagramatic order
_∘_ : ∀ {x y z} (g : Hom[ y , z ]) (f : Hom[ x , y ]) → Hom[ x , z ]
g ∘ f = f ⋆ g
⟨_⟩⋆⟨_⟩ : {x y z : ob} {f f' : Hom[ x , y ]} {g g' : Hom[ y , z ]}
→ f ≡ f' → g ≡ g' → f ⋆ g ≡ f' ⋆ g'
⟨ ≡f ⟩⋆⟨ ≡g ⟩ = cong₂ _⋆_ ≡f ≡g
infixr 9 _⋆_
infixr 9 _∘_
open Category
-- Helpful syntax/notation
_[_,_] : (C : Category ℓ ℓ') → (x y : C .ob) → Type ℓ'
_[_,_] = Hom[_,_]
_End[_] : (C : Category ℓ ℓ') → (x : C .ob) → Type ℓ'
C End[ x ] = C [ x , x ]
-- Needed to define this in order to be able to make the subsequence syntax declaration
seq' : ∀ (C : Category ℓ ℓ') {x y z} (f : C [ x , y ]) (g : C [ y , z ]) → C [ x , z ]
seq' = _⋆_
infixl 15 seq'
syntax seq' C f g = f ⋆⟨ C ⟩ g
-- composition
comp' : ∀ (C : Category ℓ ℓ') {x y z} (g : C [ y , z ]) (f : C [ x , y ]) → C [ x , z ]
comp' = _∘_
infixr 16 comp'
syntax comp' C g f = g ∘⟨ C ⟩ f
-- Isomorphisms and paths in categories
record isIso (C : Category ℓ ℓ'){x y : C .ob}(f : C [ x , y ]) : Type ℓ' where
constructor isiso
field
inv : C [ y , x ]
sec : inv ⋆⟨ C ⟩ f ≡ C .id
ret : f ⋆⟨ C ⟩ inv ≡ C .id
open isIso
isPropIsIso : {C : Category ℓ ℓ'}{x y : C .ob}(f : C [ x , y ]) → isProp (isIso C f)
isPropIsIso {C = C} f p q i .inv =
(sym (C .⋆IdL _)
∙ (λ i → q .sec (~ i) ⋆⟨ C ⟩ p .inv)
∙ C .⋆Assoc _ _ _
∙ (λ i → q .inv ⋆⟨ C ⟩ p .ret i)
∙ C .⋆IdR _) i
isPropIsIso {C = C} f p q i .sec j =
isSet→SquareP (λ i j → C .isSetHom)
(p .sec) (q .sec) (λ i → isPropIsIso {C = C} f p q i .inv ⋆⟨ C ⟩ f) refl i j
isPropIsIso {C = C} f p q i .ret j =
isSet→SquareP (λ i j → C .isSetHom)
(p .ret) (q .ret) (λ i → f ⋆⟨ C ⟩ isPropIsIso {C = C} f p q i .inv) refl i j
CatIso : (C : Category ℓ ℓ') (x y : C .ob) → Type ℓ'
CatIso C x y = Σ[ f ∈ C [ x , y ] ] isIso C f
CatIso≡ : {C : Category ℓ ℓ'}{x y : C .ob}(f g : CatIso C x y) → f .fst ≡ g .fst → f ≡ g
CatIso≡ f g = Σ≡Prop isPropIsIso
-- `constructor` of CatIso
catiso : {C : Category ℓ ℓ'}{x y : C .ob}
→ (mor : C [ x , y ])
→ (inv : C [ y , x ])
→ (sec : inv ⋆⟨ C ⟩ mor ≡ C .id)
→ (ret : mor ⋆⟨ C ⟩ inv ≡ C .id)
→ CatIso C x y
catiso mor inv sec ret = mor , isiso inv sec ret
idCatIso : {C : Category ℓ ℓ'} {x : C .ob} → CatIso C x x
idCatIso {C = C} = C .id , isiso (C .id) (C .⋆IdL (C .id)) (C .⋆IdL (C .id))
isSet-CatIso : {C : Category ℓ ℓ'} → ∀ x y → isSet (CatIso C x y)
isSet-CatIso {C = C} x y = isOfHLevelΣ 2 (C .isSetHom) (λ f → isProp→isSet (isPropIsIso f))
pathToIso : {C : Category ℓ ℓ'} {x y : C .ob} (p : x ≡ y) → CatIso C x y
pathToIso {C = C} p = J (λ z _ → CatIso C _ z) idCatIso p
pathToIso-refl : {C : Category ℓ ℓ'} {x : C .ob} → pathToIso {C = C} {x} refl ≡ idCatIso
pathToIso-refl {C = C} {x} = JRefl (λ z _ → CatIso C x z) (idCatIso)
-- Univalent Categories
record isUnivalent (C : Category ℓ ℓ') : Type (ℓ-max ℓ ℓ') where
field
univ : (x y : C .ob) → isEquiv (pathToIso {C = C} {x = x} {y = y})
-- package up the univalence equivalence
univEquiv : ∀ (x y : C .ob) → (x ≡ y) ≃ (CatIso _ x y)
univEquiv x y = pathToIso , univ x y
-- The function extracting paths from category-theoretic isomorphisms.
CatIsoToPath : {x y : C .ob} (p : CatIso _ x y) → x ≡ y
CatIsoToPath = invEq (univEquiv _ _)
isGroupoid-ob : isGroupoid (C .ob)
isGroupoid-ob = isOfHLevelPath'⁻ 2 (λ _ _ → isOfHLevelRespectEquiv 2 (invEquiv (univEquiv _ _)) (isSet-CatIso _ _))
isPropIsUnivalent : {C : Category ℓ ℓ'} → isProp (isUnivalent C)
isPropIsUnivalent =
isPropRetract isUnivalent.univ _ (λ _ → refl)
(isPropΠ2 λ _ _ → isPropIsEquiv _ )
-- Opposite category
-- TODO: move all of this to Constructions.Opposite?
_^op : Category ℓ ℓ' → Category ℓ ℓ'
ob (C ^op) = ob C
Hom[_,_] (C ^op) x y = C [ y , x ]
id (C ^op) = id C
_⋆_ (C ^op) f g = g ⋆⟨ C ⟩ f
⋆IdL (C ^op) = C .⋆IdR
⋆IdR (C ^op) = C .⋆IdL
⋆Assoc (C ^op) f g h = sym (C .⋆Assoc _ _ _)
isSetHom (C ^op) = C .isSetHom
ΣPropCat : (C : Category ℓ ℓ') (P : ℙ (ob C)) → Category ℓ ℓ'
ob (ΣPropCat C P) = Σ[ x ∈ ob C ] x ∈ P
Hom[_,_] (ΣPropCat C P) x y = C [ fst x , fst y ]
id (ΣPropCat C P) = id C
_⋆_ (ΣPropCat C P) = _⋆_ C
⋆IdL (ΣPropCat C P) = ⋆IdL C
⋆IdR (ΣPropCat C P) = ⋆IdR C
⋆Assoc (ΣPropCat C P) = ⋆Assoc C
isSetHom (ΣPropCat C P) = isSetHom C
isIsoΣPropCat : {C : Category ℓ ℓ'} {P : ℙ (ob C)}
{x y : ob C} (p : x ∈ P) (q : y ∈ P)
(f : C [ x , y ])
→ isIso C f → isIso (ΣPropCat C P) {x , p} {y , q} f
inv (isIsoΣPropCat p q f isIsoF) = isIsoF .inv
sec (isIsoΣPropCat p q f isIsoF) = isIsoF .sec
ret (isIsoΣPropCat p q f isIsoF) = isIsoF .ret-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Cohomology.EilenbergMacLane.Base.html`
{-# OPTIONS --lossy-unification #-}
module Cubical.Cohomology.EilenbergMacLane.Base where
open import Cubical.Homotopy.EilenbergMacLane.GroupStructure
open import Cubical.Homotopy.EilenbergMacLane.Base
open import Cubical.Homotopy.EilenbergMacLane.Properties
open import Cubical.Homotopy.EilenbergMacLane.Order2
open import Cubical.Homotopy.Connected
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Function
open import Cubical.Foundations.Transport
open import Cubical.Foundations.HLevels
open import Cubical.Foundations.GroupoidLaws
open import Cubical.Foundations.Path
open import Cubical.Foundations.Pointed
open import Cubical.Foundations.Pointed.Homogeneous
open import Cubical.Foundations.Isomorphism
open import Cubical.HITs.PropositionalTruncation as PT
open import Cubical.HITs.Truncation as TR
open import Cubical.Data.Nat
open import Cubical.Data.Sigma
open import Cubical.Algebra.Group.Base
open import Cubical.Algebra.Group.MorphismProperties
open import Cubical.Algebra.Group.Morphisms
open import Cubical.Algebra.AbGroup.Base
open import Cubical.Algebra.Monoid
open import Cubical.Algebra.Semigroup
open import Cubical.Algebra.Group.Instances.IntMod
open import Cubical.Algebra.AbGroup.Instances.IntMod
open import Cubical.Algebra.AbGroup.Instances.DirectProduct
open import Cubical.Algebra.AbGroup.Properties
open import Cubical.HITs.SetTruncation as ST
hiding (rec ; map ; elim ; elim2 ; elim3)
private
variable
ℓ ℓ' : Level
open IsAbGroup
open IsGroup
open IsSemigroup
open IsMonoid
open AbGroupStr
-- cohomology groups
coHom : (n : ℕ) (G : AbGroup ℓ) (A : Type ℓ') → Type _
coHom n G A = ∥ (A → EM G n) ∥₂
module _ {n : ℕ} {G : AbGroup ℓ} {A : Type ℓ'} where
_+ₕ_ : coHom n G A → coHom n G A → coHom n G A
_+ₕ_ = ST.rec2 squash₂ λ f g → ∣ (λ x → f x +ₖ g x) ∣₂
-ₕ_ : coHom n G A → coHom n G A
-ₕ_ = ST.map λ f x → -ₖ f x
_-ₕ_ : coHom n G A → coHom n G A → coHom n G A
_-ₕ_ = ST.rec2 squash₂ λ f g → ∣ (λ x → f x -ₖ g x) ∣₂
module _ (n : ℕ) {G : AbGroup ℓ} {A : Type ℓ'} where
+ₕ-syntax : coHom n G A → coHom n G A → coHom n G A
+ₕ-syntax = _+ₕ_
-ₕ-syntax : coHom n G A → coHom n G A
-ₕ-syntax = -ₕ_
-'ₕ-syntax : coHom n G A → coHom n G A → coHom n G A
-'ₕ-syntax = _-ₕ_
syntax +ₕ-syntax n x y = x +[ n ]ₕ y
syntax -ₕ-syntax n x = -[ n ]ₕ x
syntax -'ₕ-syntax n x y = x -[ n ]ₕ y
module _ (n : ℕ) {G : AbGroup ℓ} {A : Type ℓ'} where
0ₕ : coHom n G A
0ₕ = ∣ (λ _ → 0ₖ n) ∣₂
rUnitₕ : (x : coHom n G A) → x +ₕ 0ₕ ≡ x
rUnitₕ = ST.elim (λ _ → isSetPathImplicit)
λ f → cong ∣_∣₂ (funExt λ x → rUnitₖ n (f x))
lUnitₕ : (x : coHom n G A) → 0ₕ +[ n ]ₕ x ≡ x
lUnitₕ = ST.elim (λ _ → isSetPathImplicit)
λ f → cong ∣_∣₂ (funExt λ x → lUnitₖ n (f x))
commₕ : (x y : coHom n G A) → x +ₕ y ≡ y +ₕ x
commₕ = ST.elim2 (λ _ _ → isSetPathImplicit)
λ f g → cong ∣_∣₂ (funExt λ x → commₖ n (f x) (g x))
assocₕ : (x y z : coHom n G A) → x +ₕ (y +ₕ z) ≡ (x +ₕ y) +ₕ z
assocₕ = ST.elim3 (λ _ _ _ → isSetPathImplicit)
λ f g h → cong ∣_∣₂ (funExt λ x → assocₖ n (f x) (g x) (h x))
rCancelₕ : (x : coHom n G A) → x +ₕ (-ₕ x) ≡ 0ₕ
rCancelₕ = ST.elim (λ _ → isSetPathImplicit)
λ f → cong ∣_∣₂ (funExt λ x → rCancelₖ n (f x))
lCancelₕ : (x : coHom n G A) → (-ₕ x) +ₕ x ≡ 0ₕ
lCancelₕ = ST.elim (λ _ → isSetPathImplicit)
λ f → cong ∣_∣₂ (funExt λ x → lCancelₖ n (f x))
coHomGr : (n : ℕ) (G : AbGroup ℓ) (A : Type ℓ') → AbGroup (ℓ-max ℓ ℓ')
fst (coHomGr n G A) = coHom n G A
0g (snd (coHomGr n G A)) = 0ₕ n
AbGroupStr._+_ (snd (coHomGr n G A)) = _+ₕ_
- snd (coHomGr n G A) = -ₕ_
is-set (isSemigroup (isMonoid (isGroup (isAbGroup (snd (coHomGr n G A)))))) = squash₂
·Assoc (isSemigroup (isMonoid (isGroup (isAbGroup (snd (coHomGr n G A)))))) = assocₕ n
·IdR (isMonoid (isGroup (isAbGroup (snd (coHomGr n G A))))) = rUnitₕ n
·IdL (isMonoid (isGroup (isAbGroup (snd (coHomGr n G A))))) = lUnitₕ n
·InvR (isGroup (isAbGroup (snd (coHomGr n G A)))) = rCancelₕ n
·InvL (isGroup (isAbGroup (snd (coHomGr n G A)))) = lCancelₕ n
+Comm (isAbGroup (snd (coHomGr n G A))) = commₕ n
-- reduced cohomology groups
coHomRed : (n : ℕ) (G : AbGroup ℓ) (A : Pointed ℓ') → Type _
coHomRed n G A = ∥ (A →∙ EM∙ G n) ∥₂
0ₕ∙ : (n : ℕ) {G : AbGroup ℓ} {A : Pointed ℓ'} → coHomRed n G A
0ₕ∙ n = ∣ (λ _ → 0ₖ n) , refl ∣₂
-- operations
module _ {n : ℕ} {G : AbGroup ℓ} {A : Pointed ℓ'} where
_+ₕ∙_ : coHomRed n G A → coHomRed n G A → coHomRed n G A
_+ₕ∙_ = ST.rec2 squash₂
λ f g → ∣ (λ x → fst f x +ₖ fst g x)
, cong₂ _+ₖ_ (snd f) (snd g) ∙ rUnitₖ n (0ₖ n) ∣₂
-ₕ∙_ : coHomRed n G A → coHomRed n G A
-ₕ∙_ = ST.map λ f → (λ x → -ₖ (fst f x))
, cong -ₖ_ (snd f)
∙ -0ₖ n
-- group laws
-- Note that→∙Homogeneous≡ (in Foundations.Pointed.Homogeneous) is
-- purposely avoided to minimise the size of the proof terms
module coHomRedAxioms (n : ℕ) {G : AbGroup ℓ} {A : Pointed ℓ'} where
commₕ∙ : (x y : coHomRed n G A) → x +ₕ∙ y ≡ y +ₕ∙ x
commₕ∙ =
ST.elim2 (λ _ _ → isSetPathImplicit)
λ f g → cong ∣_∣₂ (ΣPathP (funExt (λ x → commₖ n (fst f x) (fst g x))
, help n _ (sym (snd f)) _ (sym (snd g))))
where
help : (n : ℕ) (f0 : EM G n) (f1 : 0ₖ n ≡ f0)
(g0 : EM G n) (g1 : 0ₖ n ≡ g0)
→ PathP (λ i → commₖ n f0 g0 i ≡ 0ₖ n)
(sym (cong₂ _+ₖ_ f1 g1) ∙ rUnitₖ n (0ₖ n))
(sym (cong₂ _+ₖ_ g1 f1) ∙ rUnitₖ n (0ₖ n))
help zero _ _ _ _ =
isOfHLevelPathP' 0 (is-set (snd G) _ _) _ _ .fst
help (suc zero) = J> (J> refl)
help (suc (suc n)) = J> (J> refl)
rCancelₕ∙ : (x : coHomRed n G A) → (x +ₕ∙ (-ₕ∙ x)) ≡ 0ₕ∙ n
rCancelₕ∙ =
ST.elim (λ _ → isSetPathImplicit)
λ f → cong ∣_∣₂ (ΣPathP ((funExt (λ x → rCancelₖ n (fst f x)))
, help n _ (sym (snd f))))
where
help : (n : ℕ) (f0 : EM G n) (f1 : 0ₖ n ≡ f0)
→ PathP (λ i → rCancelₖ n f0 i ≡ 0ₖ n)
(cong₂ _+ₖ_ (sym f1) (cong -ₖ_ (sym f1) ∙ -0ₖ n)
∙ rUnitₖ n (0ₖ n))
refl
help zero _ _ = isOfHLevelPathP' 0 (is-set (snd G) _ _) _ _ .fst
help (suc zero) = J> (sym (rUnit _) ∙ sym (rUnit _))
help (suc (suc n)) = J> (sym (rUnit _) ∙ sym (rUnit _))
lCancelₕ∙ : (x : coHomRed n G A) → ((-ₕ∙ x) +ₕ∙ x) ≡ 0ₕ∙ n
lCancelₕ∙ x = commₕ∙ (-ₕ∙ x) x ∙ rCancelₕ∙ x
rUnitₕ∙ : (x : coHomRed n G A) → (x +ₕ∙ 0ₕ∙ n) ≡ x
rUnitₕ∙ = ST.elim (λ _ → isSetPathImplicit)
λ f → cong ∣_∣₂ (ΣPathP ((funExt λ x → rUnitₖ n (fst f x))
, help n _ (sym (snd f))))
where
help : (n : ℕ) (f0 : EM G n) (f1 : 0ₖ n ≡ f0)
→ PathP (λ i → rUnitₖ n f0 i ≡ 0ₖ n)
(cong (_+ₖ 0ₖ n) (sym f1) ∙ rUnitₖ n (0ₖ n))
(sym f1)
help zero _ _ = isOfHLevelPathP' 0 (is-set (snd G) _ _) _ _ .fst
help (suc zero) = J> sym (rUnit refl)
help (suc (suc n)) = J> sym (rUnit refl)
lUnitₕ∙ : (x : coHomRed n G A) → (0ₕ∙ n +ₕ∙ x) ≡ x
lUnitₕ∙ = ST.elim (λ _ → isSetPathImplicit)
λ f → cong ∣_∣₂ (ΣPathP ((funExt (λ x → lUnitₖ n (fst f x)))
, help n _ (sym (snd f))))
where
help : (n : ℕ) (f0 : EM G n) (f1 : 0ₖ n ≡ f0)
→ PathP (λ i → lUnitₖ n f0 i ≡ 0ₖ n)
(cong (0ₖ n +ₖ_) (sym f1) ∙ rUnitₖ n (0ₖ n))
(sym f1)
help zero _ _ = isOfHLevelPathP' 0 (is-set (snd G) _ _) _ _ .fst
help (suc zero) = J> sym (rUnit refl)
help (suc (suc n)) = J> sym (rUnit refl)
assocₕ∙ : (x y z : coHomRed n G A) → x +ₕ∙ (y +ₕ∙ z) ≡ (x +ₕ∙ y) +ₕ∙ z
assocₕ∙ =
ST.elim3 (λ _ _ _ → isSetPathImplicit)
λ f g h → cong ∣_∣₂
(ΣPathP ((funExt (λ x → assocₖ n (fst f x) (fst g x) (fst h x)))
, help n _ (sym (snd f)) _ (sym (snd g)) _ (sym (snd h))))
where
help : (n : ℕ) (f0 : EM G n) (f1 : 0ₖ n ≡ f0)
(g0 : EM G n) (g1 : 0ₖ n ≡ g0)
(h0 : EM G n) (h1 : 0ₖ n ≡ h0)
→ PathP (λ i → assocₖ n f0 g0 h0 i ≡ 0ₖ n)
(cong₂ _+ₖ_ (sym f1)
(cong₂ _+ₖ_ (sym g1) (sym h1) ∙ rUnitₖ n (0ₖ n))
∙ rUnitₖ n (0ₖ n))
(cong₂ _+ₖ_ (cong₂ _+ₖ_ (sym f1) (sym g1)
∙ rUnitₖ n (0ₖ n)) (sym h1) ∙ rUnitₖ n (0ₖ n))
help zero _ _ _ _ _ _ = isOfHLevelPathP' 0 (is-set (snd G) _ _) _ _ .fst
help (suc zero) =
J> (J> (J> cong (_∙ refl)
(cong (cong₂ _+ₖ_ refl) (sym (rUnit refl))
∙ (cong (λ z → cong₂ (+ₖ-syntax {G = G} 1) z (refl {x = 0ₖ {G = G} 1}))
(rUnit refl)))))
help (suc (suc n)) =
J> (J> (J> flipSquare ((sym (rUnit refl))
◁ flipSquare (cong (_∙ refl)
(cong (cong₂ _+ₖ_ refl) (sym (rUnit refl))
∙ (cong (λ z → cong₂ (+ₖ-syntax {G = G} (suc (suc n))) z
(refl {x = 0ₖ {G = G} (suc (suc n))}))
(rUnit refl)))))))
coHomRedGr : (n : ℕ) (G : AbGroup ℓ) (A : Pointed ℓ') → AbGroup _
fst (coHomRedGr n G A) = coHomRed n G A
0g (snd (coHomRedGr n G A)) = 0ₕ∙ n
AbGroupStr._+_ (snd (coHomRedGr n G A)) = _+ₕ∙_
- snd (coHomRedGr n G A) = -ₕ∙_
is-set (isSemigroup (isMonoid (isGroup (isAbGroup (snd (coHomRedGr n G A)))))) = squash₂
·Assoc (isSemigroup (isMonoid (isGroup (isAbGroup (snd (coHomRedGr n G A)))))) = coHomRedAxioms.assocₕ∙ n
·IdR (isMonoid (isGroup (isAbGroup (snd (coHomRedGr n G A))))) = coHomRedAxioms.rUnitₕ∙ n
·IdL (isMonoid (isGroup (isAbGroup (snd (coHomRedGr n G A))))) = coHomRedAxioms.lUnitₕ∙ n
·InvR (isGroup (isAbGroup (snd (coHomRedGr n G A)))) = coHomRedAxioms.rCancelₕ∙ n
·InvL (isGroup (isAbGroup (snd (coHomRedGr n G A)))) = coHomRedAxioms.lCancelₕ∙ n
+Comm (isAbGroup (snd (coHomRedGr n G A))) = coHomRedAxioms.commₕ∙ n
coHom≅coHomRed : (n : ℕ) (G : AbGroup ℓ) (A : Pointed ℓ')
→ AbGroupEquiv (coHomGr (suc n) G (fst A)) (coHomRedGr (suc n) G A)
coHom≅coHomRed n G A =
GroupIso→GroupEquiv (invGroupIso main)
where
con-lem : (n : ℕ) (x : EM G (suc n)) → ∥ x ≡ 0ₖ (suc n) ∥₁
con-lem n =
EM-raw'-elim G (suc n)
(λ _ → isProp→isOfHLevelSuc (suc n) squash₁)
(EM-raw'-trivElim G n (λ _ → isProp→isOfHLevelSuc n squash₁)
∣ EM-raw'→EM∙ G (suc n) ∣₁)
main : GroupIso _ _
Iso.fun (fst main) = ST.map fst
Iso.inv (fst main) = ST.map λ f → (λ x → f x -ₖ f (pt A))
, rCancelₖ (suc n) (f (pt A))
Iso.sec (fst main) =
ST.elim (λ _ → isSetPathImplicit)
λ f → PT.rec (squash₂ _ _)
(λ p → cong ∣_∣₂
(funExt λ x → cong (λ z → f x +ₖ z)
(cong -ₖ_ p ∙ -0ₖ (suc n)) ∙ rUnitₖ (suc n) (f x)))
(con-lem n (f (pt A)))
Iso.ret (fst main) =
ST.elim (λ _ → isSetPathImplicit)
λ f → cong ∣_∣₂ (→∙Homogeneous≡ (isHomogeneousEM (suc n))
(funExt λ x → cong (fst f x +ₖ_) (cong -ₖ_ (snd f) ∙ -0ₖ (suc n))
∙ rUnitₖ (suc n) (fst f x)))
snd main =
makeIsGroupHom (ST.elim2 (λ _ _ → isSetPathImplicit)
λ _ _ → refl)
coHom⁰≅coHomRed⁰ : (G : AbGroup ℓ) (A : Pointed ℓ)
→ AbGroupEquiv (AbDirProd (coHomRedGr 0 G A) G) (coHomGr 0 G (typ A))
fst (coHom⁰≅coHomRed⁰ G A) = isoToEquiv is
where
is : Iso _ _
Iso.fun is = uncurry (ST.rec (isSetΠ (λ _ → squash₂))
λ f g → ∣ (λ x → AbGroupStr._+_ (snd G) (fst f x) g) ∣₂)
Iso.inv is = ST.rec (isSet× squash₂ (is-set (snd G)))
λ f → ∣ (λ x → AbGroupStr._-_ (snd G) (f x) (f (pt A)))
, +InvR (snd G) (f (pt A)) ∣₂ , f (pt A)
Iso.sec is = ST.elim (λ _ → isSetPathImplicit)
λ f → cong ∣_∣₂ (funExt λ x
→ sym (+Assoc (snd G) _ _ _)
∙∙ cong (AbGroupStr._+_ (snd G) (f x))
(+InvL (snd G) (f (pt A)))
∙∙ +IdR (snd G) (f x))
Iso.ret is =
uncurry (ST.elim
(λ _ → isSetΠ (λ _ → isOfHLevelPath 2
(isSet× squash₂ (is-set (snd G))) _ _))
λ f → λ g
→ ΣPathP (cong ∣_∣₂ (Σ≡Prop (λ _ → is-set (snd G) _ _)
(funExt (λ x → cong₂ (AbGroupStr._+_ (snd G))
refl
(cong (- (snd G))
(cong₂ (AbGroupStr._+_ (snd G)) (snd f) refl
∙ +IdL (snd G) g))
∙ sym (+Assoc (snd G) _ _ _)
∙ cong (AbGroupStr._+_ (snd G) (fst f x))
(+InvR (snd G) g)
∙ +IdR (snd G) (f .fst x))))
, (cong (λ x → AbGroupStr._+_ (snd G) x g) (snd f)
∙ +IdL (snd G) g)))
snd (coHom⁰≅coHomRed⁰ G A) =
makeIsGroupHom (uncurry (ST.elim (λ _ → isSetΠ2 λ _ _ → isSetPathImplicit)
λ f1 g1 → uncurry (ST.elim (λ _ → isSetΠ λ _ → isSetPathImplicit)
λ f2 g2 → cong ∣_∣₂ (funExt λ a → AbGroupTheory.comm-4 G _ _ _ _))))
-- ℤ/2 lemmas
+ₕ≡id-ℤ/2 : ∀ {ℓ} {A : Type ℓ} (n : ℕ) (x : coHom n ℤ/2 A) → x +ₕ x ≡ 0ₕ n
+ₕ≡id-ℤ/2 n =
ST.elim (λ _ → isSetPathImplicit)
λ f → cong ∣_∣₂ (funExt λ x → +ₖ≡id-ℤ/2 n (f x))
-ₕConst-ℤ/2 : (n : ℕ) {A : Type ℓ} (x : coHom n ℤ/2 A) → -ₕ x ≡ x
-ₕConst-ℤ/2 zero =
ST.elim (λ _ → isSetPathImplicit)
λ f → cong ∣_∣₂ (funExt λ x → -Const-ℤ/2 (f x))
-ₕConst-ℤ/2 (suc n) =
ST.elim (λ _ → isSetPathImplicit)
λ f → cong ∣_∣₂ (funExt λ x → -ₖConst-ℤ/2 n (f x))
coHomFun : ∀ {ℓ''} {A : Type ℓ} {B : Type ℓ'} {G : AbGroup ℓ''}
(n : ℕ) (f : A → B)
→ coHom n G B → coHom n G A
coHomFun n f = ST.map λ g x → g (f x)
coHomHom : ∀ {ℓ''} {A : Type ℓ} {B : Type ℓ'} {G : AbGroup ℓ''}
(n : ℕ) (f : A → B)
→ AbGroupHom (coHomGr n G B) (coHomGr n G A)
fst (coHomHom n f) = coHomFun n f
snd (coHomHom n f) =
makeIsGroupHom (ST.elim2 (λ _ _ → isOfHLevelPath 2 squash₂ _ _)
λ f g → refl)
coHomEquiv : ∀ {ℓ''} {A : Type ℓ} {B : Type ℓ'} {G : AbGroup ℓ''}
(n : ℕ)
→ (Iso A B)
→ AbGroupEquiv (coHomGr n G B) (coHomGr n G A)
fst (coHomEquiv n f) = isoToEquiv is
where
is : Iso _ _
Iso.fun is = coHomFun n (Iso.fun f)
Iso.inv is = coHomFun n (Iso.inv f)
Iso.sec is =
ST.elim (λ _ → isSetPathImplicit)
λ g → cong ∣_∣₂ (funExt λ x → cong g (Iso.ret f x))
Iso.ret is =
ST.elim (λ _ → isSetPathImplicit)
λ g → cong ∣_∣₂ (funExt λ x → cong g (Iso.sec f x))
snd (coHomEquiv n f) = snd (coHomHom n (Iso.fun f))
coHomFun∙ : ∀ {ℓ''} {A : Pointed ℓ} {B : Pointed ℓ'} {G : AbGroup ℓ''}
(n : ℕ) (f : A →∙ B)
→ coHomRed n G B → coHomRed n G A
coHomFun∙ n f = ST.map λ g → g ∘∙ f
coHomHom∙ : ∀ {ℓ''} {A : Pointed ℓ} {B : Pointed ℓ'} {G : AbGroup ℓ''}
(n : ℕ) (f : A →∙ B)
→ AbGroupHom (coHomRedGr n G B) (coHomRedGr n G A)
fst (coHomHom∙ n f) = coHomFun∙ n f
snd (coHomHom∙ n f) =
makeIsGroupHom (ST.elim2 (λ _ _ → isSetPathImplicit)
λ g h → cong ∣_∣₂ (→∙Homogeneous≡ (isHomogeneousEM n) refl))
substℕ-coHom : {A : Type ℓ} {G : AbGroup ℓ'} {n m : ℕ}
→ (p : n ≡ m)
→ AbGroupEquiv (coHomGr n G A) (coHomGr m G A)
fst (substℕ-coHom {A = A} {G = G} p) =
substEquiv' (λ i → coHom i G A) p
snd (substℕ-coHom {A = A} {G = G} p) =
makeIsGroupHom
λ x y →
J (λ m p → subst (λ i → coHom i G A) p (x +ₕ y)
≡ (subst (λ i → coHom i G A) p x
+ₕ subst (λ i → coHom i G A) p y))
(transportRefl _ ∙ cong₂ _+ₕ_
(sym (transportRefl x)) (sym (transportRefl y))) p
substℕ-coHomRed : {A : Pointed ℓ} {G : AbGroup ℓ'} {n m : ℕ}
→ (p : n ≡ m)
→ AbGroupEquiv (coHomRedGr n G A) (coHomRedGr m G A)
fst (substℕ-coHomRed {A = A} {G = G} p) =
substEquiv' (λ i → coHomRed i G A) p
snd (substℕ-coHomRed {A = A} {G = G} p) =
makeIsGroupHom
λ x y →
J (λ m p → subst (λ i → coHomRed i G A) p (x +ₕ∙ y)
≡ (subst (λ i → coHomRed i G A) p x
+ₕ∙ subst (λ i → coHomRed i G A) p y))
(transportRefl _ ∙ cong₂ _+ₕ∙_
(sym (transportRefl x)) (sym (transportRefl y))) p
subst-EM-0ₖ : ∀{ℓ} {G : AbGroup ℓ} {n m : ℕ} (p : n ≡ m)
→ subst (EM G) p (0ₖ n) ≡ 0ₖ m
subst-EM-0ₖ {G = G} {n = n} =
J (λ m p → subst (EM G) p (0ₖ n) ≡ 0ₖ m) (transportRefl _)
subst-EM∙ : ∀ {ℓ} {G : AbGroup ℓ} {n m : ℕ} (p : n ≡ m)
→ EM∙ G n →∙ EM∙ G m
fst (subst-EM∙ {G = G} p) = subst (EM G) p
snd (subst-EM∙ p) = subst-EM-0ₖ p
coHomPointedElim : ∀ {ℓ ℓ' ℓ''} {G : AbGroup ℓ}
{A : Type ℓ'} (n : ℕ) (a : A) {B : coHom (suc n) G A → Type ℓ''}
→ ((x : coHom (suc n) G A) → isProp (B x))
→ ((f : A → EM G (suc n)) → f a ≡ 0ₖ (suc n) → B ∣ f ∣₂)
→ (x : coHom (suc n) G A) → B x
coHomPointedElim {ℓ'' = ℓ''} {G = G} {A = A} n a isprop indp =
ST.elim (λ _ → isOfHLevelSuc 1 (isprop _))
λ f → helper n isprop indp f
where
helper : (n : ℕ) {B : coHom (suc n) G A → Type ℓ''}
→ ((x : coHom (suc n) G A) → isProp (B x))
→ ((f : A → EM G (suc n)) → f a ≡ 0ₖ (suc n) → B ∣ f ∣₂)
→ (f : A → EM G (suc n))
→ B ∣ f ∣₂
helper n isprop ind f =
TR.rec (isProp→isOfHLevelSuc n (isprop _))
(ind f)
(isConnectedPath (suc n) (isConnectedEM (suc n)) (f a) (0ₖ (suc n)) .fst)
coHomTruncEquiv : {A : Type ℓ} (G : AbGroup ℓ) (n : ℕ)
→ AbGroupEquiv (coHomGr n G (∥ A ∥ (suc (suc n)))) (coHomGr n G A)
fst (coHomTruncEquiv G n) =
isoToEquiv (setTruncIso (univTrunc (suc (suc n)) {B = _ , hLevelEM G n}))
snd (coHomTruncEquiv G n) =
makeIsGroupHom (ST.elim2 (λ _ _ → isSetPathImplicit)
λ _ _ → refl)
EM→-charac : ∀ {ℓ ℓ'} {A : Pointed ℓ} {G : AbGroup ℓ'} (n : ℕ)
→ Iso (fst A → EM G n) ((A →∙ EM∙ G n) × EM G n)
Iso.fun (EM→-charac {A = A} n) f =
((λ x → f x -ₖ f (pt A)) , rCancelₖ n (f (pt A))) , f (pt A)
Iso.inv (EM→-charac n) (f , a) x = fst f x +ₖ a
Iso.sec (EM→-charac {A = A} n) ((f , p) , a) =
ΣPathP (→∙Homogeneous≡ (isHomogeneousEM _)
(funExt (λ x → (λ i → (f x +ₖ a) -ₖ (cong (_+ₖ a) p ∙ lUnitₖ n a) i)
∙ sym (assocₖ n (f x) a (-ₖ a))
∙ cong (f x +ₖ_) (rCancelₖ n a)
∙ rUnitₖ n (f x)))
, cong (_+ₖ a) p ∙ lUnitₖ n a)
Iso.ret (EM→-charac {A = A} n) f =
funExt λ x → sym (assocₖ n (f x) (-ₖ f (pt A)) (f (pt A)))
∙∙ cong (f x +ₖ_) (lCancelₖ n (f (pt A)))
∙∙ rUnitₖ n (f x)-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Data.Empty.Properties.html`
module Cubical.Data.Empty.Properties where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Isomorphism
open import Cubical.Data.Empty.Base
isProp⊥ : isProp ⊥
isProp⊥ ()
isProp⊥* : ∀ {ℓ} → isProp {ℓ} ⊥*
isProp⊥* _ ()
isContr⊥→A : ∀ {ℓ} {A : Type ℓ} → isContr (⊥ → A)
fst isContr⊥→A ()
snd isContr⊥→A f i ()
isContrΠ⊥ : ∀ {ℓ} {A : ⊥ → Type ℓ} → isContr ((x : ⊥) → A x)
fst isContrΠ⊥ ()
snd isContrΠ⊥ f i ()
isContrΠ⊥* : ∀ {ℓ ℓ'} {A : ⊥* {ℓ} → Type ℓ'} → isContr ((x : ⊥*) → A x)
fst isContrΠ⊥* ()
snd isContrΠ⊥* f i ()
uninhabEquiv : ∀ {ℓ ℓ'} {A : Type ℓ} {B : Type ℓ'}
→ (A → ⊥) → (B → ⊥) → A ≃ B
uninhabEquiv ¬a ¬b = isoToEquiv isom
where
open Iso
isom : Iso _ _
isom .fun a = rec (¬a a)
isom .inv b = rec (¬b b)
isom .sec b = rec (¬b b)
isom .ret a = rec (¬a a)-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Data.Equality.Conversion.html`
{- Conversion between paths and the inductively defined equality type
- Path and _≡_ are equal (Path≡Eq)
- conversion between dependent paths and PathP (pathOver→PathP and PathP→pathOver)
- cong-PathP→apd-pathOver for HIT β rules (see S¹ loop case)
-}
module Cubical.Data.Equality.Conversion where
open import Cubical.Foundations.Prelude
hiding (_≡_ ; step-≡ ; _∎ ; isPropIsContr)
renaming ( refl to reflPath
; transport to transportPath
; J to JPath
; JRefl to JPathRefl
; sym to symPath
; _∙_ to compPath
; cong to congPath
; subst to substPath
; substRefl to substPathReflPath
; funExt to funExtPath
; isContr to isContrPath
; isProp to isPropPath
)
open import Cubical.Foundations.Equiv
renaming ( fiber to fiberPath
; isEquiv to isEquivPath
; _≃_ to EquivPath
; equivFun to equivFunPath
; isPropIsEquiv to isPropIsEquivPath
)
hiding ( equivCtr
; equivIsEquiv )
open import Cubical.Foundations.Isomorphism
using ()
renaming ( Iso to IsoPath
; iso to isoPath
; isoToPath to isoPathToPath
; isoToEquiv to isoPathToEquivPath
)
open import Cubical.Data.Equality.Base
private
variable
a b ℓ ℓ' : Level
A : Type a
B : Type b
x y z : A
--------------------------------------------------------------------------------
-- Paths
congPathd : {C : A → Type ℓ} (f : (x : A) → C x) {x y : A} (p : Path A x y) → Path (C y) (substPath C p (f x)) (f y)
congPathd f p = fromPathP (congPath f p)
-- Equality between Path and equality
eqToPath : {x y : A} → x ≡ y → Path A x y
eqToPath refl = reflPath
pathToEq : {x y : A} → Path A x y → x ≡ y
pathToEq {x = x} = JPath (λ y _ → x ≡ y) refl
pathToEq-reflPath : {x : A} → pathToEq reflPath ≡ refl {x = x}
pathToEq-reflPath {x = x} = pathToEq (JPathRefl (λ y _ → x ≡ y) refl)
eqToPath-pathToEq : {x y : A} → (p : Path A x y) → Path _ (eqToPath (pathToEq p)) p
eqToPath-pathToEq p =
JPath (λ _ h → Path _ (eqToPath (pathToEq h)) h)
(congPath eqToPath (transportRefl refl)) p
pathToEq-eqToPath : {x y : A} → (p : x ≡ y) → Path _ (pathToEq (eqToPath p)) p
pathToEq-eqToPath refl = transportRefl refl
PathIsoEq : {x y : A} → IsoPath (Path A x y) (x ≡ y)
PathIsoEq = isoPath pathToEq eqToPath pathToEq-eqToPath eqToPath-pathToEq
PathPathEq : {x y : A} → Path _ (Path A x y) (x ≡ y)
PathPathEq = isoPathToPath PathIsoEq
Path≡Eq : {x y : A} → (Path A x y) ≡ (x ≡ y)
Path≡Eq = pathToEq PathPathEq
happly : {B : A → Type ℓ} {f g : (x : A) → B x} → f ≡ g → (x : A) → f x ≡ g x
happly refl x = refl
-- We get funExt by going back and forth between Path and Eq
funExt : {B : A → Type ℓ} {f g : (x : A) → B x} → ((x : A) → f x ≡ g x) → f ≡ g
funExt p = pathToEq (λ i x → eqToPath (p x) i)
funExtRefl : {B : A → Type ℓ} {f : (x : A) → B x} → funExt (λ x → refl {x = f x}) ≡ refl
funExtRefl = pathToEq-reflPath
Σ≡Prop : {P : A → Type ℓ} → ((x : A) → isProp (P x)) → {u v : Σ A P} → u .pr₁ ≡ v .pr₁ → u ≡ v
Σ≡Prop p {v = (x , y)} refl = ap (x ,_) (p x _ y)
-- Some lemmas relating the definitions for Path and ≡
substPath≡transport' : (C : A → Type ℓ) {x y : A} (b : C x) (p : x ≡ y) → substPath C (eqToPath p) b ≡ transport C p b
substPath≡transport' C b refl = pathToEq (transportRefl b)
substPath≡transport : (C : A → Type ℓ) {x y : A} (b : C x) (p : Path _ x y) → substPath C p b ≡ transport C (pathToEq p) b
substPath≡transport C b p = ap (λ x → substPath C x b) (pathToEq (symPath (eqToPath-pathToEq p)))
∙ substPath≡transport' C b (pathToEq p)
congPath≡ap : {x y : A} → (f : A → B) (p : x ≡ y) → congPath f (eqToPath p) ≡ eqToPath (ap f p)
congPath≡ap f refl = refl
ap≡congPath : {x y : A} → (f : A → B) (p : Path A x y) → ap f (pathToEq p) ≡ pathToEq (congPath f p)
ap≡congPath {x = x} f p = JPath (λ _ q → ap f (pathToEq q) ≡ pathToEq (congPath f q)) rem p
where
rem : ap f (transp (λ i → x ≡ x) i0 refl) ≡ transp (λ i → f x ≡ f x) i0 refl
rem = pathToEq (compPath (λ i → ap f (transportRefl refl i)) (symPath (transportRefl refl)))
-- Functions for going between the various definitions. This could
-- also be achieved by making lines in the universe and transporting
-- back and forth along them.
fiberPathToFiber : {f : A → B} {y : B} → fiberPath f y → fiber f y
fiberPathToFiber (x , p) = (x , pathToEq p)
fiberToFiberPath : {f : A → B} {y : B} → fiber f y → fiberPath f y
fiberToFiberPath (x , p) = (x , eqToPath p)
fiberToFiber : {f : A → B} {y : B} (p : fiber f y) → Path _ (fiberPathToFiber (fiberToFiberPath p)) p
fiberToFiber (x , p) i = x , pathToEq-eqToPath p i
fiberPathToFiberPath : {f : A → B} {y : B} (p : fiberPath f y) → Path _ (fiberToFiberPath (fiberPathToFiber p)) p
fiberPathToFiberPath (x , p) i = x , eqToPath-pathToEq p i
isContrPathToIsContr : isContrPath A → isContr A
isContrPathToIsContr (ctr , p) = (ctr , λ y → pathToEq (p y))
isContrToIsContrPath : isContr A → isContrPath A
isContrToIsContrPath (ctr , p) = (ctr , λ y → eqToPath (p y))
isPropPathToIsProp : isPropPath A → isProp A
isPropPathToIsProp H x y = pathToEq (H x y)
isPropToIsPropPath : isProp A → isPropPath A
isPropToIsPropPath H x y = eqToPath (H x y)
-- Specialized helper lemmas for going back and forth between
-- isContrPath and isContr:
private
helper1 : {A B : Type ℓ} (f : A → B) (g : B → A) (h : ∀ y → Path _ (f (g y)) y)
→ isContrPath A → isContr B
helper1 f g h (x , p) =
(f x , λ y → pathToEq (λ i → hcomp (λ j → λ { (i = i0) → f x
; (i = i1) → h y j })
(f (p (g y) i))))
helper2 : {A B : Type ℓ} (f : A → B) (g : B → A) (h : ∀ y → Path _ (g (f y)) y)
→ isContr B → isContrPath A
helper2 {A = A} f g h (x , p) = (g x , λ y → eqToPath (ap g (p (f y)) ∙ pathToEq (h y)))
-- This proof is essentially the one for proving that isContr with
-- Path is a proposition, but as we are working with ≡ we have to
-- insert a lot of conversion functions.
-- TODO: prove this directly following the HoTT proof?
isPropIsContr : (p1 p2 : isContr A) → Path (isContr A) p1 p2
isPropIsContr (a0 , p0) (a1 , p1) j =
( eqToPath (p0 a1) j ,
hcomp (λ i → λ { (j = i0) → λ x → pathToEq-eqToPath (p0 x) i
; (j = i1) → λ x → pathToEq-eqToPath (p1 x) i })
(λ x → pathToEq (λ i → hcomp (λ k → λ { (i = i0) → eqToPath (p0 a1) j
; (i = i1) → eqToPath (p0 x) (j ∨ k)
; (j = i0) → eqToPath (p0 x) (i ∧ k)
; (j = i1) → eqToPath (p1 x) i })
(eqToPath (p0 (eqToPath (p1 x) i)) j))))
-- We now prove that isEquiv is a proposition
isPropIsEquiv : {A B : Type ℓ} {f : A → B} (h1 h2 : isEquiv f) → Path _ h1 h2
equiv-proof (isPropIsEquiv h1 h2 i) y = isPropIsContr (h1 .equiv-proof y) (h2 .equiv-proof y) i
equivToEquivPath : A ≃ B → EquivPath A B
equivToEquivPath (f , p) =
(f , λ { .equiv-proof y → helper2 fiberPathToFiber fiberToFiberPath fiberPathToFiberPath (p .equiv-proof y) })
-- Go from a Path equivalence to an ≡ equivalence
equivPathToEquiv : EquivPath A B → A ≃ B
equivPathToEquiv (f , p) =
(f , λ { .equiv-proof y → helper1 fiberPathToFiber fiberToFiberPath fiberToFiber (p .equiv-proof y) })
equivToEquiv : {A B : Type ℓ} (p : A ≃ B) → Path _ (equivPathToEquiv (equivToEquivPath p)) p
equivToEquiv (f , p) i =
(f , isPropIsEquiv (λ { .equiv-proof y → helper1 fiberPathToFiber fiberToFiberPath fiberToFiber
(helper2 fiberPathToFiber fiberToFiberPath fiberPathToFiberPath (p .equiv-proof y)) }) p i)
equivPathToEquivPath : {A B : Type ℓ} (p : EquivPath A B) → Path _ (equivToEquivPath (equivPathToEquiv p)) p
equivPathToEquivPath (f , p) i =
( f , isPropIsEquivPath f (equivToEquivPath (equivPathToEquiv (f , p)) .snd) p i )
equivPath≡Equiv : {A B : Type ℓ} → Path _ (EquivPath A B) (A ≃ B)
equivPath≡Equiv {ℓ} = isoPathToPath (isoPath (equivPathToEquiv {ℓ}) equivToEquivPath equivToEquiv equivPathToEquivPath)
path≡Eq : {A B : Type ℓ} → Path _ (Path _ A B) (A ≡ B)
path≡Eq = isoPathToPath (isoPath pathToEq eqToPath pathToEq-eqToPath eqToPath-pathToEq)
--------------------------------------------------------------------------------
-- Isomorphisms
record Iso {ℓ ℓ'} (A : Type ℓ) (B : Type ℓ') : Type (ℓ-max ℓ ℓ') where
no-eta-equality
constructor iso
pattern
field
fun : A → B
inv : B → A
sec : (b : B) → fun (inv b) ≡ b
ret : (a : A) → inv (fun a) ≡ a
isoToIsoPath : Iso A B → IsoPath A B
isoToIsoPath (iso f g η ε) = isoPath f g (λ b → eqToPath (η b)) (λ a → eqToPath (ε a))
isoToEquiv : Iso A B → A ≃ B
isoToEquiv f = equivPathToEquiv (isoPathToEquivPath (isoToIsoPath f))
--------------------------------------------------------------------------------
-- dependent paths and PathP
-- similar to https://www.cse.chalmers.se/~nad/listings/equality/Equality.Path.Isomorphisms.html
-- used for eliminators and β rules for HITs
transportPathToEq→transportPath : (P : A → Type ℓ) (p : Path A x y) (u : P x) → transport P (pathToEq p) u ≡ substPath P p u
transportPathToEq→transportPath {x = x} P = JPath (λ y p → (u : P x) → transport P (pathToEq p) u ≡ substPath P p u)
λ u → ap (λ t → transport P t u) pathToEq-reflPath ∙ sym (pathToEq (substPathReflPath {B = P} u))
module _ (P : A → Type ℓ) {x y : A} {u : P x} {v : P y} where
pathOver→PathP : (p : Path _ x y) → transport P (pathToEq p) u ≡ v → PathP (λ i → P (p i)) u v
pathOver→PathP p q =
JPath (λ y p → (v : P y) → transport P (pathToEq p) u ≡ v → PathP (λ i → P (p i)) u v)
(λ v q → eqToPath (ap (λ r → transport P r u) (sym pathToEq-reflPath) ∙ q)) p v q
PathP→pathOver : (p : Path _ x y) → PathP (λ i → P (p i)) u v → transport P (pathToEq p) u ≡ v
PathP→pathOver p q = JPath (λ y p → (v : P y) (q : PathP (λ i → P (p i)) u v) → transport P (pathToEq p) u ≡ v)
(λ v q → ap (λ t → transport P t u) pathToEq-reflPath ∙ pathToEq q) p _ q
module _ (P : A → Type ℓ) {x : A} {u v : P x} where
pathOver→PathP-reflPath : (q : transport P (pathToEq reflPath) u ≡ v) →
pathOver→PathP P reflPath q ≡ eqToPath (ap (λ t → transport P t u) (sym pathToEq-reflPath) ∙ q)
pathOver→PathP-reflPath q = pathToEq λ i →
JPathRefl (λ y p → (v : P y) → transport P (pathToEq p) u ≡ v → PathP (λ i → P (p i)) u v)
(λ v q → eqToPath (ap (λ r → transport P r u) (sym pathToEq-reflPath) ∙ q)) i _ q
PathP→pathOver-reflPath : (q : PathP (λ i → P x) u v) →
PathP→pathOver P reflPath q ≡ ap (λ t → transport P t u) pathToEq-reflPath ∙ pathToEq q
PathP→pathOver-reflPath q = pathToEq λ i →
JPathRefl (λ y p → (v : P y) (q : PathP (λ i → P (p i)) u v) → transport P (pathToEq p) u ≡ v)
(λ v q → ap (λ t → transport P t u) pathToEq-reflPath ∙ pathToEq q) i _ q
apd-pathToEq≡PathP→pathOver-cong : {P : A → Type ℓ} {x y : A} (f : (x : A) → P x) (p : Path _ x y) →
apd f (pathToEq p) ≡ PathP→pathOver P p (congPath f p)
apd-pathToEq≡PathP→pathOver-cong {P = P} {x = x} f = JPath (λ _ p → apd f (pathToEq p) ≡ PathP→pathOver P p (congPath f p))
let step1 = sym (apd (λ (p : x ≡ x) → apd f p) (sym pathToEq-reflPath))
step2 = transport-path (λ p → transport P p (f x)) (λ _ → f x) (sym pathToEq-reflPath) refl
step3 = ap (λ t → sym (ap (λ p → transport P p (f x)) (sym pathToEq-reflPath)) ∙ refl ∙ t)
(ap-const {A = x ≡ x} (sym pathToEq-reflPath) (f x))
step4 = ap (λ t → sym t ∙ refl) (sym (sym-ap (λ p → transport P p (f x)) pathToEq-reflPath))
step5 = ap (_∙ refl) (sym-invol (ap (λ p → transport P p (f x)) pathToEq-reflPath))
step6 = ap (ap (λ t → transport P t (f x)) pathToEq-reflPath ∙_) (sym pathToEq-reflPath)
step7 = sym (PathP→pathOver-reflPath P reflPath)
in apd f (pathToEq reflPath) ≡⟨ step1 ⟩
transport (λ p → transport P p (f x) ≡ f x) (sym pathToEq-reflPath) refl ≡⟨ step2 ⟩
sym (ap (λ p → transport P p (f x)) (sym pathToEq-reflPath)) ∙ refl ∙ ap (λ (_ : x ≡ x) → f x) (sym pathToEq-reflPath) ≡⟨ step3 ⟩
sym (ap (λ p → transport P p (f x)) (sym pathToEq-reflPath)) ∙ refl ≡⟨ step4 ⟩
sym (sym (ap (λ p → transport P p (f x)) pathToEq-reflPath)) ∙ refl ≡⟨ step5 ⟩
ap (λ t → transport P t (f x)) pathToEq-reflPath ∙ refl ≡⟨ step6 ⟩
ap (λ t → transport P t (f x)) pathToEq-reflPath ∙ pathToEq reflPath ≡⟨ step7 ⟩
PathP→pathOver P reflPath reflPath ∎
module _ (P : A → Type ℓ) {x y : A} {u : P x} {v : P y} where
-- TODO
-- PathP→pathOver→PathP : (p : Path _ x y) (q : PathP (λ i → P (p i)) u v) → pathOver→PathP P p (PathP→pathOver P p q) ≡ q
-- PathP→pathOver→PathP p q = {!!}
pathOver→PathP→pathOver : (p : Path _ x y) (q : transport P (pathToEq p) u ≡ v) → PathP→pathOver P p (pathOver→PathP P p q) ≡ q
pathOver→PathP→pathOver p q =
JPath (λ y p → {v : P y} (q : transport P (pathToEq p) u ≡ v) → PathP→pathOver P p (pathOver→PathP P p q) ≡ q) (λ q →
let step1 = ap (PathP→pathOver P reflPath) (pathOver→PathP-reflPath P q)
step2 = PathP→pathOver-reflPath P (eqToPath (ap (λ t → transport P t u) (sym pathToEq-reflPath) ∙ q))
step3 = ap (ap (λ t → transport P t u) pathToEq-reflPath ∙_)
(pathToEq (pathToEq-eqToPath (ap (λ t → transport P t u) (sym pathToEq-reflPath) ∙ q)))
step4 = sym (assoc (ap (λ t → transport P t u) pathToEq-reflPath) (ap (λ t → transport P t u) (sym pathToEq-reflPath)) q)
step5 = ap (_∙ q) (sym (ap-∙ (λ t → transport P t u) pathToEq-reflPath (sym pathToEq-reflPath)))
step6 = ap (λ t → ap (λ t → transport P t u) t ∙ q) (invR pathToEq-reflPath)
in PathP→pathOver P reflPath (pathOver→PathP P reflPath q) ≡⟨ step1 ⟩
PathP→pathOver P reflPath (eqToPath (ap (λ t → transport P t u) (sym pathToEq-reflPath) ∙ q)) ≡⟨ step2 ⟩
ap (λ t → transport P t u) pathToEq-reflPath ∙ pathToEq (eqToPath (ap (λ t → transport P t u) (sym pathToEq-reflPath) ∙ q)) ≡⟨ step3 ⟩
ap (λ t → transport P t u) pathToEq-reflPath ∙ ap (λ t → transport P t u) (sym pathToEq-reflPath) ∙ q ≡⟨ step4 ⟩
(ap (λ t → transport P t u) pathToEq-reflPath ∙ ap (λ t → transport P t u) (sym pathToEq-reflPath)) ∙ q ≡⟨ step5 ⟩
ap (λ t → transport P t u) (pathToEq-reflPath ∙ sym pathToEq-reflPath) ∙ q ≡⟨ step6 ⟩
q ∎) p q
cong-PathP→apd-pathOver : (P : A → Type ℓ) {x y : A} (f : (x : A) → P x)
→ (p : Path _ x y) (q : transport P (pathToEq p) (f x) ≡ f y)
→ congPath f p ≡ pathOver→PathP P p q → apd f (pathToEq p) ≡ q
cong-PathP→apd-pathOver {A = A} P {x = x} f p q r =
apd f (pathToEq p) ≡⟨ apd-pathToEq≡PathP→pathOver-cong f p ⟩
PathP→pathOver P p (congPath f p) ≡⟨ ap (PathP→pathOver P p) r ⟩
PathP→pathOver P p (pathOver→PathP P p q) ≡⟨ pathOver→PathP→pathOver P p q ⟩
q ∎-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Data.Int.MoreInts.QuoInt.Base.html`
-- Define the integers as a HIT by identifying +0 and -0
module Cubical.Data.Int.MoreInts.QuoInt.Base where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Transport
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Univalence
open import Cubical.Relation.Nullary
open import Cubical.Data.Int using ()
renaming (ℤ to Int ; discreteℤ to discreteInt ; isSetℤ to isSetInt ; 0≢1-ℤ to 0≢1-Int)
open import Cubical.Data.Nat as ℕ using (ℕ; zero; suc)
open import Cubical.Data.Bool as Bool using (Bool; not; notnot)
variable
l : Level
Sign : Type₀
Sign = Bool
pattern spos = Bool.false
pattern sneg = Bool.true
_·S_ : Sign → Sign → Sign
_·S_ = Bool._⊕_
data ℤ : Type₀ where
signed : (s : Sign) (n : ℕ) → ℤ
posneg : signed spos 0 ≡ signed sneg 0
pattern pos n = signed spos n
pattern neg n = signed sneg n
sign : ℤ → Sign
sign (signed _ zero) = spos
sign (signed s (suc _)) = s
sign (posneg i) = spos
sign-pos : ∀ n → sign (pos n) ≡ spos
sign-pos zero = refl
sign-pos (suc n) = refl
abs : ℤ → ℕ
abs (signed _ n) = n
abs (posneg i) = zero
signed-inv : ∀ n → signed (sign n) (abs n) ≡ n
signed-inv (pos zero) = refl
signed-inv (neg zero) = posneg
signed-inv (signed s (suc n)) = refl
signed-inv (posneg i) j = posneg (i ∧ j)
signed-zero : ∀ s₁ s₂ → signed s₁ zero ≡ signed s₂ zero
signed-zero spos spos = refl
signed-zero sneg sneg = refl
signed-zero spos sneg = posneg
signed-zero sneg spos = sym posneg
rec : ∀ {A : Type l} → (pos' neg' : ℕ → A) → pos' 0 ≡ neg' 0 → ℤ → A
rec pos' neg' eq (pos m) = pos' m
rec pos' neg' eq (neg m) = neg' m
rec pos' neg' eq (posneg i) = eq i
elim : ∀ (P : ℤ → Type l)
→ (pos' : ∀ n → P (pos n))
→ (negsuc' : ∀ n → P (neg (suc n)))
→ ∀ z → P z
elim P pos' negsuc' (pos n) = pos' n
elim P pos' negsuc' (neg zero) = subst P posneg (pos' zero)
elim P pos' negsuc' (neg (suc n)) = negsuc' n
elim P pos' negsuc' (posneg i) = subst-filler P posneg (pos' zero) i
Int→ℤ : Int → ℤ
Int→ℤ (Int.pos n) = pos n
Int→ℤ (Int.negsuc n) = neg (suc n)
ℤ→Int : ℤ → Int
ℤ→Int (pos n) = Int.pos n
ℤ→Int (neg zero) = Int.pos 0
ℤ→Int (neg (suc n)) = Int.negsuc n
ℤ→Int (posneg _) = Int.pos 0
ℤ→Int→ℤ : ∀ (n : ℤ) → Int→ℤ (ℤ→Int n) ≡ n
ℤ→Int→ℤ (pos n) _ = pos n
ℤ→Int→ℤ (neg zero) i = posneg i
ℤ→Int→ℤ (neg (suc n)) _ = neg (suc n)
ℤ→Int→ℤ (posneg j) i = posneg (j ∧ i)
Int→ℤ→Int : ∀ (n : Int) → ℤ→Int (Int→ℤ n) ≡ n
Int→ℤ→Int (Int.pos n) _ = Int.pos n
Int→ℤ→Int (Int.negsuc n) _ = Int.negsuc n
isoIntℤ : Iso Int ℤ
isoIntℤ = iso Int→ℤ ℤ→Int ℤ→Int→ℤ Int→ℤ→Int
Int≡ℤ : Int ≡ ℤ
Int≡ℤ = isoToPath isoIntℤ
discreteℤ : Discrete ℤ
discreteℤ = subst Discrete Int≡ℤ discreteInt
isSetℤ : isSet ℤ
isSetℤ = subst isSet Int≡ℤ isSetInt
-_ : ℤ → ℤ
- signed s n = signed (not s) n
- posneg i = posneg (~ i)
negate-invol : ∀ n → - - n ≡ n
negate-invol (signed s n) i = signed (notnot s i) n
negate-invol (posneg i) _ = posneg i
negateEquiv : ℤ ≃ ℤ
negateEquiv = isoToEquiv (iso -_ -_ negate-invol negate-invol)
negateEq : ℤ ≡ ℤ
negateEq = ua negateEquiv
infixl 6 _+_
infixl 7 _·_
sucℤ : ℤ → ℤ
sucℤ (pos n) = pos (suc n)
sucℤ (neg zero) = pos 1
sucℤ (neg (suc n)) = neg n
sucℤ (posneg _) = pos 1
predℤ : ℤ → ℤ
predℤ = subst (λ Z → (Z → Z)) negateEq sucℤ
-- definitionally equal to λ n → - (sucℤ (- n))
-- strictly more useful than the direct pattern matching version,
-- see negateSuc and negatePred
sucPredℤ : ∀ n → sucℤ (predℤ n) ≡ n
sucPredℤ (pos zero) = sym posneg
sucPredℤ (pos (suc _)) = refl
sucPredℤ (neg _) = refl
sucPredℤ (posneg i) j = posneg (i ∨ ~ j)
predSucℤ : ∀ n → predℤ (sucℤ n) ≡ n
predSucℤ (pos _) = refl
predSucℤ (neg zero) = posneg
predSucℤ (neg (suc _)) = refl
predSucℤ (posneg i) j = posneg (i ∧ j)
_+_ : ℤ → ℤ → ℤ
(signed _ zero) + n = n
(posneg _) + n = n
(pos (suc m)) + n = sucℤ (pos m + n)
(neg (suc m)) + n = predℤ (neg m + n)
sucPathℤ : ℤ ≡ ℤ
sucPathℤ = isoToPath (iso sucℤ predℤ sucPredℤ predSucℤ)
-- We do the same trick as in Cubical.Data.Int to prove that addition
-- is an equivalence
addEqℤ : ℕ → ℤ ≡ ℤ
addEqℤ zero = refl
addEqℤ (suc n) = addEqℤ n ∙ sucPathℤ
predPathℤ : ℤ ≡ ℤ
predPathℤ = isoToPath (iso predℤ sucℤ predSucℤ sucPredℤ)
subEqℤ : ℕ → ℤ ≡ ℤ
subEqℤ zero = refl
subEqℤ (suc n) = subEqℤ n ∙ predPathℤ
addℤ : ℤ → ℤ → ℤ
addℤ (pos m) n = transport (addEqℤ m) n
addℤ (neg m) n = transport (subEqℤ m) n
addℤ (posneg _) n = n
isEquivAddℤ : (m : ℤ) → isEquiv (addℤ m)
isEquivAddℤ (pos n) = isEquivTransport (addEqℤ n)
isEquivAddℤ (neg n) = isEquivTransport (subEqℤ n)
isEquivAddℤ (posneg _) = isEquivTransport refl
addℤ≡+ℤ : addℤ ≡ _+_
addℤ≡+ℤ i (pos (suc m)) n = sucℤ (addℤ≡+ℤ i (pos m) n)
addℤ≡+ℤ i (neg (suc m)) n = predℤ (addℤ≡+ℤ i (neg m) n)
addℤ≡+ℤ i (pos zero) n = n
addℤ≡+ℤ i (neg zero) n = n
addℤ≡+ℤ _ (posneg _) n = n
isEquiv+ℤ : (m : ℤ) → isEquiv (m +_)
isEquiv+ℤ = subst (λ _+_ → (m : ℤ) → isEquiv (m +_)) addℤ≡+ℤ isEquivAddℤ
_·_ : ℤ → ℤ → ℤ
m · n = signed (sign m ·S sign n) (abs m ℕ.· abs n)
private
·-abs : ∀ m n → abs (m · n) ≡ abs m ℕ.· abs n
·-abs m n = refl
-- Natural number and negative integer literals for ℤ
open import Cubical.Data.Nat.Literals public
instance
fromNatℤ : HasFromNat ℤ
fromNatℤ = record { Constraint = λ _ → Unit ; fromNat = λ n → pos n }
instance
fromNegℤ : HasFromNeg ℤ
fromNegℤ = record { Constraint = λ _ → Unit ; fromNeg = λ n → neg n }
-- ℤ is non-trivial
0≢1-ℤ : ¬ 0 ≡ 1
0≢1-ℤ p = 0≢1-Int (cong ℤ→Int p)-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Data.List.FinData.html`
module Cubical.Data.List.FinData where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Function
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Isomorphism
open import Cubical.Data.List
open import Cubical.Data.FinData
open import Cubical.Data.Empty as ⊥
open import Cubical.Data.Sigma.Properties
open import Cubical.Data.Nat
private
variable
ℓ : Level
A B : Type ℓ
-- copy-paste from agda-stdlib
lookup : ∀ (xs : List A) → Fin (length xs) → A
lookup (x ∷ xs) zero = x
lookup (x ∷ xs) (suc i) = lookup xs i
tabulate : ∀ n → (Fin n → A) → List A
tabulate zero ^a = []
tabulate (suc n) ^a = ^a zero ∷ tabulate n (^a ∘ suc)
length-tabulate : ∀ n → (^a : Fin n → A) → length (tabulate n ^a) ≡ n
length-tabulate zero ^a = refl
length-tabulate (suc n) ^a = cong suc (length-tabulate n (^a ∘ suc))
tabulate-lookup : ∀ (xs : List A) → tabulate (length xs) (lookup xs) ≡ xs
tabulate-lookup [] = refl
tabulate-lookup (x ∷ xs) = cong (x ∷_) (tabulate-lookup xs)
lookup-tabulate : ∀ n → (^a : Fin n → A)
→ PathP (λ i → (Fin (length-tabulate n ^a i) → A)) (lookup (tabulate n ^a)) ^a
lookup-tabulate (suc n) ^a i zero = ^a zero
lookup-tabulate (suc n) ^a i (suc p) = lookup-tabulate n (^a ∘ suc) i p
open Iso
lookup-tabulate-iso : (A : Type ℓ) → Iso (List A) (Σ[ n ∈ ℕ ] (Fin n → A))
fun (lookup-tabulate-iso A) xs = (length xs) , lookup xs
inv (lookup-tabulate-iso A) (n , f) = tabulate n f
ret (lookup-tabulate-iso A) = tabulate-lookup
sec (lookup-tabulate-iso A) (n , f) =
ΣPathP ((length-tabulate n f) , lookup-tabulate n f)
lookup-tabulate-equiv : (A : Type ℓ) → List A ≃ (Σ[ n ∈ ℕ ] (Fin n → A))
lookup-tabulate-equiv A = isoToEquiv (lookup-tabulate-iso A)
lookup-map : ∀ (f : A → B) (xs : List A)
→ (p0 : Fin (length (map f xs)))
→ (p1 : Fin (length xs))
→ (p : PathP (λ i → Fin (length-map f xs i)) p0 p1)
→ lookup (map f xs) p0 ≡ f (lookup xs p1)
lookup-map f (x ∷ xs) zero zero p = refl
lookup-map f (x ∷ xs) zero (suc p1) p = ⊥.rec (znotsP p)
lookup-map f (x ∷ xs) (suc p0) zero p = ⊥.rec (snotzP p)
lookup-map f (x ∷ xs) (suc p0) (suc p1) p = lookup-map f xs p0 p1 (injSucFinP p)-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Data.Maybe.Properties.html`
module Cubical.Data.Maybe.Properties where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.HLevels
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Function using (_∘_; idfun)
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Pointed.Base using (Pointed; _→∙_; pt)
open import Cubical.Foundations.Structure using (⟨_⟩)
open import Cubical.Functions.Embedding using (isEmbedding)
open import Cubical.Data.Empty as ⊥ using (⊥; isProp⊥)
open import Cubical.Data.Unit
open import Cubical.Data.Nat using (suc)
open import Cubical.Data.Sum using (_⊎_; inl; inr)
open import Cubical.Data.Sigma using (ΣPathP)
open import Cubical.Relation.Nullary using (¬_; Discrete; yes; no)
open import Cubical.Data.Maybe.Base as Maybe
Maybe∙ : ∀ {ℓ} (A : Type ℓ) → Pointed ℓ
Maybe∙ A .fst = Maybe A
Maybe∙ A .snd = nothing
-- Maybe∙ is the "free pointing" functor, that is, left adjoint to the
-- forgetful functor forgetting the base point.
module _ {ℓ} (A : Type ℓ) {ℓ'} (B : Pointed ℓ') where
freelyPointedIso : Iso (Maybe∙ A →∙ B) (A → ⟨ B ⟩)
Iso.fun freelyPointedIso f∙ = fst f∙ ∘ just
Iso.inv freelyPointedIso f = Maybe.rec (pt B) f , refl
Iso.sec freelyPointedIso f = refl
Iso.ret freelyPointedIso f∙ =
ΣPathP
( funExt (Maybe.elim _ (sym (snd f∙)) (λ a → refl))
, λ i j → snd f∙ (~ i ∨ j))
map-Maybe-id : ∀ {ℓ} {A : Type ℓ} → ∀ m → map-Maybe (idfun A) m ≡ m
map-Maybe-id nothing = refl
map-Maybe-id (just _) = refl
-- Path space of Maybe type
module MaybePath {ℓ} {A : Type ℓ} where
Cover : Maybe A → Maybe A → Type ℓ
Cover nothing nothing = Lift Unit
Cover nothing (just _) = Lift ⊥
Cover (just _) nothing = Lift ⊥
Cover (just a) (just a') = a ≡ a'
reflCode : (c : Maybe A) → Cover c c
reflCode nothing = lift tt
reflCode (just b) = refl
encode : ∀ c c' → c ≡ c' → Cover c c'
encode c _ = J (λ c' _ → Cover c c') (reflCode c)
encodeRefl : ∀ c → encode c c refl ≡ reflCode c
encodeRefl c = JRefl (λ c' _ → Cover c c') (reflCode c)
decode : ∀ c c' → Cover c c' → c ≡ c'
decode nothing nothing _ = refl
decode (just _) (just _) p = cong just p
decodeRefl : ∀ c → decode c c (reflCode c) ≡ refl
decodeRefl nothing = refl
decodeRefl (just _) = refl
decodeEncode : ∀ c c' → (p : c ≡ c') → decode c c' (encode c c' p) ≡ p
decodeEncode c _ =
J (λ c' p → decode c c' (encode c c' p) ≡ p)
(cong (decode c c) (encodeRefl c) ∙ decodeRefl c)
encodeDecode : ∀ c c' → (d : Cover c c') → encode c c' (decode c c' d) ≡ d
encodeDecode nothing nothing _ = refl
encodeDecode (just a) (just a') =
J (λ a' p → encode (just a) (just a') (cong just p) ≡ p) (encodeRefl (just a))
Cover≃Path : ∀ c c' → Cover c c' ≃ (c ≡ c')
Cover≃Path c c' = isoToEquiv
(iso (decode c c') (encode c c') (decodeEncode c c') (encodeDecode c c'))
Cover≡Path : ∀ c c' → Cover c c' ≡ (c ≡ c')
Cover≡Path c c' = isoToPath
(iso (decode c c') (encode c c') (decodeEncode c c') (encodeDecode c c'))
isOfHLevelCover : (n : HLevel)
→ isOfHLevel (suc (suc n)) A
→ ∀ c c' → isOfHLevel (suc n) (Cover c c')
isOfHLevelCover n p nothing nothing = isOfHLevelLift (suc n) (isOfHLevelUnit (suc n))
isOfHLevelCover n p nothing (just a') = isOfHLevelLift (suc n) (isProp→isOfHLevelSuc n isProp⊥)
isOfHLevelCover n p (just a) nothing = isOfHLevelLift (suc n) (isProp→isOfHLevelSuc n isProp⊥)
isOfHLevelCover n p (just a) (just a') = p a a'
isOfHLevelMaybe : ∀ {ℓ} (n : HLevel) {A : Type ℓ}
→ isOfHLevel (suc (suc n)) A
→ isOfHLevel (suc (suc n)) (Maybe A)
isOfHLevelMaybe n lA c c' =
isOfHLevelRetract (suc n)
(MaybePath.encode c c')
(MaybePath.decode c c')
(MaybePath.decodeEncode c c')
(MaybePath.isOfHLevelCover n lA c c')
private
variable
ℓ : Level
A : Type ℓ
fromJust-def : A → Maybe A → A
fromJust-def a nothing = a
fromJust-def _ (just a) = a
just-inj : (x y : A) → just x ≡ just y → x ≡ y
just-inj x _ eq = cong (fromJust-def x) eq
isEmbedding-just : isEmbedding (just {A = A})
isEmbedding-just w z = MaybePath.Cover≃Path (just w) (just z) .snd
¬nothing≡just : ∀ {x : A} → ¬ (nothing ≡ just x)
¬nothing≡just {A = A} {x = x} p = lower (subst (caseMaybe (Maybe A) (Lift ⊥)) p (just x))
¬just≡nothing : ∀ {x : A} → ¬ (just x ≡ nothing)
¬just≡nothing {A = A} {x = x} p = lower (subst (caseMaybe (Lift ⊥) (Maybe A)) p (just x))
isProp-x≡nothing : (x : Maybe A) → isProp (x ≡ nothing)
isProp-x≡nothing nothing x w =
subst isProp (MaybePath.Cover≡Path nothing nothing) (isOfHLevelLift 1 isPropUnit) x w
isProp-x≡nothing (just _) p _ = ⊥.rec (¬just≡nothing p)
isProp-nothing≡x : (x : Maybe A) → isProp (nothing ≡ x)
isProp-nothing≡x nothing x w =
subst isProp (MaybePath.Cover≡Path nothing nothing) (isOfHLevelLift 1 isPropUnit) x w
isProp-nothing≡x (just _) p _ = ⊥.rec (¬nothing≡just p)
isContr-nothing≡nothing : isContr (nothing {A = A} ≡ nothing)
isContr-nothing≡nothing = inhProp→isContr refl (isProp-x≡nothing _)
discreteMaybe : Discrete A → Discrete (Maybe A)
discreteMaybe eqA nothing nothing = yes refl
discreteMaybe eqA nothing (just a') = no ¬nothing≡just
discreteMaybe eqA (just a) nothing = no ¬just≡nothing
discreteMaybe eqA (just a) (just a') with eqA a a'
... | yes p = yes (cong just p)
... | no ¬p = no (λ p → ¬p (just-inj _ _ p))
module SumUnit where
Maybe→SumUnit : Maybe A → Unit ⊎ A
Maybe→SumUnit nothing = inl tt
Maybe→SumUnit (just a) = inr a
SumUnit→Maybe : Unit ⊎ A → Maybe A
SumUnit→Maybe (inl _) = nothing
SumUnit→Maybe (inr a) = just a
Maybe→SumUnit→Maybe : (x : Maybe A) → SumUnit→Maybe (Maybe→SumUnit x) ≡ x
Maybe→SumUnit→Maybe nothing = refl
Maybe→SumUnit→Maybe (just _) = refl
SumUnit→Maybe→SumUnit : (x : Unit ⊎ A) → Maybe→SumUnit (SumUnit→Maybe x) ≡ x
SumUnit→Maybe→SumUnit (inl _) = refl
SumUnit→Maybe→SumUnit (inr _) = refl
Maybe≡SumUnit : Maybe A ≡ Unit ⊎ A
Maybe≡SumUnit = isoToPath (iso Maybe→SumUnit SumUnit→Maybe SumUnit→Maybe→SumUnit Maybe→SumUnit→Maybe)
where open SumUnit
congMaybeEquiv : ∀ {ℓ ℓ'} {A : Type ℓ} {B : Type ℓ'}
→ A ≃ B → Maybe A ≃ Maybe B
congMaybeEquiv e = isoToEquiv isom
where
open Iso
isom : Iso _ _
isom .fun = map-Maybe (equivFun e)
isom .inv = map-Maybe (invEq e)
isom .sec nothing = refl
isom .sec (just b) = cong just (secEq e b)
isom .ret nothing = refl
isom .ret (just a) = cong just (retEq e a)-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Data.NatPlusOne.MoreNats.AssocNat.Properties.html`
module Cubical.Data.NatPlusOne.MoreNats.AssocNat.Properties where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Function
open import Cubical.Foundations.HLevels
open import Cubical.Foundations.Isomorphism
open import Cubical.Data.Nat
open import Cubical.Data.NatPlusOne.MoreNats.AssocNat.Base
open import Cubical.Data.NatPlusOne renaming (ℕ₊₁ to Nat; one to one'; _+₁_ to _+₁'_)
Nat→ℕ₊₁ : Nat → ℕ₊₁
Nat→ℕ₊₁ one' = 1
Nat→ℕ₊₁ (2+ n) = 1 +₁ Nat→ℕ₊₁ (1+ n)
ℕ₊₁→Nat : ℕ₊₁ → Nat
ℕ₊₁→Nat one = 1
ℕ₊₁→Nat (a +₁ b) = ℕ₊₁→Nat a +₁' ℕ₊₁→Nat b
ℕ₊₁→Nat (assoc a b c i) = +₁-assoc (ℕ₊₁→Nat a) (ℕ₊₁→Nat b) (ℕ₊₁→Nat c) i
ℕ₊₁→Nat (trunc m n p q i j) =
1+ (isSetℕ _ _ (λ k → -1+ (ℕ₊₁→Nat (p k))) (λ k → -1+ (ℕ₊₁→Nat (q k))) i j)
ℕ₊₁→Nat→ℕ₊₁ : ∀ n → ℕ₊₁→Nat (Nat→ℕ₊₁ n) ≡ n
ℕ₊₁→Nat→ℕ₊₁ one' = refl
ℕ₊₁→Nat→ℕ₊₁ (2+ n) = cong (1+_ ∘ suc ∘ -1+_) (ℕ₊₁→Nat→ℕ₊₁ (1+ n))
private
Nat→ℕ₊₁-+ : ∀ a b → Nat→ℕ₊₁ (a +₁' b) ≡ Nat→ℕ₊₁ a +₁ Nat→ℕ₊₁ b
Nat→ℕ₊₁-+ one' b = refl
Nat→ℕ₊₁-+ (2+ a) b = cong (one +₁_) (Nat→ℕ₊₁-+ (1+ a) b)
∙ assoc one (Nat→ℕ₊₁ (1+ a)) (Nat→ℕ₊₁ b)
Nat→ℕ₊₁→Nat : ∀ n → Nat→ℕ₊₁ (ℕ₊₁→Nat n) ≡ n
Nat→ℕ₊₁→Nat = ElimProp.f (trunc _ _) (λ i → one)
λ {a} {b} m n → Nat→ℕ₊₁-+ (ℕ₊₁→Nat a) (ℕ₊₁→Nat b) ∙ (λ i → m i +₁ n i)
ℕ₊₁≡Nat : ℕ₊₁ ≡ Nat
ℕ₊₁≡Nat = isoToPath (iso ℕ₊₁→Nat Nat→ℕ₊₁ ℕ₊₁→Nat→ℕ₊₁ Nat→ℕ₊₁→Nat)-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Data.Queue.Truncated2List.html`
{-# OPTIONS --no-exact-split #-}
module Cubical.Data.Queue.Truncated2List where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Function
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.HLevels
open import Cubical.Foundations.SIP
open import Cubical.Structures.Queue
open import Cubical.Data.Maybe
open import Cubical.Data.List
open import Cubical.Data.Sigma
open import Cubical.Data.Queue.1List
module Truncated2List {ℓ} (A : Type ℓ) (Aset : isSet A) where
open Queues-on A Aset
data Q : Type ℓ where
Q⟨_,_⟩ : (xs ys : List A) → Q
tilt : ∀ xs ys z → Q⟨ xs ++ [ z ] , ys ⟩ ≡ Q⟨ xs , ys ++ [ z ] ⟩
trunc : (q q' : Q) (α β : q ≡ q') → α ≡ β
multitilt : (xs ys zs : List A) → Q⟨ xs ++ rev zs , ys ⟩ ≡ Q⟨ xs , ys ++ zs ⟩
multitilt xs ys [] = cong₂ Q⟨_,_⟩ (++-unit-r xs) (sym (++-unit-r ys))
multitilt xs ys (z ∷ zs) =
cong (λ ws → Q⟨ ws , ys ⟩) (sym (++-assoc xs (rev zs) [ z ]))
∙ tilt (xs ++ rev zs) ys z
∙ multitilt xs (ys ++ [ z ]) zs
∙ cong (λ ws → Q⟨ xs , ws ⟩) (++-assoc ys [ z ] zs)
-- enq into the first list, deq from the second if possible
emp : Q
emp = Q⟨ [] , [] ⟩
enq : A → Q → Q
enq a Q⟨ xs , ys ⟩ = Q⟨ a ∷ xs , ys ⟩
enq a (tilt xs ys z i) = tilt (a ∷ xs) ys z i
enq a (trunc q q' α β i j) =
trunc _ _ (cong (enq a) α) (cong (enq a) β) i j
deqFlush : List A → Maybe (Q × A)
deqFlush [] = nothing
deqFlush (x ∷ xs) = just (Q⟨ [] , xs ⟩ , x)
deq : Q → Maybe (Q × A)
deq Q⟨ xs , [] ⟩ = deqFlush (rev xs)
deq Q⟨ xs , y ∷ ys ⟩ = just (Q⟨ xs , ys ⟩ , y)
deq (tilt xs [] z i) = path i
where
path : deqFlush (rev (xs ++ [ z ])) ≡ just (Q⟨ xs , [] ⟩ , z)
path =
cong deqFlush (rev-++ xs [ z ])
∙ cong (λ q → just (q , z)) (sym (multitilt [] [] (rev xs)))
∙ cong (λ ys → just (Q⟨ ys , [] ⟩ , z)) (rev-rev xs)
deq (tilt xs (y ∷ ys) z i) = just (tilt xs ys z i , y)
deq (trunc q q' α β i j) =
isOfHLevelMaybe 0
(isSetΣ trunc λ _ → Aset)
(deq q) (deq q') (cong deq α) (cong deq β)
i j
Raw : RawQueue
Raw = (Q , emp , enq , deq)
-- We construct an equivalence to 1Lists and prove this is an equivalence of queue structures
private
module One = 1List A Aset
open One renaming (Q to Q₁; emp to emp₁; enq to enq₁; deq to deq₁) using ()
quot : Q₁ → Q
quot xs = Q⟨ xs , [] ⟩
eval : Q → Q₁
eval Q⟨ xs , ys ⟩ = xs ++ rev ys
eval (tilt xs ys z i) = path i
where
path : (xs ++ [ z ]) ++ rev ys ≡ xs ++ rev (ys ++ [ z ])
path =
++-assoc xs [ z ] (rev ys)
∙ cong (_++_ xs) (sym (rev-++ ys [ z ]))
eval (trunc q q' α β i j) = -- truncated case
isOfHLevelList 0 Aset (eval q) (eval q') (cong eval α) (cong eval β) i j
quot∘eval : ∀ q → quot (eval q) ≡ q
quot∘eval Q⟨ xs , ys ⟩ = multitilt xs [] ys
quot∘eval (tilt xs ys z i) = -- truncated case
isOfHLevelPathP'
{A = λ i → quot (eval (tilt xs ys z i)) ≡ tilt xs ys z i}
0
(trunc _ _)
(multitilt (xs ++ [ z ]) [] ys) (multitilt xs [] (ys ++ [ z ]))
.fst i
quot∘eval (trunc q q' α β i j) = -- truncated case
isOfHLevelPathP'
{A = λ i →
PathP (λ j → quot (eval (trunc q q' α β i j)) ≡ trunc q q' α β i j)
(quot∘eval q) (quot∘eval q')}
0
(isOfHLevelPathP' 1 (isOfHLevelSuc 2 trunc _ _) _ _)
(cong quot∘eval α) (cong quot∘eval β)
.fst i j
eval∘quot : ∀ xs → eval (quot xs) ≡ xs
eval∘quot = ++-unit-r
-- We get our desired equivalence
quotEquiv : Q₁ ≃ Q
quotEquiv = isoToEquiv (iso quot eval quot∘eval eval∘quot)
-- Now it only remains to prove that this is an equivalence of queue structures
quot∘emp : quot emp₁ ≡ emp
quot∘emp = refl
quot∘enq : ∀ x xs → quot (enq₁ x xs) ≡ enq x (quot xs)
quot∘enq x xs = refl
quot∘deq : ∀ xs → deqMap quot (deq₁ xs) ≡ deq (quot xs)
quot∘deq [] = refl
quot∘deq (x ∷ []) = refl
quot∘deq (x ∷ x' ∷ xs) =
deqMap-∘ quot (enq₁ x) (deq₁ (x' ∷ xs))
∙ sym (deqMap-∘ (enq x) quot (deq₁ (x' ∷ xs)))
∙ cong (deqMap (enq x)) (quot∘deq (x' ∷ xs))
∙ lemma x x' (rev xs)
where
lemma : ∀ x x' ys
→ deqMap (enq x) (deqFlush (ys ++ [ x' ]))
≡ deqFlush ((ys ++ [ x' ]) ++ [ x ])
lemma x x' [] i = just (tilt [] [] x i , x')
lemma x x' (y ∷ ys) i = just (tilt [] (ys ++ [ x' ]) x i , y)
quotEquivHasQueueEquivStr : RawQueueEquivStr One.Raw Raw quotEquiv
quotEquivHasQueueEquivStr = quot∘emp , quot∘enq , quot∘deq
-- And we get a path between the raw 1Lists and 2Lists
Raw-1≡2 : One.Raw ≡ Raw
Raw-1≡2 = sip rawQueueUnivalentStr _ _ (quotEquiv , quotEquivHasQueueEquivStr)
-- We derive the axioms for 2List from those for 1List
WithLaws : Queue
WithLaws = Q , str Raw , subst (uncurry QueueAxioms) Raw-1≡2 (snd (str One.WithLaws))
WithLaws-1≡2 : One.WithLaws ≡ WithLaws
WithLaws-1≡2 = sip queueUnivalentStr _ _ (quotEquiv , quotEquivHasQueueEquivStr)
Finite : FiniteQueue
Finite = Q , str WithLaws , subst (uncurry FiniteQueueAxioms) WithLaws-1≡2 (snd (str One.Finite))-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Data.Sigma.Properties.html`
{-
Basic properties about Σ-types
- Action of Σ on functions ([map-fst], [map-snd])
- Characterization of equality in Σ-types using dependent paths ([ΣPath{Iso,≃,≡}PathΣ], [Σ≡Prop])
- Proof that discrete types are closed under Σ ([discreteΣ])
- Commutativity and associativity ([Σ-swap-*, Σ-assoc-*])
- Distributivity of Π over Σ ([Σ-Π-*])
- Action of Σ on isomorphisms, equivalences, and paths ([Σ-cong-fst], [Σ-cong-snd], ...)
- Characterization of equality in Σ-types using transport ([ΣPathTransport{≃,≡}PathΣ])
- Σ with a contractible base is its fiber ([Σ-contractFst, ΣUnit])
-}
module Cubical.Data.Sigma.Properties where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Function
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Equiv.HalfAdjoint
open import Cubical.Foundations.GroupoidLaws
open import Cubical.Foundations.Path
open import Cubical.Foundations.Transport
open import Cubical.Foundations.Univalence
open import Cubical.Data.Sigma.Base
open import Cubical.Data.Unit.Base
open import Cubical.Data.Empty.Base
open import Cubical.Relation.Nullary
open import Cubical.Reflection.StrictEquiv
open Iso
private
variable
ℓ ℓ' ℓ'' : Level
A A' : Type ℓ
B B' : (a : A) → Type ℓ
C : (a : A) (b : B a) → Type ℓ
map-fst : {B : Type ℓ} → (f : A → A') → A × B → A' × B
map-fst f (a , b) = (f a , b)
map-snd : (∀ {a} → B a → B' a) → Σ A B → Σ A B'
map-snd f (a , b) = (a , f b)
map-× : {B : Type ℓ} {B' : Type ℓ'} → (A → A') → (B → B') → A × B → A' × B'
map-× f g (a , b) = (f a , g b)
≡-× : {A : Type ℓ} {B : Type ℓ'} {x y : A × B} → fst x ≡ fst y → snd x ≡ snd y → x ≡ y
≡-× p q i = (p i) , (q i)
-- Characterization of paths in Σ using dependent paths
module _ {A : I → Type ℓ} {B : (i : I) → A i → Type ℓ'}
{x : Σ (A i0) (B i0)} {y : Σ (A i1) (B i1)}
where
ΣPathP : Σ[ p ∈ PathP A (fst x) (fst y) ] PathP (λ i → B i (p i)) (snd x) (snd y)
→ PathP (λ i → Σ (A i) (B i)) x y
ΣPathP eq i = fst eq i , snd eq i
PathPΣ : PathP (λ i → Σ (A i) (B i)) x y
→ Σ[ p ∈ PathP A (fst x) (fst y) ] PathP (λ i → B i (p i)) (snd x) (snd y)
PathPΣ eq = (λ i → fst (eq i)) , (λ i → snd (eq i))
-- allows one to write
-- open PathPΣ somePathInΣAB renaming (fst ... )
module PathPΣ (p : PathP (λ i → Σ (A i) (B i)) x y) where
open Σ (PathPΣ p) public
ΣPathIsoPathΣ : Iso (Σ[ p ∈ PathP A (fst x) (fst y) ] (PathP (λ i → B i (p i)) (snd x) (snd y)))
(PathP (λ i → Σ (A i) (B i)) x y)
fun ΣPathIsoPathΣ = ΣPathP
inv ΣPathIsoPathΣ = PathPΣ
sec ΣPathIsoPathΣ _ = refl
ret ΣPathIsoPathΣ _ = refl
unquoteDecl ΣPath≃PathΣ = declStrictIsoToEquiv ΣPath≃PathΣ ΣPathIsoPathΣ
ΣPath≡PathΣ : (Σ[ p ∈ PathP A (fst x) (fst y) ] (PathP (λ i → B i (p i)) (snd x) (snd y)))
≡ (PathP (λ i → Σ (A i) (B i)) x y)
ΣPath≡PathΣ = ua ΣPath≃PathΣ
×≡Prop : isProp A' → {u v : A × A'} → u .fst ≡ v .fst → u ≡ v
×≡Prop pB {u} {v} p i = (p i) , (pB (u .snd) (v .snd) i)
×≡Prop' : isProp A → {u v : A × A'} → u .snd ≡ v .snd → u ≡ v
×≡Prop' pA {u} {v} p i = (pA (u .fst) (v .fst) i) , p i
-- Useful lemma to prove unique existence
uniqueExists : (a : A) (b : B a) (h : (a' : A) → isProp (B a')) (H : (a' : A) → B a' → a ≡ a') → ∃![ a ∈ A ] B a
fst (uniqueExists a b h H) = (a , b)
snd (uniqueExists a b h H) (a' , b') = ΣPathP (H a' b' , isProp→PathP (λ i → h (H a' b' i)) b b')
-- Characterization of dependent paths in Σ
module _ {A : I → Type ℓ} {B : (i : I) → (a : A i) → Type ℓ'}
{x : Σ (A i0) (B i0)} {y : Σ (A i1) (B i1)}
where
ΣPathPIsoPathPΣ :
Iso (Σ[ p ∈ PathP A (x .fst) (y .fst) ] PathP (λ i → B i (p i)) (x .snd) (y .snd))
(PathP (λ i → Σ (A i) (B i)) x y)
ΣPathPIsoPathPΣ .fun (p , q) i = p i , q i
ΣPathPIsoPathPΣ .inv pq .fst i = pq i .fst
ΣPathPIsoPathPΣ .inv pq .snd i = pq i .snd
ΣPathPIsoPathPΣ .sec _ = refl
ΣPathPIsoPathPΣ .ret _ = refl
unquoteDecl ΣPathP≃PathPΣ = declStrictIsoToEquiv ΣPathP≃PathPΣ ΣPathPIsoPathPΣ
ΣPathP≡PathPΣ = ua ΣPathP≃PathPΣ
-- Σ of discrete types
discreteΣ : Discrete A → ((a : A) → Discrete (B a)) → Discrete (Σ A B)
discreteΣ {B = B} Adis Bdis (a0 , b0) (a1 , b1) = discreteΣ' (Adis a0 a1)
where
discreteΣ' : Dec (a0 ≡ a1) → Dec ((a0 , b0) ≡ (a1 , b1))
discreteΣ' (yes p) = J (λ a1 p → ∀ b1 → Dec ((a0 , b0) ≡ (a1 , b1))) (discreteΣ'') p b1
where
discreteΣ'' : (b1 : B a0) → Dec ((a0 , b0) ≡ (a0 , b1))
discreteΣ'' b1 with Bdis a0 b0 b1
... | (yes q) = yes (transport ΣPath≡PathΣ (refl , q))
... | (no ¬q) = no (λ r → ¬q (subst (λ X → PathP (λ i → B (X i)) b0 b1) (Discrete→isSet Adis a0 a0 (cong fst r) refl) (cong snd r)))
discreteΣ' (no ¬p) = no (λ r → ¬p (cong fst r))
lUnit×Iso : Iso (Unit × A) A
fun lUnit×Iso = snd
inv lUnit×Iso = tt ,_
sec lUnit×Iso _ = refl
ret lUnit×Iso _ = refl
lUnit*×Iso : ∀{ℓ} → Iso (Unit* {ℓ} × A) A
fun lUnit*×Iso = snd
inv lUnit*×Iso = tt* ,_
sec lUnit*×Iso _ = refl
ret lUnit*×Iso _ = refl
rUnit×Iso : Iso (A × Unit) A
fun rUnit×Iso = fst
inv rUnit×Iso = _, tt
sec rUnit×Iso _ = refl
ret rUnit×Iso _ = refl
rUnit*×Iso : ∀{ℓ} → Iso (A × Unit* {ℓ}) A
fun rUnit*×Iso = fst
inv rUnit*×Iso = _, tt*
sec rUnit*×Iso _ = refl
ret rUnit*×Iso _ = refl
module _ {A : Type ℓ} {A' : Type ℓ'} where
Σ-swap-Iso : Iso (A × A') (A' × A)
fun Σ-swap-Iso (x , y) = (y , x)
inv Σ-swap-Iso (x , y) = (y , x)
sec Σ-swap-Iso _ = refl
ret Σ-swap-Iso _ = refl
unquoteDecl Σ-swap-≃ = declStrictIsoToEquiv Σ-swap-≃ Σ-swap-Iso
module _ {A : Type ℓ} {B : A → Type ℓ'} {C : ∀ a → B a → Type ℓ''} where
Σ-assoc-Iso : Iso (Σ[ a ∈ Σ A B ] C (fst a) (snd a)) (Σ[ a ∈ A ] Σ[ b ∈ B a ] C a b)
fun Σ-assoc-Iso ((x , y) , z) = (x , (y , z))
inv Σ-assoc-Iso (x , (y , z)) = ((x , y) , z)
sec Σ-assoc-Iso _ = refl
ret Σ-assoc-Iso _ = refl
unquoteDecl Σ-assoc-≃ = declStrictIsoToEquiv Σ-assoc-≃ Σ-assoc-Iso
Σ-Π-Iso : Iso ((a : A) → Σ[ b ∈ B a ] C a b) (Σ[ f ∈ ((a : A) → B a) ] ∀ a → C a (f a))
fun Σ-Π-Iso f = (fst ∘ f , snd ∘ f)
inv Σ-Π-Iso (f , g) x = (f x , g x)
sec Σ-Π-Iso _ = refl
ret Σ-Π-Iso _ = refl
unquoteDecl Σ-Π-≃ = declStrictIsoToEquiv Σ-Π-≃ Σ-Π-Iso
module _ {A : Type ℓ} {B : A → Type ℓ'} {B' : ∀ a → Type ℓ''} where
Σ-assoc-swap-Iso : Iso (Σ[ a ∈ Σ A B ] B' (fst a)) (Σ[ a ∈ Σ A B' ] B (fst a))
fun Σ-assoc-swap-Iso ((x , y) , z) = ((x , z) , y)
inv Σ-assoc-swap-Iso ((x , z) , y) = ((x , y) , z)
sec Σ-assoc-swap-Iso _ = refl
ret Σ-assoc-swap-Iso _ = refl
unquoteDecl Σ-assoc-swap-≃ = declStrictIsoToEquiv Σ-assoc-swap-≃ Σ-assoc-swap-Iso
Σ-cong-iso-fst : (isom : Iso A A') → Iso (Σ A (B ∘ fun isom)) (Σ A' B)
fun (Σ-cong-iso-fst isom) x = fun isom (x .fst) , x .snd
inv (Σ-cong-iso-fst {B = B} isom) x = inv isom (x .fst) , subst B (sym (ε (x .fst))) (x .snd)
where
ε = isHAEquiv.rinv (snd (iso→HAEquiv isom))
sec (Σ-cong-iso-fst {B = B} isom) (x , y) = ΣPathP (ε x , toPathP goal)
where
ε = isHAEquiv.rinv (snd (iso→HAEquiv isom))
goal : subst B (ε x) (subst B (sym (ε x)) y) ≡ y
goal = sym (substComposite B (sym (ε x)) (ε x) y)
∙∙ cong (λ x → subst B x y) (lCancel (ε x))
∙∙ substRefl {B = B} y
ret (Σ-cong-iso-fst {A = A} {B = B} isom) (x , y) = ΣPathP (ret isom x , toPathP goal)
where
ε = isHAEquiv.rinv (snd (iso→HAEquiv isom))
γ = isHAEquiv.com (snd (iso→HAEquiv isom))
lem : (x : A) → sym (ε (fun isom x)) ∙ cong (fun isom) (ret isom x) ≡ refl
lem x = cong (λ a → sym (ε (fun isom x)) ∙ a) (γ x) ∙ lCancel (ε (fun isom x))
goal : subst B (cong (fun isom) (ret isom x)) (subst B (sym (ε (fun isom x))) y) ≡ y
goal = sym (substComposite B (sym (ε (fun isom x))) (cong (fun isom) (ret isom x)) y)
∙∙ cong (λ a → subst B a y) (lem x)
∙∙ substRefl {B = B} y
Σ-cong-equiv-fst : (e : A ≃ A') → Σ A (B ∘ equivFun e) ≃ Σ A' B
-- we could just do this:
-- Σ-cong-equiv-fst e = isoToEquiv (Σ-cong-iso-fst (equivToIso e))
-- but the following reduces slightly better
Σ-cong-equiv-fst {A = A} {A' = A'} {B = B} e = intro , isEqIntro
where
intro : Σ A (B ∘ equivFun e) → Σ A' B
intro (a , b) = equivFun e a , b
isEqIntro : isEquiv intro
isEqIntro .equiv-proof x = ctr , isCtr where
PB : ∀ {x y} → x ≡ y → B x → B y → Type _
PB p = PathP (λ i → B (p i))
open Σ x renaming (fst to a'; snd to b)
open Σ (equivCtr e a') renaming (fst to ctrA; snd to α)
ctrB : B (equivFun e ctrA)
ctrB = subst B (sym α) b
ctrP : PB α ctrB b
ctrP = symP (transport-filler (λ i → B (sym α i)) b)
ctr : fiber intro x
ctr = (ctrA , ctrB) , ΣPathP (α , ctrP)
isCtr : ∀ y → ctr ≡ y
isCtr ((r , s) , p) = λ i → (a≡r i , b!≡s i) , ΣPathP (α≡ρ i , coh i) where
open PathPΣ p renaming (fst to ρ; snd to σ)
open PathPΣ (equivCtrPath e a' (r , ρ)) renaming (fst to a≡r; snd to α≡ρ)
b!≡s : PB (cong (equivFun e) a≡r) ctrB s
b!≡s i = comp (λ k → B (α≡ρ i (~ k))) (λ k → (λ
{ (i = i0) → ctrP (~ k)
; (i = i1) → σ (~ k)
})) b
coh : PathP (λ i → PB (α≡ρ i) (b!≡s i) b) ctrP σ
coh i j = fill (λ k → B (α≡ρ i (~ k))) (λ k → (λ
{ (i = i0) → ctrP (~ k)
; (i = i1) → σ (~ k)
})) (inS b) (~ j)
Σ-cong-fst : (p : A ≡ A') → Σ A (B ∘ transport p) ≡ Σ A' B
Σ-cong-fst {B = B} p i = Σ (p i) (B ∘ transp (λ j → p (i ∨ j)) i)
Σ-cong-iso-snd : ((x : A) → Iso (B x) (B' x)) → Iso (Σ A B) (Σ A B')
fun (Σ-cong-iso-snd isom) (x , y) = x , fun (isom x) y
inv (Σ-cong-iso-snd isom) (x , y') = x , inv (isom x) y'
sec (Σ-cong-iso-snd isom) (x , y) = ΣPathP (refl , sec (isom x) y)
ret (Σ-cong-iso-snd isom) (x , y') = ΣPathP (refl , ret (isom x) y')
Σ-cong-equiv-snd : (∀ a → B a ≃ B' a) → Σ A B ≃ Σ A B'
Σ-cong-equiv-snd h = isoToEquiv (Σ-cong-iso-snd (equivToIso ∘ h))
Σ-cong-snd : ((x : A) → B x ≡ B' x) → Σ A B ≡ Σ A B'
Σ-cong-snd {A = A} p i = Σ[ x ∈ A ] (p x i)
Σ-cong-iso : (isom : Iso A A')
→ ((x : A) → Iso (B x) (B' (fun isom x)))
→ Iso (Σ A B) (Σ A' B')
Σ-cong-iso isom isom' = compIso (Σ-cong-iso-snd isom') (Σ-cong-iso-fst isom)
Σ-cong-equiv : (e : A ≃ A')
→ ((x : A) → B x ≃ B' (equivFun e x))
→ Σ A B ≃ Σ A' B'
Σ-cong-equiv e e' = isoToEquiv (Σ-cong-iso (equivToIso e) (equivToIso ∘ e'))
Σ-cong' : (p : A ≡ A') → PathP (λ i → p i → Type ℓ') B B' → Σ A B ≡ Σ A' B'
Σ-cong' p p' = cong₂ (λ (A : Type _) (B : A → Type _) → Σ A B) p p'
Σ-cong-equiv-prop :
(e : A ≃ A')
→ ((x : A ) → isProp (B x))
→ ((x : A') → isProp (B' x))
→ ((x : A) → B x → B' (equivFun e x))
→ ((x : A) → B' (equivFun e x) → B x)
→ Σ A B ≃ Σ A' B'
Σ-cong-equiv-prop e prop prop' prop→ prop← =
Σ-cong-equiv e (λ x → propBiimpl→Equiv (prop x) (prop' (equivFun e x)) (prop→ x) (prop← x))
-- Alternative version for path in Σ-types, as in the HoTT book
ΣPathTransport : (a b : Σ A B) → Type _
ΣPathTransport {B = B} a b = Σ[ p ∈ (fst a ≡ fst b) ] transport (λ i → B (p i)) (snd a) ≡ snd b
IsoΣPathTransportPathΣ : (a b : Σ A B) → Iso (ΣPathTransport a b) (a ≡ b)
IsoΣPathTransportPathΣ {B = B} a b =
compIso (Σ-cong-iso-snd (λ p → invIso (PathPIsoPath (λ i → B (p i)) _ _)))
ΣPathIsoPathΣ
ΣPathTransport≃PathΣ : (a b : Σ A B) → ΣPathTransport a b ≃ (a ≡ b)
ΣPathTransport≃PathΣ {B = B} a b = isoToEquiv (IsoΣPathTransportPathΣ a b)
ΣPathTransport→PathΣ : (a b : Σ A B) → ΣPathTransport a b → (a ≡ b)
ΣPathTransport→PathΣ a b = Iso.fun (IsoΣPathTransportPathΣ a b)
PathΣ→ΣPathTransport : (a b : Σ A B) → (a ≡ b) → ΣPathTransport a b
PathΣ→ΣPathTransport a b = Iso.inv (IsoΣPathTransportPathΣ a b)
ΣPathTransport≡PathΣ : (a b : Σ A B) → ΣPathTransport a b ≡ (a ≡ b)
ΣPathTransport≡PathΣ a b = ua (ΣPathTransport≃PathΣ a b)
Σ-contractFstIso : (c : isContr A) → Iso (Σ A B) (B (c .fst))
fun (Σ-contractFstIso {B = B} c) p = subst B (sym (c .snd (fst p))) (snd p)
inv (Σ-contractFstIso {B = B} c) b = _ , b
sec (Σ-contractFstIso {B = B} c) b =
cong (λ p → subst B p b) (isProp→isSet (isContr→isProp c) _ _ _ _) ∙ transportRefl _
fst (ret (Σ-contractFstIso {B = B} c) p j) = c .snd (fst p) j
snd (ret (Σ-contractFstIso {B = B} c) p j) =
transp (λ i → B (c .snd (fst p) (~ i ∨ j))) j (snd p)
Σ-contractFst : (c : isContr A) → Σ A B ≃ B (c .fst)
Σ-contractFst {B = B} c = isoToEquiv (Σ-contractFstIso c)
-- a special case of the above
module _ (A : Unit → Type ℓ) where
ΣUnit : Σ Unit A ≃ A tt
unquoteDef ΣUnit = defStrictEquiv {B = A tt} ΣUnit snd (tt ,_)
Σ-contractSnd : ((a : A) → isContr (B a)) → Σ A B ≃ A
Σ-contractSnd c = isoToEquiv isom
where
isom : Iso _ _
isom .fun = fst
isom .inv a = a , c a .fst
isom .sec _ = refl
isom .ret (a , b) = cong (a ,_) (c a .snd b)
isEmbeddingFstΣProp : ((x : A) → isProp (B x))
→ {u v : Σ A B}
→ isEquiv (λ (p : u ≡ v) → cong fst p)
isEmbeddingFstΣProp {B = B} pB {u = u} {v = v} .equiv-proof x = ctr , isCtr
where
ctrP : u ≡ v
ctrP = ΣPathP (x , isProp→PathP (λ _ → pB _) _ _)
ctr : fiber (λ (p : u ≡ v) → cong fst p) x
ctr = ctrP , refl
isCtr : ∀ z → ctr ≡ z
isCtr (z , p) = ΣPathP (ctrP≡ , cong (sym ∘ snd) fzsingl) where
fzsingl : Path (singl x) (x , refl) (cong fst z , sym p)
fzsingl = isContrSingl x .snd (cong fst z , sym p)
ctrSnd : SquareP (λ i j → B (fzsingl i .fst j)) (cong snd ctrP) (cong snd z) _ _
ctrSnd = isProp→SquareP (λ _ _ → pB _) _ _ _ _
ctrP≡ : ctrP ≡ z
ctrP≡ i = ΣPathP (fzsingl i .fst , ctrSnd i)
Σ≡PropEquiv : ((x : A) → isProp (B x)) → {u v : Σ A B}
→ (u .fst ≡ v .fst) ≃ (u ≡ v)
Σ≡PropEquiv pB = invEquiv (_ , isEmbeddingFstΣProp pB)
Σ≡Prop : ((x : A) → isProp (B x)) → {u v : Σ A B}
→ (p : u .fst ≡ v .fst) → u ≡ v
Σ≡Prop pB p = equivFun (Σ≡PropEquiv pB) p
-- dependent version
ΣPathPProp : ∀ {ℓ ℓ'} {A : I → Type ℓ} {B : (i : I) → A i → Type ℓ'}
→ {u : Σ (A i0) (B i0)} {v : Σ (A i1) (B i1)}
→ ((a : A (i1)) → isProp (B i1 a))
→ PathP (λ i → A i) (fst u) (fst v)
→ PathP (λ i → Σ (A i) (B i)) u v
fst (ΣPathPProp {u = u} {v = v} pB p i) = p i
snd (ΣPathPProp {B = B} {u = u} {v = v} pB p i) = lem i
where
lem : PathP (λ i → B i (p i)) (snd u) (snd v)
lem = toPathP (pB _ _ _)
discreteΣProp : Discrete A → ((x : A) → isProp (B x)) → Discrete (Σ A B)
discreteΣProp _≟_ isPropA _ _ =
EquivPresDec (Σ≡PropEquiv isPropA) (_ ≟ _)
≃-× : ∀ {ℓ'' ℓ'''} {A : Type ℓ} {B : Type ℓ'} {C : Type ℓ''} {D : Type ℓ'''} → A ≃ C → B ≃ D → A × B ≃ C × D
≃-× eq1 eq2 =
map-× (fst eq1) (fst eq2)
, record
{ equiv-proof
= λ {(c , d) → ((eq1⁻ c .fst .fst
, eq2⁻ d .fst .fst)
, ≡-× (eq1⁻ c .fst .snd)
(eq2⁻ d .fst .snd))
, λ {((a , b) , p) → ΣPathP (≡-× (cong fst (eq1⁻ c .snd (a , cong fst p)))
(cong fst (eq2⁻ d .snd (b , cong snd p)))
, λ i → ≡-× (snd ((eq1⁻ c .snd (a , cong fst p)) i))
(snd ((eq2⁻ d .snd (b , cong snd p)) i)))}}}
where
eq1⁻ = equiv-proof (eq1 .snd)
eq2⁻ = equiv-proof (eq2 .snd)
{- Some simple ismorphisms -}
prodIso : ∀ {ℓ ℓ' ℓ'' ℓ'''} {A : Type ℓ} {B : Type ℓ'} {C : Type ℓ''} {D : Type ℓ'''}
→ Iso A C
→ Iso B D
→ Iso (A × B) (C × D)
Iso.fun (prodIso iAC iBD) (a , b) = (Iso.fun iAC a) , Iso.fun iBD b
Iso.inv (prodIso iAC iBD) (c , d) = (Iso.inv iAC c) , Iso.inv iBD d
Iso.sec (prodIso iAC iBD) (c , d) = ΣPathP ((Iso.sec iAC c) , (Iso.sec iBD d))
Iso.ret (prodIso iAC iBD) (a , b) = ΣPathP ((Iso.ret iAC a) , (Iso.ret iBD b))
prodEquivToIso : ∀ {ℓ'' ℓ'''} {A : Type ℓ} {B : Type ℓ'} {C : Type ℓ''} {D : Type ℓ'''}
→ (e : A ≃ C)(e' : B ≃ D)
→ prodIso (equivToIso e) (equivToIso e') ≡ equivToIso (≃-× e e')
Iso.fun (prodEquivToIso e e' i) = Iso.fun (equivToIso (≃-× e e'))
Iso.inv (prodEquivToIso e e' i) = Iso.inv (equivToIso (≃-× e e'))
Iso.sec (prodEquivToIso e e' i) = Iso.sec (equivToIso (≃-× e e'))
Iso.ret (prodEquivToIso e e' i) = Iso.ret (equivToIso (≃-× e e'))
toProdIso : {B C : A → Type ℓ}
→ Iso ((a : A) → B a × C a) (((a : A) → B a) × ((a : A) → C a))
Iso.fun toProdIso = λ f → (λ a → fst (f a)) , (λ a → snd (f a))
Iso.inv toProdIso (f , g) = λ a → (f a) , (g a)
Iso.sec toProdIso (f , g) = refl
Iso.ret toProdIso b = refl
module _ {A : Type ℓ} {B : A → Type ℓ'} {C : ∀ a → B a → Type ℓ''} where
curryIso : Iso (((a , b) : Σ A B) → C a b) ((a : A) → (b : B a) → C a b)
Iso.fun curryIso f a b = f (a , b)
Iso.inv curryIso f a = f (fst a) (snd a)
Iso.sec curryIso a = refl
Iso.ret curryIso f = refl
unquoteDecl curryEquiv = declStrictIsoToEquiv curryEquiv curryIso
-- Sigma type with empty base
module _ (A : ⊥ → Type ℓ) where
open Iso
ΣEmptyIso : Iso (Σ ⊥ A) ⊥
fun ΣEmptyIso (* , _) = *
ΣEmpty : Σ ⊥ A ≃ ⊥
ΣEmpty = isoToEquiv ΣEmptyIso
module _ {ℓ : Level} (A : ⊥* {ℓ} → Type ℓ) where
open Iso
ΣEmpty*Iso : Iso (Σ ⊥* A) ⊥*
fun ΣEmpty*Iso (* , _) = *
-- fiber of projection map
module _
(A : Type ℓ)
(B : A → Type ℓ') where
private
proj : Σ A B → A
proj (a , b) = a
module _
(a : A) where
open Iso
fiberProjIso : Iso (B a) (fiber proj a)
fiberProjIso .fun b = (a , b) , refl
fiberProjIso .inv ((a' , b') , p) = subst B p b'
fiberProjIso .ret b i = substRefl {B = B} b i
fiberProjIso .sec (_ , p) i .fst .fst = p (~ i)
fiberProjIso .sec ((_ , b') , p) i .fst .snd = subst-filler B p b' (~ i)
fiberProjIso .sec (_ , p) i .snd j = p (~ i ∨ j)
fiberProjEquiv : B a ≃ fiber proj a
fiberProjEquiv = isoToEquiv fiberProjIso
separatedΣ : Separated A → ((a : A) → Separated (B a)) → Separated (Σ A B)
separatedΣ {B = B} sepA sepB (a , b) (a' , b') p = ΣPathTransport→PathΣ _ _ (pA , pB)
where
pA : a ≡ a'
pA = sepA a a' (λ q → p (λ r → q (cong fst r)))
pB : subst B pA b ≡ b'
pB = sepB _ _ _ (λ q → p (λ r → q (cong (λ r' → subst B r' b)
(Separated→isSet sepA _ _ pA (cong fst r)) ∙ snd (PathΣ→ΣPathTransport _ _ r))))-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Data.Unit.Properties.html`
module Cubical.Data.Unit.Properties where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Function
open import Cubical.Foundations.HLevels
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Univalence
open import Cubical.Data.Nat
open import Cubical.Data.Unit.Base
open import Cubical.Data.Prod.Base
open import Cubical.Data.Sigma hiding (_×_)
open import Cubical.Reflection.StrictEquiv
open Iso
private
variable
ℓ ℓ' : Level
terminal : (A : Type ℓ) → A → Unit
terminal A x = tt
isContrUnit : isContr Unit
isContrUnit = tt , λ {tt → refl}
isPropUnit : isProp Unit
isPropUnit _ _ i = tt -- definitionally equal to: isContr→isProp isContrUnit
isSetUnit : isSet Unit
isSetUnit = isProp→isSet isPropUnit
isOfHLevelUnit : (n : HLevel) → isOfHLevel n Unit
isOfHLevelUnit n = isContr→isOfHLevel n isContrUnit
module _ (A : Type ℓ) where
UnitToType≃ : (Unit → A) ≃ A
unquoteDef UnitToType≃ = defStrictEquiv UnitToType≃ (λ f → f _) const
UnitToTypePath : ∀ {ℓ} (A : Type ℓ) → (Unit → A) ≡ A
UnitToTypePath A = ua (UnitToType≃ A)
module _ (A : Unit → Type ℓ) where
open Iso
ΠUnitIso : Iso ((x : Unit) → A x) (A tt)
fun ΠUnitIso f = f tt
inv ΠUnitIso a tt = a
sec ΠUnitIso a = refl
ret ΠUnitIso f = refl
ΠUnit : ((x : Unit) → A x) ≃ A tt
ΠUnit = isoToEquiv ΠUnitIso
module _ (A : Unit* {ℓ} → Type ℓ') where
open Iso
ΠUnit*Iso : Iso ((x : Unit*) → A x) (A tt*)
fun ΠUnit*Iso f = f tt*
inv ΠUnit*Iso a tt* = a
sec ΠUnit*Iso a = refl
ret ΠUnit*Iso f = refl
ΠUnit* : ((x : Unit*) → A x) ≃ A tt*
ΠUnit* = isoToEquiv ΠUnit*Iso
fiberUnitIso : {A : Type ℓ} → Iso (fiber (λ (a : A) → tt) tt) A
fun fiberUnitIso = fst
inv fiberUnitIso a = a , refl
sec fiberUnitIso _ = refl
ret fiberUnitIso _ = refl
isContr→Iso2 : {A : Type ℓ} {B : Type ℓ'} → isContr A → Iso (A → B) B
fun (isContr→Iso2 iscontr) f = f (fst iscontr)
inv (isContr→Iso2 iscontr) b _ = b
sec (isContr→Iso2 iscontr) _ = refl
ret (isContr→Iso2 iscontr) f = funExt λ x → cong f (snd iscontr x)
diagonal-unit : Unit ≡ Unit × Unit
diagonal-unit = isoToPath (iso (λ x → tt , tt) (λ x → tt) (λ {(tt , tt) i → tt , tt}) λ {tt i → tt})
fibId : (A : Type ℓ) → (fiber (λ (x : A) → tt) tt) ≡ A
fibId A = ua e
where
unquoteDecl e = declStrictEquiv e fst (λ a → a , refl)
isContr→≃Unit : {A : Type ℓ} → isContr A → A ≃ Unit
isContr→≃Unit contr = isoToEquiv (iso (λ _ → tt) (λ _ → fst contr) (λ _ → refl) λ _ → snd contr _)
isContr→≡Unit : {A : Type₀} → isContr A → A ≡ Unit
isContr→≡Unit contr = ua (isContr→≃Unit contr)
isContrUnit* : ∀ {ℓ} → isContr (Unit* {ℓ})
isContrUnit* = tt* , λ _ → refl
isPropUnit* : ∀ {ℓ} → isProp (Unit* {ℓ})
isPropUnit* _ _ = refl
isSetUnit* : ∀ {ℓ} → isSet (Unit* {ℓ})
isSetUnit* _ _ _ _ = refl
isOfHLevelUnit* : ∀ {ℓ} (n : HLevel) → isOfHLevel n (Unit* {ℓ})
isOfHLevelUnit* zero = tt* , λ _ → refl
isOfHLevelUnit* (suc zero) _ _ = refl
isOfHLevelUnit* (suc (suc zero)) _ _ _ _ _ _ = tt*
isOfHLevelUnit* (suc (suc (suc n))) = isOfHLevelPlus 3 (isOfHLevelUnit* n)
Unit≃Unit* : ∀ {ℓ} → Unit ≃ Unit* {ℓ}
Unit≃Unit* = invEquiv (isContr→≃Unit isContrUnit*)
isContr→≃Unit* : {A : Type ℓ} → isContr A → A ≃ Unit* {ℓ'}
isContr→≃Unit* contr = compEquiv (isContr→≃Unit contr) Unit≃Unit*
isContr→≡Unit* : {A : Type ℓ} → isContr A → A ≡ Unit*
isContr→≡Unit* contr = ua (isContr→≃Unit* contr)
-- J for pointed propositions
JPointedProp : ∀ {ℓ ℓ'} {B : (A : Type ℓ') (a : A) (isPr : isProp A) → Type ℓ}
→ B Unit* tt* isPropUnit*
→ (A : Type ℓ') (a : A) (isPr : isProp A) → B A a isPr
JPointedProp {ℓ' = ℓ'} {B = B} ind A a isPr =
transport (λ i → B (P (~ i) .fst) (coh i) (P (~ i) .snd)) ind
where
A* : TypeOfHLevel ℓ' 1
A* = A , isPr
P : A* ≡ (Unit* , isPropUnit*)
P = Σ≡Prop (λ _ → isPropIsProp)
(ua (propBiimpl→Equiv isPr isPropUnit* (λ _ → tt*) λ _ → a))
coh : PathP (λ i → (P (~ i) .fst)) tt* a
coh = toPathP refl-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Data.Vec.Properties.html`
module Cubical.Data.Vec.Properties where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.HLevels
open import Cubical.Foundations.Univalence
import Cubical.Data.Empty as ⊥
open import Cubical.Data.Unit
open import Cubical.Data.Nat
open import Cubical.Data.Sigma
open import Cubical.Data.Sum
open import Cubical.Data.Vec.Base
open import Cubical.Data.FinData
open import Cubical.Relation.Nullary
open Iso
private
variable
ℓ : Level
A : Type ℓ
-- This is really cool!
-- Compare with: https://github.com/agda/agda-stdlib/blob/master/src/Data/Vec/Properties/WithK.agda#L32
++-assoc : ∀ {m n k} (xs : Vec A m) (ys : Vec A n) (zs : Vec A k) →
PathP (λ i → Vec A (+-assoc m n k (~ i))) ((xs ++ ys) ++ zs) (xs ++ ys ++ zs)
++-assoc {m = zero} [] ys zs = refl
++-assoc {m = suc m} (x ∷ xs) ys zs i = x ∷ ++-assoc xs ys zs i
-- Equivalence between Fin n → A and Vec A n
FinVec→Vec : {n : ℕ} → FinVec A n → Vec A n
FinVec→Vec {n = zero} xs = []
FinVec→Vec {n = suc _} xs = xs zero ∷ FinVec→Vec (λ x → xs (suc x))
Vec→FinVec : {n : ℕ} → Vec A n → FinVec A n
Vec→FinVec xs f = lookup f xs
FinVec→Vec→FinVec : {n : ℕ} (xs : FinVec A n) → Vec→FinVec (FinVec→Vec xs) ≡ xs
FinVec→Vec→FinVec {n = zero} xs = funExt λ f → ⊥.rec (¬Fin0 f)
FinVec→Vec→FinVec {n = suc n} xs = funExt goal
where
goal : (f : Fin (suc n))
→ Vec→FinVec (xs zero ∷ FinVec→Vec (λ x → xs (suc x))) f ≡ xs f
goal zero = refl
goal (suc f) i = FinVec→Vec→FinVec (λ x → xs (suc x)) i f
Vec→FinVec→Vec : {n : ℕ} (xs : Vec A n) → FinVec→Vec (Vec→FinVec xs) ≡ xs
Vec→FinVec→Vec {n = zero} [] = refl
Vec→FinVec→Vec {n = suc n} (x ∷ xs) i = x ∷ Vec→FinVec→Vec xs i
FinVecIsoVec : (n : ℕ) → Iso (FinVec A n) (Vec A n)
FinVecIsoVec n = iso FinVec→Vec Vec→FinVec Vec→FinVec→Vec FinVec→Vec→FinVec
FinVec≃Vec : (n : ℕ) → FinVec A n ≃ Vec A n
FinVec≃Vec n = isoToEquiv (FinVecIsoVec n)
FinVec≡Vec : (n : ℕ) → FinVec A n ≡ Vec A n
FinVec≡Vec n = ua (FinVec≃Vec n)
isContrVec0 : isContr (Vec A 0)
isContrVec0 = [] , λ { [] → refl }
-- encode - decode Vec
module VecPath {A : Type ℓ}
where
code : {n : ℕ} → (v v' : Vec A n) → Type ℓ
code [] [] = Unit*
code (a ∷ v) (a' ∷ v') = (a ≡ a') × (v ≡ v')
-- encode
reflEncode : {n : ℕ} → (v : Vec A n) → code v v
reflEncode [] = tt*
reflEncode (a ∷ v) = refl , refl
encode : {n : ℕ} → (v v' : Vec A n) → (v ≡ v') → code v v'
encode v v' p = J (λ v' _ → code v v') (reflEncode v) p
encodeRefl : {n : ℕ} → (v : Vec A n) → encode v v refl ≡ reflEncode v
encodeRefl v = JRefl (λ v' _ → code v v') (reflEncode v)
-- decode
decode : {n : ℕ} → (v v' : Vec A n) → (r : code v v') → (v ≡ v')
decode [] [] _ = refl
decode (a ∷ v) (a' ∷ v') (p , q) = cong₂ _∷_ p q
decodeRefl : {n : ℕ} → (v : Vec A n) → decode v v (reflEncode v) ≡ refl
decodeRefl [] = refl
decodeRefl (a ∷ v) = refl
-- equiv
≡Vec≃codeVec : {n : ℕ} → (v v' : Vec A n) → (v ≡ v') ≃ (code v v')
≡Vec≃codeVec v v' = isoToEquiv is
where
is : Iso (v ≡ v') (code v v')
fun is = encode v v'
inv is = decode v v'
sec is = sect v v'
where
sect : {n : ℕ} → (v v' : Vec A n) → (r : code v v')
→ encode v v' (decode v v' r) ≡ r
sect [] [] tt* = encodeRefl []
sect (a ∷ v) (a' ∷ v') (p , q) = J (λ a' p → encode (a ∷ v) (a' ∷ v') (decode (a ∷ v) (a' ∷ v') (p , q)) ≡ (p , q))
(J (λ v' q → encode (a ∷ v) (a ∷ v') (decode (a ∷ v) (a ∷ v') (refl , q)) ≡ (refl , q))
(encodeRefl (a ∷ v)) q) p
ret is = retr v v'
where
retr : {n : ℕ} → (v v' : Vec A n) → (p : v ≡ v')
→ decode v v' (encode v v' p) ≡ p
retr v v' p = J (λ v' p → decode v v' (encode v v' p) ≡ p)
(cong (decode v v) (encodeRefl v) ∙ decodeRefl v) p
isOfHLevelVec : (h : HLevel) (n : ℕ)
→ isOfHLevel (suc (suc h)) A → isOfHLevel (suc (suc h)) (Vec A n)
isOfHLevelVec h zero ofLevelA [] [] = isOfHLevelRespectEquiv (suc h) (invEquiv (≡Vec≃codeVec [] []))
(isOfHLevelUnit* (suc h))
isOfHLevelVec h (suc n) ofLevelA (x ∷ v) (x' ∷ v') = isOfHLevelRespectEquiv (suc h) (invEquiv (≡Vec≃codeVec _ _))
(isOfHLevelΣ (suc h) (ofLevelA x x') (λ _ → isOfHLevelVec h n ofLevelA v v'))
discreteA→discreteVecA : Discrete A → (n : ℕ) → Discrete (Vec A n)
discreteA→discreteVecA DA zero [] [] = yes refl
discreteA→discreteVecA DA (suc n) (a ∷ v) (a' ∷ v') with (DA a a') | (discreteA→discreteVecA DA n v v')
... | yes p | yes q = yes (invIsEq (snd (≡Vec≃codeVec (a ∷ v) (a' ∷ v'))) (p , q))
... | yes p | no ¬q = no (λ r → ¬q (snd (funIsEq (snd (≡Vec≃codeVec (a ∷ v) (a' ∷ v'))) r)))
... | no ¬p | yes q = no (λ r → ¬p (fst (funIsEq (snd (≡Vec≃codeVec (a ∷ v) (a' ∷ v'))) r)))
... | no ¬p | no ¬q = no (λ r → ¬q (snd (funIsEq (snd (≡Vec≃codeVec (a ∷ v) (a' ∷ v'))) r)))
≢-∷ : {m : ℕ} → (Discrete A) → (a : A) → (v : Vec A m) → (a' : A) → (v' : Vec A m) →
(a ∷ v ≡ a' ∷ v' → ⊥.⊥) → (a ≡ a' → ⊥.⊥) ⊎ (v ≡ v' → ⊥.⊥)
≢-∷ {m} discreteA a v a' v' ¬r with (discreteA a a')
| (discreteA→discreteVecA discreteA m v v')
... | yes p | yes q = ⊥.rec (¬r (cong₂ _∷_ p q))
... | yes p | no ¬q = inr ¬q
... | no ¬p | y = inl ¬p-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Displayed.Record.html`
{-
Generate univalent reflexive graph characterizations for record types from
characterizations of the field types using reflection.
See end of file for an example.
-}
{-# OPTIONS --no-exact-split #-}
module Cubical.Displayed.Record where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Function
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Path
open import Cubical.Data.Sigma
open import Cubical.Data.List as List
open import Cubical.Data.Unit
open import Cubical.Data.Bool
open import Cubical.Data.Maybe as Maybe
open import Cubical.Displayed.Base
open import Cubical.Displayed.Properties
open import Cubical.Displayed.Prop
open import Cubical.Displayed.Sigma
open import Cubical.Displayed.Unit
open import Cubical.Displayed.Universe
open import Cubical.Displayed.Auto
import Agda.Builtin.Reflection as R
open import Cubical.Reflection.Base
import Cubical.Reflection.RecordEquiv as RE
{-
`DUAFields`
A collection of DURG characterizations for fields of a record is described by an element of this inductive
family. If you just want to see how to use it, have a look at the end of the file first.
An element of `DUAFields 𝒮-A R _≅R⟨_⟩_ πS 𝒮ᴰ-S πS≅` describes a mapping
- from a structure `R : A → Type _` and notion of structured equivalence `_≅R⟨_⟩_`,
which are meant to be defined as parameterized record types,
- to a DURG `𝒮ᴰ-S`,
the underlying structure of which will be an iterated Σ-type,
- via projections `πS` and `πS≅`.
`𝒮-A`, `R`, and `_≅R⟨_⟩_` are parameters, while `πS`, `𝒮ᴰ-S`, and `πS≅` are indices;
the user builds up the Σ-type representation of the record using the DUAFields constructors.
A DUAFields representation is _total_ when the projections `πS` and `πS≅` are equivalences, in which case we
obtain a DURG on `R` with `_≅R⟨_⟩_` as the notion of structured equivalence---see `𝒮ᴰ-Fields` below.
When `R`, and `_≅R⟨_⟩_` are defined by record types, we can use reflection to automatically generate proofs
`πS` and `πS≅` are equivalences---see `𝒮ᴰ-Record` below.
-}
data DUAFields {ℓA ℓ≅A ℓR ℓ≅R} {A : Type ℓA} (𝒮-A : UARel A ℓ≅A)
(R : A → Type ℓR) (_≅R⟨_⟩_ : {a a' : A} → R a → UARel._≅_ 𝒮-A a a' → R a' → Type ℓ≅R)
: ∀ {ℓS ℓ≅S} {S : A → Type ℓS}
(πS : ∀ {a} → R a → S a) (𝒮ᴰ-S : DUARel 𝒮-A S ℓ≅S)
(πS≅ : ∀ {a} {r : R a} {e} {r' : R a} → r ≅R⟨ e ⟩ r' → DUARel._≅ᴰ⟨_⟩_ 𝒮ᴰ-S (πS r) e (πS r'))
→ Typeω
where
-- `fields:`
-- Base case, no fields yet recorded in `𝒮ᴰ-S`.
fields: : DUAFields 𝒮-A R _≅R⟨_⟩_ (λ _ → tt) (𝒮ᴰ-Unit 𝒮-A) (λ _ → tt)
-- `… data[ πF ∣ 𝒮ᴰ-F ∣ πF≅ ]`
-- Add a new field with a DURG. `πF` should be the name of the field in the structure record `R` and `πF≅`
-- the name of the corresponding field in the equivalence record `_≅R⟨_⟩_`, while `𝒮ᴰ-F` is a DURG for the
-- field's type over `𝒮-A`. Data fields that depend on previous fields of the record are not currently
-- supported.
_data[_∣_∣_] : ∀ {ℓS ℓ≅S} {S : A → Type ℓS}
{πS : ∀ {a} → R a → S a} {𝒮ᴰ-S : DUARel 𝒮-A S ℓ≅S}
{πS≅ : ∀ {a} {r : R a} {e} {r' : R a} → r ≅R⟨ e ⟩ r' → DUARel._≅ᴰ⟨_⟩_ 𝒮ᴰ-S (πS r) e (πS r')}
→ DUAFields 𝒮-A R _≅R⟨_⟩_ πS 𝒮ᴰ-S πS≅
→ ∀ {ℓF ℓ≅F} {F : A → Type ℓF}
(πF : ∀ {a} → (r : R a) → F a)
(𝒮ᴰ-F : DUARel 𝒮-A F ℓ≅F)
(πF≅ : ∀ {a} {r : R a} {e} {r' : R a} (p : r ≅R⟨ e ⟩ r') → DUARel._≅ᴰ⟨_⟩_ 𝒮ᴰ-F (πF r) e (πF r'))
→ DUAFields 𝒮-A R _≅R⟨_⟩_ (λ r → πS r , πF r) (𝒮ᴰ-S ×𝒮ᴰ 𝒮ᴰ-F) (λ p → πS≅ p , πF≅ p)
-- `… prop[ πF ∣ propF ]`
-- Add a new propositional field. `πF` should be the name of the field in the structure record `R`, while
-- propF is a proof that this field is a proposition.
_prop[_∣_] : ∀ {ℓS ℓ≅S} {S : A → Type ℓS}
{πS : ∀ {a} → R a → S a} {𝒮ᴰ-S : DUARel 𝒮-A S ℓ≅S}
{πS≅ : ∀ {a} {r : R a} {e} {r' : R a} → r ≅R⟨ e ⟩ r' → DUARel._≅ᴰ⟨_⟩_ 𝒮ᴰ-S (πS r) e (πS r')}
→ DUAFields 𝒮-A R _≅R⟨_⟩_ πS 𝒮ᴰ-S πS≅
→ ∀ {ℓF} {F : (a : A) → S a → Type ℓF}
(πF : ∀ {a} → (r : R a) → F a (πS r))
(propF : ∀ a s → isProp (F a s))
→ DUAFields 𝒮-A R _≅R⟨_⟩_ (λ r → πS r , πF r) (𝒮ᴰ-subtype 𝒮ᴰ-S propF) (λ p → πS≅ p)
module _ {ℓA ℓ≅A} {A : Type ℓA} {𝒮-A : UARel A ℓ≅A}
{ℓR ℓ≅R} {R : A → Type ℓR} (_≅R⟨_⟩_ : {a a' : A} → R a → UARel._≅_ 𝒮-A a a' → R a' → Type ℓ≅R)
{ℓS ℓ≅S} {S : A → Type ℓS}
{πS : ∀ {a} → R a → S a} {𝒮ᴰ-S : DUARel 𝒮-A S ℓ≅S}
{πS≅ : ∀ {a} {r : R a} {e} {r' : R a} → r ≅R⟨ e ⟩ r' → DUARel._≅ᴰ⟨_⟩_ 𝒮ᴰ-S (πS r) e (πS r')}
(fs : DUAFields 𝒮-A R _≅R⟨_⟩_ πS 𝒮ᴰ-S πS≅)
where
open UARel 𝒮-A
open DUARel 𝒮ᴰ-S
𝒮ᴰ-Fields :
(e : ∀ a → Iso (R a) (S a))
(e≅ : ∀ a a' (r : R a) p (r' : R a') → Iso (r ≅R⟨ p ⟩ r') ((e a .Iso.fun r ≅ᴰ⟨ p ⟩ e a' .Iso.fun r')))
→ DUARel 𝒮-A R ℓ≅R
DUARel._≅ᴰ⟨_⟩_ (𝒮ᴰ-Fields e e≅) r p r' = r ≅R⟨ p ⟩ r'
DUARel.uaᴰ (𝒮ᴰ-Fields e e≅) r p r' =
isoToEquiv
(compIso
(e≅ _ _ r p r')
(compIso
(equivToIso (uaᴰ (e _ .Iso.fun r) p (e _ .Iso.fun r')))
(invIso (congPathIso λ i → isoToEquiv (e _)))))
module DisplayedRecordMacro where
-- Extract a name from a term
findName : R.Term → R.TC R.Name
findName t =
Maybe.rec
(R.typeError (R.strErr "Not a name: " ∷ R.termErr t ∷ []))
(λ s → s)
(go t)
where
go : R.Term → Maybe (R.TC R.Name)
go (R.meta x _) = just (R.blockOnMeta x)
go (R.def name _) = just (R.returnTC name)
go (R.lam _ (R.abs _ t)) = go t
go t = nothing
-- ℓA ℓ≅A ℓR ℓ≅R A 𝒮-A R _≅R⟨_⟩_
pattern family∷ hole = _ h∷ _ h∷ _ h∷ _ h∷ _ h∷ _ h∷ _ h∷ _ h∷ hole
-- ℓS ℓ≅S S πS 𝒮ᴰ-S πS≅
pattern indices∷ hole = _ h∷ _ h∷ _ h∷ _ h∷ _ h∷ _ h∷ hole
{-
Takes a reflected DUAFields term as input and collects lists of structure field names and equivalence
field names. (These are returned in reverse order.
-}
parseFields : R.Term → R.TC (List R.Name × List R.Name)
parseFields (R.con (quote fields:) _) = R.returnTC ([] , [])
parseFields (R.con (quote _data[_∣_∣_]) (family∷ (indices∷ (fs v∷ ℓF h∷ ℓ≅F h∷ F h∷ πF v∷ 𝒮ᴰ-F v∷ πF≅ v∷ _)))) =
parseFields fs >>= λ (fs , f≅s) →
findName πF >>= λ f →
findName πF≅ >>= λ f≅ →
R.returnTC (f ∷ fs , f≅ ∷ f≅s)
parseFields (R.con (quote _prop[_∣_]) (family∷ (indices∷ (fs v∷ ℓF h∷ F h∷ πF v∷ _)))) =
parseFields fs >>= λ (fs , f≅s) →
findName πF >>= λ f →
R.returnTC (f ∷ fs , f≅s)
parseFields (R.meta x _) = R.blockOnMeta x
parseFields t = R.typeError (R.strErr "Malformed specification: " ∷ R.termErr t ∷ [])
{-
Given a list of record field names (in reverse order), generates a ΣFormat (in the sense of
Cubical.Reflection.RecordEquiv) associating the record fields with the fields of a left-associated
iterated Σ-type
-}
List→LeftAssoc : List R.Name → RE.ΣFormat
List→LeftAssoc [] = RE.unit
List→LeftAssoc (x ∷ xs) = List→LeftAssoc xs RE., RE.leaf x
module _ {ℓA ℓ≅A} {A : Type ℓA} (𝒮-A : UARel A ℓ≅A)
{ℓR ℓ≅R} {R : A → Type ℓR} (≅R : {a a' : A} → R a → UARel._≅_ 𝒮-A a a' → R a' → Type ℓ≅R)
{ℓS ℓ≅S} {S : A → Type ℓS}
{πS : ∀ {a} → R a → S a} {𝒮ᴰ-S : DUARel 𝒮-A S ℓ≅S}
{πS≅ : ∀ {a} {r : R a} {e} {r' : R a} → ≅R r e r' → DUARel._≅ᴰ⟨_⟩_ 𝒮ᴰ-S (πS r) e (πS r')}
where
{-
"𝒮ᴰ-Record ... : DUARel 𝒮-A R ℓ≅R"
Requires that `R` and `_≅R⟨_⟩_` are defined by records and `πS` and `πS≅` are equivalences.
The proofs of equivalence are generated using Cubical.Reflection.RecordEquiv and then
`𝒮ᴰ-Fields` is applied.
-}
𝒮ᴰ-Record : DUAFields 𝒮-A R ≅R πS 𝒮ᴰ-S πS≅ → R.Term → R.TC Unit
𝒮ᴰ-Record fs hole =
R.quoteTC (DUARel 𝒮-A R ℓ≅R) >>= R.checkType hole >>= λ hole →
R.quoteωTC fs >>= λ `fs` →
parseFields `fs` >>= λ (fields , ≅fields) →
R.freshName "fieldsIso" >>= λ fieldsIso →
R.freshName "≅fieldsIso" >>= λ ≅fieldsIso →
R.quoteTC R >>= R.normalise >>= λ `R` →
R.quoteTC {A = {a a' : A} → R a → UARel._≅_ 𝒮-A a a' → R a' → Type ℓ≅R} ≅R >>= R.normalise >>= λ `≅R` →
findName `R` >>= RE.declareRecordIsoΣ' fieldsIso (List→LeftAssoc fields) >>
findName `≅R` >>= RE.declareRecordIsoΣ' ≅fieldsIso (List→LeftAssoc ≅fields) >>
R.unify hole
(R.def (quote 𝒮ᴰ-Fields)
(`≅R` v∷ `fs` v∷
vlam "_" (R.def fieldsIso []) v∷
vlam "a" (vlam "a'" (vlam "r" (vlam "p" (vlam "r'" (R.def ≅fieldsIso []))))) v∷
[]))
macro
𝒮ᴰ-Record = DisplayedRecordMacro.𝒮ᴰ-Record
-- Example
private
module Example where
record Example (A : Type) : Type where
no-eta-equality -- works with or without eta equality
field
dog : A → A → A
cat : A → A → A
mouse : Unit
open Example
record ExampleEquiv {A B : Type} (x : Example A) (e : A ≃ B) (y : Example B) : Type where
no-eta-equality -- works with or without eta equality
field
dogEq : ∀ a a' → e .fst (x .dog a a') ≡ y .dog (e .fst a) (e .fst a')
catEq : ∀ a a' → e .fst (x .cat a a') ≡ y .cat (e .fst a) (e .fst a')
open ExampleEquiv
example : DUARel (𝒮-Univ ℓ-zero) Example ℓ-zero
example =
𝒮ᴰ-Record (𝒮-Univ ℓ-zero) ExampleEquiv
(fields:
data[ dog ∣ autoDUARel _ _ ∣ dogEq ]
data[ cat ∣ autoDUARel _ _ ∣ catEq ]
prop[ mouse ∣ (λ _ _ → isPropUnit) ])-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Displayed.Subst`
{-
Given a type A with a UARel and a family B over A,
a SubstRel on B is a family of functions a ≅ a' → B a ≃ B a' path-equal to transport in that family.
Any SubstRel gives rise to a DUARel in which b and b' are related over p when the transport of b along p is
equial to b'.
-}
module Cubical.Displayed.Subst where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Path
open import Cubical.Foundations.Transport
open import Cubical.Foundations.Univalence
open import Cubical.Displayed.Base
private
variable
ℓA ℓ≅A ℓB : Level
record SubstRel {A : Type ℓA} {ℓ≅A : Level} (𝒮-A : UARel A ℓ≅A) (B : A → Type ℓB)
: Type (ℓ-max (ℓ-max ℓA ℓB) ℓ≅A)
where
no-eta-equality
constructor substrel
open UARel 𝒮-A
field
act : {a a' : A} → a ≅ a' → B a ≃ B a'
uaˢ : {a a' : A} (p : a ≅ a') (b : B a) → subst B (≅→≡ p) b ≡ equivFun (act p) b
uaˢ⁻ : {a a' : A} (p : a ≅ a') (b : B a') → subst B (sym (≅→≡ p)) b ≡ invEq (act p) b
uaˢ⁻ p b =
subst B (sym (≅→≡ p)) b
≡⟨ cong (subst B (sym (≅→≡ p))) (sym (secEq (act p) b)) ⟩
subst B (sym (≅→≡ p)) (equivFun (act p) (invEq (act p) b))
≡⟨ cong (subst B (sym (≅→≡ p))) (sym (uaˢ p (invEq (act p) b))) ⟩
subst B (sym (≅→≡ p)) (subst B (≅→≡ p) (invEq (act p) b))
≡⟨ pathToIso (cong B (≅→≡ p)) .Iso.ret (invEq (act p) b) ⟩
invEq (act p) b
∎
Subst→DUA : {A : Type ℓA} {ℓ≅A : Level} {𝒮-A : UARel A ℓ≅A} {B : A → Type ℓB}
→ SubstRel 𝒮-A B → DUARel 𝒮-A B ℓB
DUARel._≅ᴰ⟨_⟩_ (Subst→DUA 𝒮ˢ-B) b p b' =
equivFun (SubstRel.act 𝒮ˢ-B p) b ≡ b'
DUARel.uaᴰ (Subst→DUA {𝒮-A = 𝒮-A} {B = B} 𝒮ˢ-B) b p b' =
equivFun (SubstRel.act 𝒮ˢ-B p) b ≡ b'
≃⟨ invEquiv (compPathlEquiv (sym (SubstRel.uaˢ 𝒮ˢ-B p b))) ⟩
subst B (≅→≡ p) b ≡ b'
≃⟨ invEquiv (PathP≃Path (λ i → B (≅→≡ p i)) b b') ⟩
PathP (λ i → B (≅→≡ p i)) b b'
■
where
open UARel 𝒮-A-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Foundations.Cubes.Base.html`
{-
This file contains:
- The definition of the type of n-cubes;
- Some basic operations.
-}
module Cubical.Foundations.Cubes.Base where
open import Cubical.Foundations.Prelude hiding (Cube)
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Isomorphism
open import Cubical.Data.Nat.Base
open import Cubical.Data.Sigma.Base
private
variable
ℓ ℓ' : Level
A : Type ℓ
-- The Type of n-Cubes
-- P.S.
-- Only the definitions of `∂Cube` and `CubeRel` essentially use mutual recursion.
-- The case of `Cube` is designed to gain more definitional equality.
interleaved mutual
Cube : (n : ℕ) (A : Type ℓ) → Type ℓ
∂Cube₀₁ : (n : ℕ) (A : Type ℓ) (a₀ a₁ : Cube n A) → Type ℓ
∂Cube : (n : ℕ) (A : Type ℓ) → Type ℓ
CubeRel : (n : ℕ) (A : Type ℓ) → ∂Cube n A → Type ℓ
Cube 0 A = A
Cube (suc n) A = Σ[ ∂ ∈ ∂Cube (suc n) A ] CubeRel (suc n) A ∂
∂Cube₀₁ 0 A _ _ = Unit*
∂Cube₀₁ (suc n) A a₀ a₁ = a₀ .fst ≡ a₁ .fst
∂Cube 0 A = Unit*
∂Cube 1 A = A × A
∂Cube (suc (suc n)) A = Σ[ a₀ ∈ Cube (suc n) A ] Σ[ a₁ ∈ Cube (suc n) A ] ∂Cube₀₁ (suc n) A a₀ a₁
CubeRel 0 A _ = A
CubeRel 1 A ∂ = ∂ .fst ≡ ∂ .snd
CubeRel (suc (suc n)) A (a₀ , a₁ , ∂₋) = PathP (λ i → CubeRel (suc n) A (∂₋ i)) (a₀ .snd) (a₁ .snd)
-- Some basic operations
∂_ : {n : ℕ}{A : Type ℓ} → Cube n A → ∂Cube n A
∂_ {n = 0} _ = tt*
∂_ {n = suc n} = fst
∂₀ : {n : ℕ}{A : Type ℓ} → Cube (suc n) A → Cube n A
∂₀ {n = 0} (_ , p) = p i0
∂₀ {n = suc n} (_ , p) = _ , p i0
∂₁ : {n : ℕ}{A : Type ℓ} → Cube (suc n) A → Cube n A
∂₁ {n = 0} (_ , p) = p i1
∂₁ {n = suc n} (_ , p) = _ , p i1
∂ᵇ₀ : {n : ℕ}{A : Type ℓ} → ∂Cube (suc n) A → Cube n A
∂ᵇ₀ {n = 0} (a₀ , a₁) = a₀
∂ᵇ₀ {n = suc n} (a₀ , a₁ , ∂₋) = a₀
∂ᵇ₁ : {n : ℕ}{A : Type ℓ} → ∂Cube (suc n) A → Cube n A
∂ᵇ₁ {n = 0} (a₀ , a₁) = a₁
∂ᵇ₁ {n = suc n} (a₀ , a₁ , ∂₋) = a₁
make∂ : {n : ℕ}{A : Type ℓ}{∂₀ ∂₁ : ∂Cube n A} → ∂₀ ≡ ∂₁ → CubeRel n A ∂₀ → CubeRel n A ∂₁ → ∂Cube (suc n) A
make∂ {n = 0} _ a b = a , b
make∂ {n = suc n} ∂₋ a₀ a₁ = (_ , a₀) , (_ , a₁) , ∂₋
makeCube : {n : ℕ}{A : Type ℓ}{a₀ a₁ : Cube n A} → a₀ ≡ a₁ → Cube (suc n) A
makeCube {n = 0} a₋ = _ , a₋
makeCube {n = suc n} a₋ = _ , λ i → a₋ i .snd
-- A cube is just a path of cubes of one-lower-dimension.
-- Unfortunately the following function cannot begin at 0,
-- because Agda doesn't support pattern matching on ℕ towards pre-types.
-- P.S. It will be fixed in Agda 2.6.3 when I → A becomes fibrant.
pathCube : (n : ℕ) → (I → Cube (suc n) A) → Cube (suc (suc n)) A
pathCube n p = _ , λ i → p i .snd
∂Cube₀₁→∂Cube : {n : ℕ}{A : Type ℓ}{a₀ a₁ : Cube n A} → ∂Cube₀₁ n A a₀ a₁ → ∂Cube (suc n) A
∂Cube₀₁→∂Cube {n = 0} {a₀ = a₀} {a₁} _ = a₀ , a₁
∂Cube₀₁→∂Cube {n = suc n} {a₀ = a₀} {a₁} ∂ = a₀ , a₁ , ∂
CubeRel→Cube : {n : ℕ}{A : Type ℓ}{∂ : ∂Cube n A} → CubeRel n A ∂ → Cube n A
CubeRel→Cube {n = 0} a = a
CubeRel→Cube {n = suc n} cube = _ , cube
-- Composition of internal cubes, with specified boundary
hcomp∂ :
{n : ℕ} {A : Type ℓ}
{∂₀ ∂₁ : ∂Cube n A} (∂₋ : ∂₀ ≡ ∂₁)
(a₀ : CubeRel n A ∂₀)
→ CubeRel n A ∂₁
hcomp∂ ∂₋ = transport (λ i → CubeRel _ _ (∂₋ i))
hfill∂ :
{n : ℕ} {A : Type ℓ}
{∂₀ ∂₁ : ∂Cube n A} (∂₋ : ∂₀ ≡ ∂₁)
(a₀ : CubeRel n A ∂₀)
→ CubeRel (suc n) A (make∂ ∂₋ a₀ (hcomp∂ ∂₋ a₀))
hfill∂ {n = 0} ∂₋ a₀ i = transportRefl a₀ (~ i)
hfill∂ {n = suc n} ∂₋ = transport-filler (λ i → CubeRel _ _ (∂₋ i))
-- Constant path of n-cube as (n+1)-cube
constCube : {n : ℕ}{A : Type ℓ} → Cube n A → Cube (suc n) A
constCube {n = 0} a = _ , λ i → a
constCube {n = suc n} (∂ , cube) = _ , λ i → cube
retConst : {n : ℕ}{A : Type ℓ} → (cube : Cube n A) → ∂₀ (constCube {n = n} cube) ≡ cube
retConst {n = 0} _ = refl
retConst {n = suc n} _ = refl
secConst : {n : ℕ}{A : Type ℓ} → (cube : Cube (suc n) A) → constCube (∂₀ cube) ≡ cube
secConst {n = 0} (_ , p) i = _ , λ j → p (i ∧ j)
secConst {n = suc n} (_ , p) i = _ , λ j → p (i ∧ j)
isEquivConstCube : {n : ℕ}{A : Type ℓ} → isEquiv (constCube {n = n} {A = A})
isEquivConstCube {n = n} = isoToEquiv (iso constCube ∂₀ secConst (retConst {n = n})) .snd
-- Constant cubes
const : (n : ℕ){A : Type ℓ} → A → Cube n A
const 0 a = a
const (suc n) a = constCube (const n a)
isEquivConst : {n : ℕ}{A : Type ℓ} → isEquiv (const n {A = A})
isEquivConst {n = 0} = idIsEquiv _
isEquivConst {n = suc n} = compEquiv (_ , isEquivConst) (_ , isEquivConstCube) .snd
cubeEquiv : {n : ℕ}{A : Type ℓ} → A ≃ Cube n A
cubeEquiv = _ , isEquivConst
makeConst : {n : ℕ}{A : Type ℓ} → (cube : Cube n A) → Σ[ a ∈ A ] cube ≡ const n a
makeConst {n = n} cube = invEq cubeEquiv cube , sym (secEq (cubeEquiv {n = n}) cube)
makeConstUniq : {n : ℕ}{A : Type ℓ} → (a : A) → makeConst (const n a) ≡ (a , refl)
makeConstUniq {n = n} a i .fst = isEquivConst .equiv-proof (const n a) .snd (a , refl) i .fst
makeConstUniq {n = n} a i .snd j = isEquivConst .equiv-proof (const n a) .snd (a , refl) i .snd (~ j)
-- Cube with constant boundary
const∂ : (n : ℕ){A : Type ℓ} → A → ∂Cube n A
const∂ n a = ∂ (const n a)
-- J-rule for n-cubes,
-- in some sense a generalization of the usual (symmetric form of) J-rule,
-- which is equivalent to the case n=1.
module _ {n : ℕ} {A : Type ℓ}
(P : Cube n A → Type ℓ') (d : (a : A) → P (const _ a)) where
JCube : (a₋ : Cube n A) → P a₋
JCube a₋ =
let c-path = makeConst {n = n} a₋ in
transport (λ i → P (c-path .snd (~ i))) (d (c-path .fst))
JCubeβ : (a : A) → JCube (const _ a) ≡ d a
JCubeβ a i =
let c-square = makeConstUniq {n = n} a in
let c-path = transport-filler (λ i → P (c-square i0 .snd (~ i))) (d (c-square i0 .fst)) in
comp (λ j → P (c-square j .snd i))
(λ j → λ
{ (i = i0) → c-path i1
; (i = i1) → d _ })
(c-path (~ i))-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Foundations.Equiv.html`
{-
Theory about equivalences
Definitions are in Core/Glue.agda but re-exported by this module
- isEquiv is a proposition ([isPropIsEquiv])
- Any isomorphism is an equivalence ([isoToEquiv])
There are more statements about equivalences in Equiv/Properties.agda:
- if f is an equivalence then (cong f) is an equivalence
- if f is an equivalence then precomposition with f is an equivalence
- if f is an equivalence then postcomposition with f is an equivalence
-}
module Cubical.Foundations.Equiv where
open import Cubical.Foundations.Function
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Equiv.Base public
open import Cubical.Data.Sigma.Base
private
variable
ℓ ℓ' ℓ'' : Level
A B C D : Type ℓ
infixr 30 _∙ₑ_
equivIsEquiv : (e : A ≃ B) → isEquiv (equivFun e)
equivIsEquiv e = snd e
equivCtr : (e : A ≃ B) (y : B) → fiber (equivFun e) y
equivCtr e y = e .snd .equiv-proof y .fst
equivCtrPath : (e : A ≃ B) (y : B) →
(v : fiber (equivFun e) y) → Path _ (equivCtr e y) v
equivCtrPath e y = e .snd .equiv-proof y .snd
-- Proof using isPropIsContr. This is slow and the direct proof below is better
isPropIsEquiv' : (f : A → B) → isProp (isEquiv f)
equiv-proof (isPropIsEquiv' f u0 u1 i) y =
isPropIsContr (u0 .equiv-proof y) (u1 .equiv-proof y) i
-- Direct proof that computes quite ok (can be optimized further if
-- necessary, see:
-- https://github.com/mortberg/cubicaltt/blob/pi4s3_dimclosures/examples/brunerie2.ctt#L562
isPropIsEquiv : (f : A → B) → isProp (isEquiv f)
equiv-proof (isPropIsEquiv f p q i) y =
let p2 = p .equiv-proof y .snd
q2 = q .equiv-proof y .snd
in p2 (q .equiv-proof y .fst) i
, λ w j → hcomp (λ k → λ { (i = i0) → p2 w j
; (i = i1) → q2 w (j ∨ ~ k)
; (j = i0) → p2 (q2 w (~ k)) i
; (j = i1) → w })
(p2 w (i ∨ j))
equivPathP : {A : I → Type ℓ} {B : I → Type ℓ'} {e : A i0 ≃ B i0} {f : A i1 ≃ B i1}
→ (h : PathP (λ i → A i → B i) (e .fst) (f .fst)) → PathP (λ i → A i ≃ B i) e f
equivPathP {e = e} {f = f} h =
λ i → (h i) , isProp→PathP (λ i → isPropIsEquiv (h i)) (e .snd) (f .snd) i
equivEq : {e f : A ≃ B} → (h : e .fst ≡ f .fst) → e ≡ f
equivEq = equivPathP
module _ {f : A → B} (equivF : isEquiv f) where
funIsEq : A → B
funIsEq = f
invIsEq : B → A
invIsEq y = equivF .equiv-proof y .fst .fst
secIsEq : section f invIsEq
secIsEq y = equivF .equiv-proof y .fst .snd
retIsEq : retract f invIsEq
retIsEq a i = equivF .equiv-proof (f a) .snd (a , refl) i .fst
commSqIsEq : ∀ a → Square (secIsEq (f a)) refl (cong f (retIsEq a)) refl
commSqIsEq a i = equivF .equiv-proof (f a) .snd (a , refl) i .snd
commPathIsEq : ∀ a → secIsEq (f a) ≡ cong f (retIsEq a)
commPathIsEq a i j =
hcomp
(λ k → λ
{ (i = i0) → secIsEq (f a) j
; (i = i1) → f (retIsEq a (j ∨ ~ k))
; (j = i0) → f (retIsEq a (i ∧ ~ k))
; (j = i1) → f a
})
(commSqIsEq a i j)
module _ (w : A ≃ B) where
invEq : B → A
invEq = invIsEq (snd w)
retEq : retract (w .fst) invEq
retEq = retIsEq (snd w)
secEq : section (w .fst) invEq
secEq = secIsEq (snd w)
open Iso
equivToIso : ∀ {ℓ ℓ'} {A : Type ℓ} {B : Type ℓ'} → A ≃ B → Iso A B
fun (equivToIso e) = e .fst
inv (equivToIso e) = invEq e
sec (equivToIso e) = secEq e
ret (equivToIso e) = retEq e
-- TODO: there should be a direct proof of this that doesn't use equivToIso
invEquiv : A ≃ B → B ≃ A
invEquiv e = isoToEquiv (invIso (equivToIso e))
invEquivIdEquiv : (A : Type ℓ) → invEquiv (idEquiv A) ≡ idEquiv A
invEquivIdEquiv _ = equivEq refl
compEquiv : A ≃ B → B ≃ C → A ≃ C
compEquiv f g .fst = g .fst ∘ f .fst
compEquiv {A = A} {C = C} f g .snd .equiv-proof c = contr
where
contractG = g .snd .equiv-proof c .snd
secFiller : (a : A) (p : g .fst (f .fst a) ≡ c) → _ {- square in A -}
secFiller a p = compPath-filler (cong (invEq f ∘ fst) (contractG (_ , p))) (retEq f a)
contr : isContr (fiber (g .fst ∘ f .fst) c)
contr .fst .fst = invEq f (invEq g c)
contr .fst .snd = cong (g .fst) (secEq f (invEq g c)) ∙ secEq g c
contr .snd (a , p) i .fst = secFiller a p i1 i
contr .snd (a , p) i .snd j =
hcomp
(λ k → λ
{ (i = i1) → fSquare k
; (j = i0) → g .fst (f .fst (secFiller a p k i))
; (j = i1) → contractG (_ , p) i .snd k
})
(g .fst (secEq f (contractG (_ , p) i .fst) j))
where
fSquare : I → C
fSquare k =
hcomp
(λ l → λ
{ (j = i0) → g .fst (f .fst (retEq f a k))
; (j = i1) → p (k ∧ l)
; (k = i0) → g .fst (secEq f (f .fst a) j)
; (k = i1) → p (j ∧ l)
})
(g .fst (f .snd .equiv-proof (f .fst a) .snd (a , refl) k .snd j))
_∙ₑ_ = compEquiv
compEquivIdEquiv : (e : A ≃ B) → compEquiv (idEquiv A) e ≡ e
compEquivIdEquiv e = equivEq refl
compEquivEquivId : (e : A ≃ B) → compEquiv e (idEquiv B) ≡ e
compEquivEquivId e = equivEq refl
invEquiv-is-rinv : (e : A ≃ B) → compEquiv e (invEquiv e) ≡ idEquiv A
invEquiv-is-rinv e = equivEq (funExt (retEq e))
invEquiv-is-linv : (e : A ≃ B) → compEquiv (invEquiv e) e ≡ idEquiv B
invEquiv-is-linv e = equivEq (funExt (secEq e))
compEquiv-assoc : (f : A ≃ B) (g : B ≃ C) (h : C ≃ D)
→ compEquiv f (compEquiv g h) ≡ compEquiv (compEquiv f g) h
compEquiv-assoc f g h = equivEq refl
LiftEquiv : A ≃ Lift {i = ℓ} {j = ℓ'} A
LiftEquiv .fst a .lower = a
LiftEquiv .snd .equiv-proof = strictContrFibers lower
Lift≃Lift : (e : A ≃ B) → Lift {j = ℓ'} A ≃ Lift {j = ℓ''} B
Lift≃Lift e .fst a .lower = e .fst (a .lower)
Lift≃Lift e .snd .equiv-proof b .fst .fst .lower = invEq e (b .lower)
Lift≃Lift e .snd .equiv-proof b .fst .snd i .lower =
e .snd .equiv-proof (b .lower) .fst .snd i
Lift≃Lift e .snd .equiv-proof b .snd (a , p) i .fst .lower =
e .snd .equiv-proof (b .lower) .snd (a .lower , cong lower p) i .fst
Lift≃Lift e .snd .equiv-proof b .snd (a , p) i .snd j .lower =
e .snd .equiv-proof (b .lower) .snd (a .lower , cong lower p) i .snd j
isContr→Equiv : isContr A → isContr B → A ≃ B
isContr→Equiv Actr Bctr = isoToEquiv (isContr→Iso Actr Bctr)
propBiimpl→Equiv : (Aprop : isProp A) (Bprop : isProp B) (f : A → B) (g : B → A) → A ≃ B
propBiimpl→Equiv Aprop Bprop f g = f , hf
where
hf : isEquiv f
hf .equiv-proof y .fst = (g y , Bprop (f (g y)) y)
hf .equiv-proof y .snd h i .fst = Aprop (g y) (h .fst) i
hf .equiv-proof y .snd h i .snd = isProp→isSet' Bprop (Bprop (f (g y)) y) (h .snd)
(cong f (Aprop (g y) (h .fst))) refl i
isEquivPropBiimpl→Equiv : isProp A → isProp B
→ ((A → B) × (B → A)) ≃ (A ≃ B)
isEquivPropBiimpl→Equiv {A = A} {B = B} Aprop Bprop = isoToEquiv isom where
isom : Iso (Σ (A → B) (λ _ → B → A)) (A ≃ B)
isom .fun (f , g) = propBiimpl→Equiv Aprop Bprop f g
isom .inv e = equivFun e , invEq e
isom .sec e = equivEq refl
isom .ret _ = refl
equivΠCod : ∀ {F : A → Type ℓ} {G : A → Type ℓ'}
→ ((x : A) → F x ≃ G x) → ((x : A) → F x) ≃ ((x : A) → G x)
equivΠCod k .fst f x = k x .fst (f x)
equivΠCod k .snd .equiv-proof f .fst .fst x = equivCtr (k x) (f x) .fst
equivΠCod k .snd .equiv-proof f .fst .snd i x = equivCtr (k x) (f x) .snd i
equivΠCod k .snd .equiv-proof f .snd (g , p) i .fst x =
equivCtrPath (k x) (f x) (g x , λ j → p j x) i .fst
equivΠCod k .snd .equiv-proof f .snd (g , p) i .snd j x =
equivCtrPath (k x) (f x) (g x , λ k → p k x) i .snd j
equivImplicitΠCod : ∀ {F : A → Type ℓ} {G : A → Type ℓ'}
→ ({x : A} → F x ≃ G x) → ({x : A} → F x) ≃ ({x : A} → G x)
equivImplicitΠCod k .fst f {x} = k {x} .fst (f {x})
equivImplicitΠCod k .snd .equiv-proof f .fst .fst {x} = equivCtr (k {x}) (f {x}) .fst
equivImplicitΠCod k .snd .equiv-proof f .fst .snd i {x} = equivCtr (k {x}) (f {x}) .snd i
equivImplicitΠCod k .snd .equiv-proof f .snd (g , p) i .fst {x} =
equivCtrPath (k {x}) (f {x}) (g {x} , λ j → p j {x}) i .fst
equivImplicitΠCod k .snd .equiv-proof f .snd (g , p) i .snd j {x} =
equivCtrPath (k {x}) (f {x}) (g {x} , λ k → p k {x}) i .snd j
equiv→Iso : (A ≃ B) → (C ≃ D) → Iso (A → C) (B → D)
equiv→Iso h k .Iso.fun f b = equivFun k (f (invEq h b))
equiv→Iso h k .Iso.inv g a = invEq k (g (equivFun h a))
equiv→Iso h k .Iso.sec g = funExt λ b → secEq k _ ∙ cong g (secEq h b)
equiv→Iso h k .Iso.ret f = funExt λ a → retEq k _ ∙ cong f (retEq h a)
equiv→ : (A ≃ B) → (C ≃ D) → (A → C) ≃ (B → D)
equiv→ h k = isoToEquiv (equiv→Iso h k)
equivΠ' : ∀ {ℓA ℓA' ℓB ℓB'} {A : Type ℓA} {A' : Type ℓA'}
{B : A → Type ℓB} {B' : A' → Type ℓB'}
(eA : A ≃ A')
(eB : {a : A} {a' : A'} → eA .fst a ≡ a' → B a ≃ B' a')
→ ((a : A) → B a) ≃ ((a' : A') → B' a')
equivΠ' {B' = B'} eA eB = isoToEquiv isom
where
open Iso
isom : Iso _ _
isom .fun f a' =
eB (secEq eA a') .fst (f (invEq eA a'))
isom .inv f' a =
invEq (eB refl) (f' (eA .fst a))
isom .sec f' =
funExt λ a' →
J (λ a'' p → eB p .fst (invEq (eB refl) (f' (p i0))) ≡ f' a'')
(secEq (eB refl) (f' (eA .fst (invEq eA a'))))
(secEq eA a')
isom .ret f =
funExt λ a →
subst
(λ p → invEq (eB refl) (eB p .fst (f (invEq eA (eA .fst a)))) ≡ f a)
(sym (commPathIsEq (eA .snd) a))
(J (λ a'' p → invEq (eB refl) (eB (cong (eA .fst) p) .fst (f (invEq eA (eA .fst a)))) ≡ f a'')
(retEq (eB refl) (f (invEq eA (eA .fst a))))
(retEq eA a))
equivΠ : ∀ {ℓA ℓA' ℓB ℓB'} {A : Type ℓA} {A' : Type ℓA'}
{B : A → Type ℓB} {B' : A' → Type ℓB'}
(eA : A ≃ A')
(eB : (a : A) → B a ≃ B' (eA .fst a))
→ ((a : A) → B a) ≃ ((a' : A') → B' a')
equivΠ {B = B} {B' = B'} eA eB = equivΠ' eA (λ {a = a} p → J (λ a' p → B a ≃ B' a') (eB a) p)
equivCompIso : (A ≃ B) → (C ≃ D) → Iso (A ≃ C) (B ≃ D)
equivCompIso h k .Iso.fun f = compEquiv (compEquiv (invEquiv h) f) k
equivCompIso h k .Iso.inv g = compEquiv (compEquiv h g) (invEquiv k)
equivCompIso h k .Iso.sec g = equivEq (equiv→Iso h k .Iso.sec (equivFun g))
equivCompIso h k .Iso.ret f = equivEq (equiv→Iso h k .Iso.ret (equivFun f))
equivComp : (A ≃ B) → (C ≃ D) → (A ≃ C) ≃ (B ≃ D)
equivComp h k = isoToEquiv (equivCompIso h k)
-- Some helpful notation:
_≃⟨_⟩_ : (X : Type ℓ) → (X ≃ B) → (B ≃ C) → (X ≃ C)
_ ≃⟨ f ⟩ g = compEquiv f g
_■ : (X : Type ℓ) → (X ≃ X)
_■ = idEquiv
infixr 0 _≃⟨_⟩_
infix 1 _■
composesToId→Equiv : (f : A → B) (g : B → A) → f ∘ g ≡ idfun B → isEquiv f → isEquiv g
composesToId→Equiv f g id iseqf =
isoToIsEquiv
(iso g f
(λ b → (λ i → equiv-proof iseqf (f b) .snd (g (f b) , cong (λ h → h (f b)) id) (~ i) .fst)
∙∙ cong (λ x → equiv-proof iseqf (f b) .fst .fst) id
∙∙ λ i → equiv-proof iseqf (f b) .snd (b , refl) i .fst)
λ a i → id i a)
precomposesToId→Equiv : (f : A → B) (g : B → A) → f ∘ g ≡ idfun B → isEquiv g → isEquiv f
precomposesToId→Equiv f g id iseqg = subst isEquiv (sym f-≡-g⁻) (snd (invEquiv (_ , iseqg)))
where
g⁻ = invEq (g , iseqg)
f-≡-g⁻ : _
f-≡-g⁻ = cong (f ∘_ ) (cong fst (sym (invEquiv-is-linv (g , iseqg)))) ∙ cong (_∘ g⁻) id
-- equivalence between isEquiv and isEquiv'
isEquiv-isEquiv'-Iso : (f : A → B) → Iso (isEquiv f) (isEquiv' f)
isEquiv-isEquiv'-Iso f .fun p = p .equiv-proof
isEquiv-isEquiv'-Iso f .inv q .equiv-proof = q
isEquiv-isEquiv'-Iso f .sec q = refl
isEquiv-isEquiv'-Iso f .ret p i .equiv-proof = p .equiv-proof
isEquiv≃isEquiv' : (f : A → B) → isEquiv f ≃ isEquiv' f
isEquiv≃isEquiv' f = isoToEquiv (isEquiv-isEquiv'-Iso f)
-- The fact that funExt is an equivalence can be found in Cubical.Functions.FunExtEquiv-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Foundations.HLevels.html`
{-
Basic theory about h-levels/n-types:
- Basic properties of isContr, isProp and isSet (definitions are in Prelude)
- Hedberg's theorem can be found in Cubical/Relation/Nullary/Properties
-}
module Cubical.Foundations.HLevels where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Function
open import Cubical.Foundations.Structure
open import Cubical.Functions.FunExtEquiv
open import Cubical.Foundations.GroupoidLaws
open import Cubical.Foundations.Pointed.Base
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Path
open import Cubical.Foundations.Transport
open import Cubical.Foundations.Univalence using (ua ; univalenceIso)
open import Cubical.Data.Sigma
open import Cubical.Data.Nat using (ℕ; zero; suc; _+_; +-zero; +-comm)
open Iso
HLevel : Type₀
HLevel = ℕ
private
variable
ℓ ℓ' ℓ'' ℓ''' ℓ'''' ℓ''''' : Level
A A' : Type ℓ
B : A → Type ℓ
C : (x : A) → B x → Type ℓ
D : (x : A) (y : B x) → C x y → Type ℓ
E : (x : A) (y : B x) → (z : C x y) → D x y z → Type ℓ
F : (x : A) (y : B x) (z : C x y) (w : D x y z) (v : E x y z w) → Type ℓ
G : (x : A) (y : B x) (z : C x y) (w : D x y z) (v : E x y z w) (u : F x y z w v) → Type ℓ
w x y z : A
n : HLevel
isOfHLevel : HLevel → Type ℓ → Type ℓ
isOfHLevel 0 A = isContr A
isOfHLevel 1 A = isProp A
isOfHLevel (suc (suc n)) A = (x y : A) → isOfHLevel (suc n) (x ≡ y)
isOfHLevelFun : (n : HLevel) {A : Type ℓ} {B : Type ℓ'} (f : A → B) → Type (ℓ-max ℓ ℓ')
isOfHLevelFun n f = ∀ b → isOfHLevel n (fiber f b)
isOfHLevelΩ→isOfHLevel :
∀ {ℓ} {A : Type ℓ} (n : ℕ)
→ ((x : A) → isOfHLevel (suc n) (x ≡ x)) → isOfHLevel (2 + n) A
isOfHLevelΩ→isOfHLevel zero hΩ x y =
J (λ y p → (q : x ≡ y) → p ≡ q) (hΩ x refl)
isOfHLevelΩ→isOfHLevel (suc n) hΩ x y =
J (λ y p → (q : x ≡ y) → isOfHLevel (suc n) (p ≡ q)) (hΩ x refl)
TypeOfHLevel : ∀ ℓ → HLevel → Type (ℓ-suc ℓ)
TypeOfHLevel ℓ n = TypeWithStr ℓ (isOfHLevel n)
hProp hSet hGroupoid h2Groupoid : ∀ ℓ → Type (ℓ-suc ℓ)
hProp ℓ = TypeOfHLevel ℓ 1
hSet ℓ = TypeOfHLevel ℓ 2
hGroupoid ℓ = TypeOfHLevel ℓ 3
h2Groupoid ℓ = TypeOfHLevel ℓ 4
-- lower h-levels imply higher h-levels
isOfHLevelSuc : (n : HLevel) → isOfHLevel n A → isOfHLevel (suc n) A
isOfHLevelSuc 0 = isContr→isProp
isOfHLevelSuc 1 = isProp→isSet
isOfHLevelSuc (suc (suc n)) h a b = isOfHLevelSuc (suc n) (h a b)
isSet→isGroupoid : isSet A → isGroupoid A
isSet→isGroupoid = isOfHLevelSuc 2
isGroupoid→is2Groupoid : isGroupoid A → is2Groupoid A
isGroupoid→is2Groupoid = isOfHLevelSuc 3
isOfHLevelPlus : (m : HLevel) → isOfHLevel n A → isOfHLevel (m + n) A
isOfHLevelPlus zero hA = hA
isOfHLevelPlus (suc m) hA = isOfHLevelSuc _ (isOfHLevelPlus m hA)
isContr→isOfHLevel : (n : HLevel) → isContr A → isOfHLevel n A
isContr→isOfHLevel zero cA = cA
isContr→isOfHLevel (suc n) cA = isOfHLevelSuc _ (isContr→isOfHLevel n cA)
isProp→isOfHLevelSuc : (n : HLevel) → isProp A → isOfHLevel (suc n) A
isProp→isOfHLevelSuc zero pA = pA
isProp→isOfHLevelSuc (suc n) pA = isOfHLevelSuc _ (isProp→isOfHLevelSuc n pA)
isOfHLevelPlus' : (m : HLevel) → isOfHLevel m A → isOfHLevel (m + n) A
isOfHLevelPlus' {n = n} 0 = isContr→isOfHLevel n
isOfHLevelPlus' {n = n} 1 = isProp→isOfHLevelSuc n
isOfHLevelPlus' {n = n} (suc (suc m)) hA a₀ a₁ = isOfHLevelPlus' (suc m) (hA a₀ a₁)
-- When proving a type has h-level n+1, we can assume it is inhabited.
-- To prove a type is a proposition, it suffices to prove it is contractible if inhabited
isOfHLevelSucIfInhabited→isOfHLevelSuc : ∀ n
→ (A → isOfHLevel (suc n) A) → isOfHLevel (suc n) A
isOfHLevelSucIfInhabited→isOfHLevelSuc zero hA a = hA a a
isOfHLevelSucIfInhabited→isOfHLevelSuc (suc n) hA a = hA a a
isContrIfInhabited→isProp : (A → isContr A) → isProp A
isContrIfInhabited→isProp hA =
isOfHLevelSucIfInhabited→isOfHLevelSuc 0 (isContr→isProp ∘ hA)
-- hlevel of path types
isProp→isContrPath : isProp A → (x y : A) → isContr (x ≡ y)
isProp→isContrPath h x y = h x y , isProp→isSet h x y _
isContr→isContrPath : isContr A → (x y : A) → isContr (x ≡ y)
isContr→isContrPath cA = isProp→isContrPath (isContr→isProp cA)
isOfHLevelPath' : (n : HLevel) → isOfHLevel (suc n) A → (x y : A) → isOfHLevel n (x ≡ y)
isOfHLevelPath' 0 = isProp→isContrPath
isOfHLevelPath' (suc n) h x y = h x y
isOfHLevelPath'⁻ : (n : HLevel) → ((x y : A) → isOfHLevel n (x ≡ y)) → isOfHLevel (suc n) A
isOfHLevelPath'⁻ zero h x y = h x y .fst
isOfHLevelPath'⁻ (suc n) h = h
isOfHLevelPath : (n : HLevel) → isOfHLevel n A → (x y : A) → isOfHLevel n (x ≡ y)
isOfHLevelPath 0 h x y = isContr→isContrPath h x y
isOfHLevelPath (suc n) h x y = isOfHLevelSuc n (isOfHLevelPath' n h x y)
-- h-level of isOfHLevel
isPropIsOfHLevel : (n : HLevel) → isProp (isOfHLevel n A)
isPropIsOfHLevel 0 = isPropIsContr
isPropIsOfHLevel 1 = isPropIsProp
isPropIsOfHLevel (suc (suc n)) f g i a b =
isPropIsOfHLevel (suc n) (f a b) (g a b) i
isPropIsSet : isProp (isSet A)
isPropIsSet = isPropIsOfHLevel 2
isPropIsGroupoid : isProp (isGroupoid A)
isPropIsGroupoid = isPropIsOfHLevel 3
isPropIs2Groupoid : isProp (is2Groupoid A)
isPropIs2Groupoid = isPropIsOfHLevel 4
TypeOfHLevel≡ : (n : HLevel) {X Y : TypeOfHLevel ℓ n} → ⟨ X ⟩ ≡ ⟨ Y ⟩ → X ≡ Y
TypeOfHLevel≡ n = Σ≡Prop (λ _ → isPropIsOfHLevel n)
-- hlevels are preserved by retracts (and consequently equivalences)
isContrRetract
: ∀ {B : Type ℓ}
→ (f : A → B) (g : B → A)
→ (h : retract f g)
→ (v : isContr B) → isContr A
fst (isContrRetract f g h (b , p)) = g b
snd (isContrRetract f g h (b , p)) x = (cong g (p (f x))) ∙ (h x)
isPropRetract
: {B : Type ℓ}
(f : A → B) (g : B → A)
(h : (x : A) → g (f x) ≡ x)
→ isProp B → isProp A
isPropRetract f g h p x y i =
hcomp
(λ j → λ
{ (i = i0) → h x j
; (i = i1) → h y j})
(g (p (f x) (f y) i))
isSetRetract
: {B : Type ℓ}
(f : A → B) (g : B → A)
(h : (x : A) → g (f x) ≡ x)
→ isSet B → isSet A
isSetRetract f g h set x y p q i j =
hcomp (λ k → λ { (i = i0) → h (p j) k
; (i = i1) → h (q j) k
; (j = i0) → h x k
; (j = i1) → h y k})
(g (set (f x) (f y)
(cong f p) (cong f q) i j))
isGroupoidRetract
: {B : Type ℓ}
(f : A → B) (g : B → A)
(h : (x : A) → g (f x) ≡ x)
→ isGroupoid B → isGroupoid A
isGroupoidRetract f g h grp x y p q P Q i j k =
hcomp ((λ l → λ { (i = i0) → h (P j k) l
; (i = i1) → h (Q j k) l
; (j = i0) → h (p k) l
; (j = i1) → h (q k) l
; (k = i0) → h x l
; (k = i1) → h y l}))
(g (grp (f x) (f y) (cong f p) (cong f q)
(cong (cong f) P) (cong (cong f) Q) i j k))
is2GroupoidRetract
: {B : Type ℓ}
(f : A → B) (g : B → A)
(h : (x : A) → g (f x) ≡ x)
→ is2Groupoid B → is2Groupoid A
is2GroupoidRetract f g h grp x y p q P Q R S i j k l =
hcomp (λ r → λ { (i = i0) → h (R j k l) r
; (i = i1) → h (S j k l) r
; (j = i0) → h (P k l) r
; (j = i1) → h (Q k l) r
; (k = i0) → h (p l) r
; (k = i1) → h (q l) r
; (l = i0) → h x r
; (l = i1) → h y r})
(g (grp (f x) (f y) (cong f p) (cong f q)
(cong (cong f) P) (cong (cong f) Q)
(cong (cong (cong f)) R) (cong (cong (cong f)) S) i j k l))
isOfHLevelRetract
: (n : HLevel) {B : Type ℓ}
(f : A → B) (g : B → A)
(h : (x : A) → g (f x) ≡ x)
→ isOfHLevel n B → isOfHLevel n A
isOfHLevelRetract 0 = isContrRetract
isOfHLevelRetract 1 = isPropRetract
isOfHLevelRetract 2 = isSetRetract
isOfHLevelRetract 3 = isGroupoidRetract
isOfHLevelRetract 4 = is2GroupoidRetract
isOfHLevelRetract (suc (suc (suc (suc (suc n))))) f g h ofLevel x y p q P Q R S =
isOfHLevelRetract (suc n) (cong (cong (cong (cong f))))
(λ s i j k l →
hcomp (λ r → λ { (i = i0) → h (R j k l) r
; (i = i1) → h (S j k l) r
; (j = i0) → h (P k l) r
; (j = i1) → h (Q k l) r
; (k = i0) → h (p l) r
; (k = i1) → h (q l) r
; (l = i0) → h x r
; (l = i1) → h y r})
(g (s i j k l)))
(λ s i j k l m →
hcomp (λ n → λ { (i = i1) → s j k l m
; (j = i0) → h (R k l m) (i ∨ n)
; (j = i1) → h (S k l m) (i ∨ n)
; (k = i0) → h (P l m) (i ∨ n)
; (k = i1) → h (Q l m) (i ∨ n)
; (l = i0) → h (p m) (i ∨ n)
; (l = i1) → h (q m) (i ∨ n)
; (m = i0) → h x (i ∨ n)
; (m = i1) → h y (i ∨ n) })
(h (s j k l m) i))
(ofLevel (f x) (f y)
(cong f p) (cong f q)
(cong (cong f) P) (cong (cong f) Q)
(cong (cong (cong f)) R) (cong (cong (cong f)) S))
isOfHLevelRetractFromIso : {A : Type ℓ} {B : Type ℓ'} (n : HLevel) → Iso A B → isOfHLevel n B → isOfHLevel n A
isOfHLevelRetractFromIso n e hlev = isOfHLevelRetract n (Iso.fun e) (Iso.inv e) (Iso.ret e) hlev
isOfHLevelRespectEquiv : {A : Type ℓ} {B : Type ℓ'} → (n : HLevel) → A ≃ B → isOfHLevel n A → isOfHLevel n B
isOfHLevelRespectEquiv n eq = isOfHLevelRetract n (invEq eq) (eq .fst) (secEq eq)
isContrRetractOfConstFun : {A : Type ℓ} {B : Type ℓ'} (b₀ : B)
→ Σ[ f ∈ (B → A) ] ((x : A) → (f ∘ (λ _ → b₀)) x ≡ x)
→ isContr A
fst (isContrRetractOfConstFun b₀ ret) = ret .fst b₀
snd (isContrRetractOfConstFun b₀ ret) y = ret .snd y
-- h-level of dependent path types
isOfHLevelPathP' : {A : I → Type ℓ} (n : HLevel)
→ isOfHLevel (suc n) (A i1)
→ (x : A i0) (y : A i1) → isOfHLevel n (PathP A x y)
isOfHLevelPathP' {A = A} n h x y =
isOfHLevelRetractFromIso n (PathPIsoPath _ x y) (isOfHLevelPath' n h _ _)
isOfHLevelPathP : {A : I → Type ℓ} (n : HLevel)
→ isOfHLevel n (A i1)
→ (x : A i0) (y : A i1) → isOfHLevel n (PathP A x y)
isOfHLevelPathP {A = A} n h x y =
isOfHLevelRetractFromIso n (PathPIsoPath _ x y) (isOfHLevelPath n h _ _)
-- Fillers for cubes from h-level
isSet→SquareP :
{A : I → I → Type ℓ}
(isSet : (i j : I) → isSet (A i j))
{a₀₀ : A i0 i0} {a₀₁ : A i0 i1} (a₀₋ : PathP (λ j → A i0 j) a₀₀ a₀₁)
{a₁₀ : A i1 i0} {a₁₁ : A i1 i1} (a₁₋ : PathP (λ j → A i1 j) a₁₀ a₁₁)
(a₋₀ : PathP (λ i → A i i0) a₀₀ a₁₀) (a₋₁ : PathP (λ i → A i i1) a₀₁ a₁₁)
→ SquareP A a₀₋ a₁₋ a₋₀ a₋₁
isSet→SquareP isset a₀₋ a₁₋ a₋₀ a₋₁ =
PathPIsoPath _ _ _ .Iso.inv (isOfHLevelPathP' 1 (isset _ _) _ _ _ _ )
isGroupoid→isGroupoid' : isGroupoid A → isGroupoid' A
isGroupoid→isGroupoid' {A = A} Agpd a₀₋₋ a₁₋₋ a₋₀₋ a₋₁₋ a₋₋₀ a₋₋₁ =
PathPIsoPath (λ i → Square (a₋₀₋ i) (a₋₁₋ i) (a₋₋₀ i) (a₋₋₁ i)) a₀₋₋ a₁₋₋ .Iso.inv
(isGroupoid→isPropSquare _ _ _ _ _ _)
where
isGroupoid→isPropSquare :
{a₀₀ a₀₁ : A} (a₀₋ : a₀₀ ≡ a₀₁)
{a₁₀ a₁₁ : A} (a₁₋ : a₁₀ ≡ a₁₁)
(a₋₀ : a₀₀ ≡ a₁₀) (a₋₁ : a₀₁ ≡ a₁₁)
→ isProp (Square a₀₋ a₁₋ a₋₀ a₋₁)
isGroupoid→isPropSquare a₀₋ a₁₋ a₋₀ a₋₁ =
isOfHLevelRetractFromIso 1 (PathPIsoPath (λ i → a₋₀ i ≡ a₋₁ i) a₀₋ a₁₋) (Agpd _ _ _ _)
isGroupoid'→isGroupoid : isGroupoid' A → isGroupoid A
isGroupoid'→isGroupoid Agpd' x y p q r s = Agpd' r s refl refl refl refl
-- h-level of Σ-types
isProp∃! : isProp (∃! A B)
isProp∃! = isPropIsContr
isContrΣ : isContr A → ((x : A) → isContr (B x)) → isContr (Σ A B)
isContrΣ {A = A} {B = B} (a , p) q =
let h : (x : A) (y : B x) → (q x) .fst ≡ y
h x y = (q x) .snd y
in (( a , q a .fst)
, ( λ x i → p (x .fst) i
, h (p (x .fst) i) (transp (λ j → B (p (x .fst) (i ∨ ~ j))) i (x .snd)) i))
isContrΣ' : (ca : isContr A) → isContr (B (fst ca)) → isContr (Σ A B)
isContrΣ' ca cb = isContrΣ ca (λ x → subst _ (snd ca x) cb)
section-Σ≡Prop
: (pB : (x : A) → isProp (B x)) {u v : Σ A B}
→ section (Σ≡Prop pB {u} {v}) (cong fst)
section-Σ≡Prop {A = A} pB {u} {v} p j i =
(p i .fst) , isProp→PathP (λ i → isOfHLevelPath 1 (pB (fst (p i)))
(Σ≡Prop pB {u} {v} (cong fst p) i .snd)
(p i .snd) )
refl refl i j
isEquiv-Σ≡Prop
: (pB : (x : A) → isProp (B x)) {u v : Σ A B}
→ isEquiv (Σ≡Prop pB {u} {v})
isEquiv-Σ≡Prop {A = A} pB {u} {v} = isoToIsEquiv (iso (Σ≡Prop pB) (cong fst) (section-Σ≡Prop pB) (λ _ → refl))
isPropΣ : isProp A → ((x : A) → isProp (B x)) → isProp (Σ A B)
isPropΣ pA pB t u = Σ≡Prop pB (pA (t .fst) (u .fst))
isOfHLevelΣ : ∀ n → isOfHLevel n A → ((x : A) → isOfHLevel n (B x))
→ isOfHLevel n (Σ A B)
isOfHLevelΣ 0 = isContrΣ
isOfHLevelΣ 1 = isPropΣ
isOfHLevelΣ {B = B} (suc (suc n)) h1 h2 x y =
isOfHLevelRetractFromIso (suc n)
(invIso (IsoΣPathTransportPathΣ _ _))
(isOfHLevelΣ (suc n) (h1 (fst x) (fst y)) λ x → h2 _ _ _)
isSetΣ : isSet A → ((x : A) → isSet (B x)) → isSet (Σ A B)
isSetΣ = isOfHLevelΣ 2
-- Useful consequence
isSetΣSndProp : isSet A → ((x : A) → isProp (B x)) → isSet (Σ A B)
isSetΣSndProp h p = isSetΣ h (λ x → isProp→isSet (p x))
isGroupoidΣ : isGroupoid A → ((x : A) → isGroupoid (B x)) → isGroupoid (Σ A B)
isGroupoidΣ = isOfHLevelΣ 3
is2GroupoidΣ : is2Groupoid A → ((x : A) → is2Groupoid (B x)) → is2Groupoid (Σ A B)
is2GroupoidΣ = isOfHLevelΣ 4
-- h-level of ×
isProp× : {A : Type ℓ} {B : Type ℓ'} → isProp A → isProp B → isProp (A × B)
isProp× pA pB = isPropΣ pA (λ _ → pB)
isProp×2 : {A : Type ℓ} {B : Type ℓ'} {C : Type ℓ''}
→ isProp A → isProp B → isProp C → isProp (A × B × C)
isProp×2 pA pB pC = isProp× pA (isProp× pB pC)
isProp×3 : {A : Type ℓ} {B : Type ℓ'} {C : Type ℓ''} {D : Type ℓ'''}
→ isProp A → isProp B → isProp C → isProp D → isProp (A × B × C × D)
isProp×3 pA pB pC pD = isProp×2 pA pB (isProp× pC pD)
isProp×4 : {A : Type ℓ} {B : Type ℓ'} {C : Type ℓ''} {D : Type ℓ'''} {E : Type ℓ''''}
→ isProp A → isProp B → isProp C → isProp D → isProp E → isProp (A × B × C × D × E)
isProp×4 pA pB pC pD pE = isProp×3 pA pB pC (isProp× pD pE)
isProp×5 : {A : Type ℓ} {B : Type ℓ'} {C : Type ℓ''} {D : Type ℓ'''} {E : Type ℓ''''} {F : Type ℓ'''''}
→ isProp A → isProp B → isProp C → isProp D → isProp E → isProp F
→ isProp (A × B × C × D × E × F)
isProp×5 pA pB pC pD pE pF = isProp×4 pA pB pC pD (isProp× pE pF)
isOfHLevel× : ∀ {A : Type ℓ} {B : Type ℓ'} n → isOfHLevel n A → isOfHLevel n B
→ isOfHLevel n (A × B)
isOfHLevel× n hA hB = isOfHLevelΣ n hA (λ _ → hB)
isSet× : ∀ {A : Type ℓ} {B : Type ℓ'} → isSet A → isSet B → isSet (A × B)
isSet× = isOfHLevel× 2
isGroupoid× : ∀ {A : Type ℓ} {B : Type ℓ'} → isGroupoid A → isGroupoid B
→ isGroupoid (A × B)
isGroupoid× = isOfHLevel× 3
is2Groupoid× : ∀ {A : Type ℓ} {B : Type ℓ'} → is2Groupoid A → is2Groupoid B
→ is2Groupoid (A × B)
is2Groupoid× = isOfHLevel× 4
-- h-level of Π-types
isOfHLevelΠ : ∀ n → ((x : A) → isOfHLevel n (B x))
→ isOfHLevel n ((x : A) → B x)
isOfHLevelΠ 0 h = (λ x → fst (h x)) , λ f i y → snd (h y) (f y) i
isOfHLevelΠ 1 h f g i x = (h x) (f x) (g x) i
isOfHLevelΠ 2 h f g F G i j z = h z (f z) (g z) (funExt⁻ F z) (funExt⁻ G z) i j
isOfHLevelΠ 3 h f g p q P Q i j k z =
h z (f z) (g z)
(funExt⁻ p z) (funExt⁻ q z)
(cong (λ f → funExt⁻ f z) P) (cong (λ f → funExt⁻ f z) Q) i j k
isOfHLevelΠ 4 h f g p q P Q R S i j k l z =
h z (f z) (g z)
(funExt⁻ p z) (funExt⁻ q z)
(cong (λ f → funExt⁻ f z) P) (cong (λ f → funExt⁻ f z) Q)
(cong (cong (λ f → funExt⁻ f z)) R) (cong (cong (λ f → funExt⁻ f z)) S) i j k l
isOfHLevelΠ (suc (suc (suc (suc (suc n))))) h f g p q P Q R S =
isOfHLevelRetract (suc n)
(cong (cong (cong funExt⁻))) (cong (cong (cong funExt))) (λ _ → refl)
(isOfHLevelΠ (suc (suc (suc (suc n)))) (λ x → h x (f x) (g x))
(funExt⁻ p) (funExt⁻ q)
(cong funExt⁻ P) (cong funExt⁻ Q)
(cong (cong funExt⁻) R) (cong (cong funExt⁻) S))
isOfHLevelΠ2 : (n : HLevel) → ((x : A) → (y : B x) → isOfHLevel n (C x y))
→ isOfHLevel n ((x : A) → (y : B x) → C x y)
isOfHLevelΠ2 n f = isOfHLevelΠ n (λ x → isOfHLevelΠ n (f x))
isContrΠ : (h : (x : A) → isContr (B x)) → isContr ((x : A) → B x)
isContrΠ = isOfHLevelΠ 0
isPropΠ : (h : (x : A) → isProp (B x)) → isProp ((x : A) → B x)
isPropΠ = isOfHLevelΠ 1
isPropΠ2 : (h : (x : A) (y : B x) → isProp (C x y))
→ isProp ((x : A) (y : B x) → C x y)
isPropΠ2 h = isPropΠ λ x → isPropΠ λ y → h x y
isPropΠ3 : (h : (x : A) (y : B x) (z : C x y) → isProp (D x y z))
→ isProp ((x : A) (y : B x) (z : C x y) → D x y z)
isPropΠ3 h = isPropΠ λ x → isPropΠ λ y → isPropΠ λ z → h x y z
isPropΠ4 : (h : (x : A) (y : B x) (z : C x y) (w : D x y z) → isProp (E x y z w))
→ isProp ((x : A) (y : B x) (z : C x y) (w : D x y z) → E x y z w)
isPropΠ4 h = isPropΠ λ _ → isPropΠ3 (h _)
isPropΠ5 : (h : (x : A) (y : B x) (z : C x y) (w : D x y z) (v : E x y z w) → isProp (F x y z w v))
→ isProp ((x : A) (y : B x) (z : C x y) (w : D x y z) (v : E x y z w) → F x y z w v)
isPropΠ5 h = isPropΠ λ _ → isPropΠ4 (h _)
isPropΠ6 : (h : (x : A) (y : B x) (z : C x y) (w : D x y z) (v : E x y z w) (u : F x y z w v) → isProp (G x y z w v u))
→ isProp ((x : A) (y : B x) (z : C x y) (w : D x y z) (v : E x y z w) (u : F x y z w v) → G x y z w v u)
isPropΠ6 h = isPropΠ λ _ → isPropΠ5 (h _)
isPropImplicitΠ : (h : (x : A) → isProp (B x)) → isProp ({x : A} → B x)
isPropImplicitΠ h f g i {x} = h x (f {x}) (g {x}) i
isPropImplicitΠ2 : (h : (x : A) (y : B x) → isProp (C x y)) → isProp ({x : A} {y : B x} → C x y)
isPropImplicitΠ2 h = isPropImplicitΠ (λ x → isPropImplicitΠ (λ y → h x y))
isPropImplicitΠ3 : (h : (x : A) (y : B x) (z : C x y) → isProp (D x y z)) →
isProp ({x : A} {y : B x} {z : C x y} → D x y z)
isPropImplicitΠ3 h = isPropImplicitΠ (λ x → isPropImplicitΠ2 (λ y → h x y))
isPropImplicitΠ4 : (h : (x : A) (y : B x) (z : C x y) (w : D x y z) → isProp (E x y z w)) →
isProp ({x : A} {y : B x} {z : C x y} {w : D x y z} → E x y z w)
isPropImplicitΠ4 h = isPropImplicitΠ (λ x → isPropImplicitΠ3 (λ y → h x y))
isProp→ : {A : Type ℓ} {B : Type ℓ'} → isProp B → isProp (A → B)
isProp→ pB = isPropΠ λ _ → pB
isSetΠ : ((x : A) → isSet (B x)) → isSet ((x : A) → B x)
isSetΠ = isOfHLevelΠ 2
isSetImplicitΠ : (h : (x : A) → isSet (B x)) → isSet ({x : A} → B x)
isSetImplicitΠ h f g F G i j {x} = h x (f {x}) (g {x}) (λ i → F i {x}) (λ i → G i {x}) i j
isSetImplicitΠ2 : (h : (x : A) → (y : B x) → isSet (C x y)) → isSet ({x : A} → {y : B x} → C x y)
isSetImplicitΠ2 h = isSetImplicitΠ (λ x → isSetImplicitΠ (λ y → h x y))
isSetImplicitΠ3 : (h : (x : A) → (y : B x) → (z : C x y) → isSet (D x y z)) →
isSet ({x : A} → {y : B x} → {z : C x y} → D x y z)
isSetImplicitΠ3 h = isSetImplicitΠ (λ x → isSetImplicitΠ2 (λ y → λ z → h x y z))
isSet→ : isSet A' → isSet (A → A')
isSet→ isSet-A' = isOfHLevelΠ 2 (λ _ → isSet-A')
isSetΠ2 : (h : (x : A) (y : B x) → isSet (C x y))
→ isSet ((x : A) (y : B x) → C x y)
isSetΠ2 h = isSetΠ λ x → isSetΠ λ y → h x y
isSetΠ3 : (h : (x : A) (y : B x) (z : C x y) → isSet (D x y z))
→ isSet ((x : A) (y : B x) (z : C x y) → D x y z)
isSetΠ3 h = isSetΠ λ x → isSetΠ λ y → isSetΠ λ z → h x y z
isGroupoidΠ : ((x : A) → isGroupoid (B x)) → isGroupoid ((x : A) → B x)
isGroupoidΠ = isOfHLevelΠ 3
isGroupoidΠ2 : (h : (x : A) (y : B x) → isGroupoid (C x y)) → isGroupoid ((x : A) (y : B x) → C x y)
isGroupoidΠ2 h = isGroupoidΠ λ _ → isGroupoidΠ λ _ → h _ _
isGroupoidΠ3 : (h : (x : A) (y : B x) (z : C x y) → isGroupoid (D x y z))
→ isGroupoid ((x : A) (y : B x) (z : C x y) → D x y z)
isGroupoidΠ3 h = isGroupoidΠ λ _ → isGroupoidΠ2 λ _ → h _ _
isGroupoidΠ4 : (h : (x : A) (y : B x) (z : C x y) (w : D x y z) → isGroupoid (E x y z w))
→ isGroupoid ((x : A) (y : B x) (z : C x y) (w : D x y z) → E x y z w)
isGroupoidΠ4 h = isGroupoidΠ λ _ → isGroupoidΠ3 λ _ → h _ _
is2GroupoidΠ : ((x : A) → is2Groupoid (B x)) → is2Groupoid ((x : A) → B x)
is2GroupoidΠ = isOfHLevelΠ 4
isOfHLevelΠ⁻ : ∀ {A : Type ℓ} {B : Type ℓ'} n
→ isOfHLevel n (A → B) → (A → isOfHLevel n B)
isOfHLevelΠ⁻ 0 h x = fst h x , λ y → funExt⁻ (snd h (const y)) x
isOfHLevelΠ⁻ 1 h x y z = funExt⁻ (h (const y) (const z)) x
isOfHLevelΠ⁻ (suc (suc n)) h x y z =
isOfHLevelΠ⁻ (suc n) (isOfHLevelRetractFromIso (suc n) funExtIso (h _ _)) x
isOfHLevel→∙ : {A : Pointed ℓ} {B : Pointed ℓ'} (n : ℕ)
→ isOfHLevel n (fst B) → isOfHLevel n (A →∙ B)
isOfHLevel→∙ n hlev =
isOfHLevelΣ n (isOfHLevelΠ n (λ _ → hlev))
λ _ → isOfHLevelPath n hlev _ _
-- h-level of A ≃ B and A ≡ B
isOfHLevel≃
: ∀ n {A : Type ℓ} {B : Type ℓ'}
→ (hA : isOfHLevel n A) (hB : isOfHLevel n B) → isOfHLevel n (A ≃ B)
isOfHLevel≃ zero {A = A} {B = B} hA hB = isContr→Equiv hA hB , contr
where
contr : (y : A ≃ B) → isContr→Equiv hA hB ≡ y
contr y = Σ≡Prop isPropIsEquiv (funExt (λ a → snd hB (fst y a)))
isOfHLevel≃ (suc n) {A = A} {B = B} hA hB =
isOfHLevelΣ (suc n) (isOfHLevelΠ _ λ _ → hB)
(λ f → isProp→isOfHLevelSuc n (isPropIsEquiv f))
isOfHLevel≡ : ∀ n → {A B : Type ℓ} (hA : isOfHLevel n A) (hB : isOfHLevel n B) →
isOfHLevel n (A ≡ B)
isOfHLevel≡ n hA hB = isOfHLevelRetractFromIso n univalenceIso (isOfHLevel≃ n hA hB)
isOfHLevel⁺≃ₗ
: ∀ n {A : Type ℓ} {B : Type ℓ'}
→ isOfHLevel (suc n) A → isOfHLevel (suc n) (A ≃ B)
isOfHLevel⁺≃ₗ zero pA e = isOfHLevel≃ 1 pA (isOfHLevelRespectEquiv 1 e pA) e
isOfHLevel⁺≃ₗ (suc n) hA e = isOfHLevel≃ m hA (isOfHLevelRespectEquiv m e hA) e
where
m = suc (suc n)
isOfHLevel⁺≃ᵣ
: ∀ n {A : Type ℓ} {B : Type ℓ'}
→ isOfHLevel (suc n) B → isOfHLevel (suc n) (A ≃ B)
isOfHLevel⁺≃ᵣ zero pB e
= isOfHLevel≃ 1 (isPropRetract (e .fst) (invEq e) (retEq e) pB) pB e
isOfHLevel⁺≃ᵣ (suc n) hB e
= isOfHLevel≃ m (isOfHLevelRetract m (e .fst) (invEq e) (retEq e) hB) hB e
where
m = suc (suc n)
isOfHLevel⁺≡ₗ
: ∀ n → {A B : Type ℓ}
→ isOfHLevel (suc n) A → isOfHLevel (suc n) (A ≡ B)
isOfHLevel⁺≡ₗ zero pA P = isOfHLevel≡ 1 pA (subst isProp P pA) P
isOfHLevel⁺≡ₗ (suc n) hA P
= isOfHLevel≡ m hA (subst (isOfHLevel m) P hA) P
where
m = suc (suc n)
isOfHLevel⁺≡ᵣ
: ∀ n → {A B : Type ℓ}
→ isOfHLevel (suc n) B → isOfHLevel (suc n) (A ≡ B)
isOfHLevel⁺≡ᵣ zero pB P = isOfHLevel≡ 1 (subst⁻ isProp P pB) pB P
isOfHLevel⁺≡ᵣ (suc n) hB P
= isOfHLevel≡ m (subst⁻ (isOfHLevel m) P hB) hB P
where
m = suc (suc n)
-- h-level of TypeOfHLevel
isPropHContr : isProp (TypeOfHLevel ℓ 0)
isPropHContr x y = Σ≡Prop (λ _ → isPropIsContr) (isOfHLevel≡ 0 (x .snd) (y .snd) .fst)
isOfHLevelTypeOfHLevel : ∀ n → isOfHLevel (suc n) (TypeOfHLevel ℓ n)
isOfHLevelTypeOfHLevel zero = isPropHContr
isOfHLevelTypeOfHLevel (suc n) (X , a) (Y , b) =
isOfHLevelRetract (suc n) (cong fst) (Σ≡Prop λ _ → isPropIsOfHLevel (suc n))
(section-Σ≡Prop λ _ → isPropIsOfHLevel (suc n))
(isOfHLevel≡ (suc n) a b)
isSetHProp : isSet (hProp ℓ)
isSetHProp = isOfHLevelTypeOfHLevel 1
isGroupoidHSet : isGroupoid (hSet ℓ)
isGroupoidHSet = isOfHLevelTypeOfHLevel 2
-- h-level of lifted type
isOfHLevelLift : ∀ {ℓ ℓ'} (n : HLevel) {A : Type ℓ} → isOfHLevel n A → isOfHLevel n (Lift {j = ℓ'} A)
isOfHLevelLift n = isOfHLevelRetract n lower lift λ _ → refl
isOfHLevelLower : ∀ {ℓ ℓ'} (n : HLevel) {A : Type ℓ} → isOfHLevel n (Lift {j = ℓ'} A) → isOfHLevel n A
isOfHLevelLower n = isOfHLevelRetract n lift lower λ _ → refl
----------------------------
-- More consequences of isProp and isContr
inhProp→isContr : A → isProp A → isContr A
inhProp→isContr x h = x , h x
extend : isContr A → (∀ φ → (u : Partial φ A) → Sub A φ u)
extend (x , p) φ u = inS (hcomp (λ { j (φ = i1) → p (u 1=1) j }) x)
isContrPartial→isContr : ∀ {ℓ} {A : Type ℓ}
→ (extend : ∀ φ → Partial φ A → A)
→ (∀ u → u ≡ (extend i1 λ { _ → u}))
→ isContr A
isContrPartial→isContr {A = A} extend law
= ex , λ y → law ex ∙ (λ i → Aux.v y i) ∙ sym (law y)
where ex = extend i0 empty
module Aux (y : A) (i : I) where
φ = ~ i ∨ i
u : Partial φ A
u = λ { (i = i0) → ex ; (i = i1) → y }
v = extend φ u
-- Dependent h-level over a type
isOfHLevelDep : HLevel → {A : Type ℓ} (B : A → Type ℓ') → Type (ℓ-max ℓ ℓ')
isOfHLevelDep 0 {A = A} B = {a : A} → Σ[ b ∈ B a ] ({a' : A} (b' : B a') (p : a ≡ a') → PathP (λ i → B (p i)) b b')
isOfHLevelDep 1 {A = A} B = {a0 a1 : A} (b0 : B a0) (b1 : B a1) (p : a0 ≡ a1) → PathP (λ i → B (p i)) b0 b1
isOfHLevelDep (suc (suc n)) {A = A} B = {a0 a1 : A} (b0 : B a0) (b1 : B a1) → isOfHLevelDep (suc n) {A = a0 ≡ a1} (λ p → PathP (λ i → B (p i)) b0 b1)
isContrDep : {A : Type ℓ} (B : A → Type ℓ') → Type (ℓ-max ℓ ℓ')
isContrDep = isOfHLevelDep 0
isPropDep : {A : Type ℓ} (B : A → Type ℓ') → Type (ℓ-max ℓ ℓ')
isPropDep = isOfHLevelDep 1
isContrDep∘
: {A' : Type ℓ} (f : A' → A) → isContrDep B → isContrDep (B ∘ f)
isContrDep∘ f cB {a} = λ where
.fst → cB .fst
.snd b' p → cB .snd b' (cong f p)
isPropDep∘ : {A' : Type ℓ} (f : A' → A) → isPropDep B → isPropDep (B ∘ f)
isPropDep∘ f pB b0 b1 = pB b0 b1 ∘ cong f
isOfHLevelDep→isOfHLevel : (n : HLevel)
→ {A : Type ℓ} {B : A → Type ℓ'} → isOfHLevelDep n {A = A} B → (a : A) → isOfHLevel n (B a)
isOfHLevelDep→isOfHLevel 0 h a = h .fst , λ b → h .snd b refl
isOfHLevelDep→isOfHLevel 1 h a x y = h x y refl
isOfHLevelDep→isOfHLevel (suc (suc n)) h a x y = isOfHLevelDep→isOfHLevel (suc n) (h x y) refl
isOfHLevel→isOfHLevelDep : (n : HLevel)
→ {A : Type ℓ} {B : A → Type ℓ'} (h : (a : A) → isOfHLevel n (B a)) → isOfHLevelDep n {A = A} B
isOfHLevel→isOfHLevelDep 0 h {a} =
(h a .fst , λ b' p → isProp→PathP (λ i → isContr→isProp (h (p i))) (h a .fst) b')
isOfHLevel→isOfHLevelDep 1 h = λ b0 b1 p → isProp→PathP (λ i → h (p i)) b0 b1
isOfHLevel→isOfHLevelDep (suc (suc n)) {A = A} {B} h {a0} {a1} b0 b1 =
isOfHLevel→isOfHLevelDep (suc n) (λ p → helper p)
where
helper : (p : a0 ≡ a1) →
isOfHLevel (suc n) (PathP (λ i → B (p i)) b0 b1)
helper p = J (λ a1 p → ∀ b1 → isOfHLevel (suc n) (PathP (λ i → B (p i)) b0 b1))
(λ _ → h _ _ _) p b1
isContrDep→isPropDep : isOfHLevelDep 0 B → isOfHLevelDep 1 B
isContrDep→isPropDep {B = B} Bctr {a0 = a0} b0 b1 p i
= comp (λ k → B (p (i ∧ k))) (λ k → λ where
(i = i0) → Bctr .snd b0 refl k
(i = i1) → Bctr .snd b1 p k)
(c0 .fst)
where
c0 = Bctr {a0}
isPropDep→isSetDep : isOfHLevelDep 1 B → isOfHLevelDep 2 B
isPropDep→isSetDep {B = B} Bprp b0 b1 b2 b3 p i j
= comp (λ k → B (p (i ∧ k) (j ∧ k))) (λ k → λ where
(j = i0) → Bprp b0 b0 refl k
(i = i0) → Bprp b0 (b2 j) (λ k → p i0 (j ∧ k)) k
(i = i1) → Bprp b0 (b3 j) (λ k → p k (j ∧ k)) k
(j = i1) → Bprp b0 b1 (λ k → p (i ∧ k) (j ∧ k)) k)
b0
isOfHLevelDepSuc : (n : HLevel) → isOfHLevelDep n B → isOfHLevelDep (suc n) B
isOfHLevelDepSuc 0 = isContrDep→isPropDep
isOfHLevelDepSuc 1 = isPropDep→isSetDep
isOfHLevelDepSuc (suc (suc n)) Blvl b0 b1 = isOfHLevelDepSuc (suc n) (Blvl b0 b1)
isPropDep→isSetDep'
: isOfHLevelDep 1 B
→ {p : w ≡ x} {q : y ≡ z} {r : w ≡ y} {s : x ≡ z}
→ {tw : B w} {tx : B x} {ty : B y} {tz : B z}
→ (sq : Square p q r s)
→ (tp : PathP (λ i → B (p i)) tw tx)
→ (tq : PathP (λ i → B (q i)) ty tz)
→ (tr : PathP (λ i → B (r i)) tw ty)
→ (ts : PathP (λ i → B (s i)) tx tz)
→ SquareP (λ i j → B (sq i j)) tp tq tr ts
isPropDep→isSetDep' {B = B} Bprp {p} {q} {r} {s} {tw} sq tp tq tr ts i j
= comp (λ k → B (sq (i ∧ k) (j ∧ k))) (λ k → λ where
(i = i0) → Bprp tw (tp j) (λ k → p (k ∧ j)) k
(i = i1) → Bprp tw (tq j) (λ k → sq (i ∧ k) (j ∧ k)) k
(j = i0) → Bprp tw (tr i) (λ k → r (k ∧ i)) k
(j = i1) → Bprp tw (ts i) (λ k → sq (k ∧ i) (j ∧ k)) k)
tw
isOfHLevelΣ' : ∀ n → isOfHLevel n A → isOfHLevelDep n B → isOfHLevel n (Σ A B)
isOfHLevelΣ' 0 Actr Bctr .fst = (Actr .fst , Bctr .fst)
isOfHLevelΣ' 0 Actr Bctr .snd (x , y) i
= Actr .snd x i , Bctr .snd y (Actr .snd x) i
isOfHLevelΣ' 1 Alvl Blvl (w , y) (x , z) i .fst = Alvl w x i
isOfHLevelΣ' 1 Alvl Blvl (w , y) (x , z) i .snd = Blvl y z (Alvl w x) i
isOfHLevelΣ' {A = A} {B = B} (suc (suc n)) Alvl Blvl (w , y) (x , z)
= isOfHLevelRetract (suc n)
(λ p → (λ i → p i .fst) , λ i → p i .snd)
ΣPathP
(λ x → refl)
(isOfHLevelΣ' (suc n) (Alvl w x) (Blvl y z))
ΣSquareSet : ((x : A) → isSet (B x)) → {u v w x : Σ A B}
→ {p : u ≡ v} {q : v ≡ w} {r : x ≡ w} {s : u ≡ x}
→ Square (cong fst p) (cong fst r)
(cong fst s) (cong fst q)
→ Square p r s q
fst (ΣSquareSet pB sq i j) = sq i j
snd (ΣSquareSet {B = B} pB {p = p} {q = q} {r = r} {s = s} sq i j) = lem i j
where
lem : SquareP (λ i j → B (sq i j))
(cong snd p) (cong snd r) (cong snd s) (cong snd q)
lem = toPathP (isOfHLevelPathP' 1 (pB _) _ _ _ _)
module _ (isSet-A : isSet A) (isSet-A' : isSet A') where
isSet-SetsIso : isSet (Iso A A')
isSet-SetsIso x y p₀ p₁ = h
where
module X = Iso x
module Y = Iso y
f-p : ∀ i₁ → (Iso.fun (p₀ i₁) , Iso.inv (p₀ i₁)) ≡
(Iso.fun (p₁ i₁) , Iso.inv (p₁ i₁))
fst (f-p i₁ i) a = isSet-A' (X.fun a ) (Y.fun a ) (cong _ p₀) (cong _ p₁) i i₁
snd (f-p i₁ i) a' = isSet-A (X.inv a') (Y.inv a') (cong _ p₀) (cong _ p₁) i i₁
s-p : ∀ b → _
s-p b =
isSet→SquareP (λ i j → isProp→isSet (isSet-A' _ _))
refl refl (λ i₁ → (Iso.sec (p₀ i₁) b)) (λ i₁ → (Iso.sec (p₁ i₁) b))
r-p : ∀ a → _
r-p a =
isSet→SquareP (λ i j → isProp→isSet (isSet-A _ _))
refl refl (λ i₁ → (Iso.ret (p₀ i₁) a)) (λ i₁ → (Iso.ret (p₁ i₁) a))
h : p₀ ≡ p₁
Iso.fun (h i i₁) = fst (f-p i₁ i)
Iso.inv (h i i₁) = snd (f-p i₁ i)
Iso.sec (h i i₁) b = s-p b i₁ i
Iso.ret (h i i₁) a = r-p a i₁ i
SetsIso≡-ext : ∀ {a b : Iso A A'}
→ (∀ x → Iso.fun a x ≡ Iso.fun b x)
→ (∀ x → Iso.inv a x ≡ Iso.inv b x)
→ a ≡ b
Iso.fun (SetsIso≡-ext {a} {b} fun≡ inv≡ i) x = fun≡ x i
Iso.inv (SetsIso≡-ext {a} {b} fun≡ inv≡ i) x = inv≡ x i
Iso.sec (SetsIso≡-ext {a} {b} fun≡ inv≡ i) b₁ =
isSet→SquareP (λ _ _ → isSet-A')
(Iso.sec a b₁)
(Iso.sec b b₁)
(λ i → fun≡ (inv≡ b₁ i) i)
refl i
Iso.ret (SetsIso≡-ext {a} {b} fun≡ inv≡ i) a₁ =
isSet→SquareP (λ _ _ → isSet-A)
(Iso.ret a a₁)
(Iso.ret b a₁)
(λ i → inv≡ (fun≡ a₁ i) i )
refl i
SetsIso≡ : ∀ {a b : Iso A A'}
→ (Iso.fun a ≡ Iso.fun b)
→ (Iso.inv a ≡ Iso.inv b)
→ a ≡ b
SetsIso≡ p q =
SetsIso≡-ext (funExt⁻ p) (funExt⁻ q)
isSet→Iso-Iso-≃ : Iso (Iso A A') (A ≃ A')
isSet→Iso-Iso-≃ = ww
where
open Iso
ww : Iso _ _
fun ww = isoToEquiv
inv ww = equivToIso
sec ww b = equivEq refl
ret ww a = SetsIso≡ refl refl
isSet→isEquiv-isoToPath : isEquiv isoToEquiv
isSet→isEquiv-isoToPath = isoToIsEquiv isSet→Iso-Iso-≃
isSet→Iso-Iso-≡ : (isSet-A : isSet A) → (isSet-A' : isSet A') → Iso (Iso A A') (A ≡ A')
isSet→Iso-Iso-≡ isSet-A isSet-A' = ww
where
open Iso
ww : Iso _ _
fun ww = isoToPath
inv ww = pathToIso
sec ww b = isInjectiveTransport (funExt λ _ → transportRefl _)
ret ww a = SetsIso≡-ext isSet-A isSet-A' (λ _ → transportRefl (fun a _)) λ _ → cong (inv a) (transportRefl _)
hSet-Iso-Iso-≡ : (A : hSet ℓ) → (A' : hSet ℓ) → Iso (Iso (fst A) (fst A')) (A ≡ A')
hSet-Iso-Iso-≡ A A' = compIso (isSet→Iso-Iso-≡ (snd A) (snd A')) (equivToIso (_ , isEquiv-Σ≡Prop λ _ → isPropIsSet))
module _ (B : (i j k : I) → Type ℓ)
{c₀₀₀ : B i0 i0 i0} {c₀₀₁ : B i0 i0 i1} {c₀₁₀ : B i0 i1 i0} {c₀₁₁ : B i0 i1 i1}
{c₁₀₀ : B i1 i0 i0} {c₁₀₁ : B i1 i0 i1} {c₁₁₀ : B i1 i1 i0} {c₁₁₁ : B i1 i1 i1}
{c₀₀₋ : PathP (λ k → B i0 i0 k) c₀₀₀ c₀₀₁} {c₀₁₋ : PathP (λ k → B i0 i1 k) c₀₁₀ c₀₁₁}
{c₀₋₀ : PathP (λ i → B i0 i i0) c₀₀₀ c₀₁₀} {c₀₋₁ : PathP (λ i → B i0 i i1) c₀₀₁ c₀₁₁}
{c₁₀₋ : PathP (λ k → B i1 i0 k) c₁₀₀ c₁₀₁} {c₁₁₋ : PathP (λ k → B i1 i1 k) c₁₁₀ c₁₁₁}
{c₁₋₀ : PathP (λ i → B i1 i i0) c₁₀₀ c₁₁₀} {c₁₋₁ : PathP (λ i → B i1 i i1) c₁₀₁ c₁₁₁}
{c₋₀₀ : PathP (λ i → B i i0 i0) c₀₀₀ c₁₀₀} {c₋₀₁ : PathP (λ i → B i i0 i1) c₀₀₁ c₁₀₁}
{c₋₁₀ : PathP (λ i → B i i1 i0) c₀₁₀ c₁₁₀} {c₋₁₁ : PathP (λ i → B i i1 i1) c₀₁₁ c₁₁₁}
(c₀₋₋ : SquareP (λ j k → B i0 j k) c₀₀₋ c₀₁₋ c₀₋₀ c₀₋₁)
(c₁₋₋ : SquareP (λ j k → B i1 j k) c₁₀₋ c₁₁₋ c₁₋₀ c₁₋₁)
(c₋₀₋ : SquareP (λ i k → B i i0 k) c₀₀₋ c₁₀₋ c₋₀₀ c₋₀₁)
(c₋₁₋ : SquareP (λ i k → B i i1 k) c₀₁₋ c₁₁₋ c₋₁₀ c₋₁₁)
(c₋₋₀ : SquareP (λ i j → B i j i0) c₀₋₀ c₁₋₀ c₋₀₀ c₋₁₀)
(c₋₋₁ : SquareP (λ i j → B i j i1) c₀₋₁ c₁₋₁ c₋₀₁ c₋₁₁) where
CubeP : Type ℓ
CubeP = PathP (λ i → SquareP (λ j k → B i j k)
(c₋₀₋ i) (c₋₁₋ i)
(c₋₋₀ i) (c₋₋₁ i))
c₀₋₋ c₁₋₋
isGroupoid→CubeP : isGroupoid (B i1 i1 i1) → CubeP
isGroupoid→CubeP grpd =
isOfHLevelPathP' 0 (isOfHLevelPathP' 1 (isOfHLevelPathP' 2 grpd _ _) _ _) _ _ .fst
Π-contractDomIso : (c : isContr A) → Iso ((x : A) → B x) (B (c .fst))
Π-contractDomIso {B = B} c .fun f = f (c .fst)
Π-contractDomIso {B = B} c .inv b x = subst B (c .snd x) b
Π-contractDomIso {B = B} c .sec b i = transp (λ j → B (isProp→isSet (isContr→isProp c) _ _ (c .snd (c .fst)) refl i j)) i b
Π-contractDomIso {B = B} c .ret f = funExt λ x → fromPathP (cong f (c .snd x))
Π-contractDom : (c : isContr A) → ((x : A) → B x) ≃ B (c .fst)
Π-contractDom c = isoToEquiv (Π-contractDomIso c)-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Foundations.Isomorphism.html`
{-
Theory about isomorphisms
- Definitions of [section] and [retract]
- Definition of isomorphisms ([Iso])
- Any isomorphism is an equivalence ([isoToEquiv])
-}
module Cubical.Foundations.Isomorphism where
open import Cubical.Core.Glue
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.GroupoidLaws
open import Cubical.Foundations.Function
open import Cubical.Foundations.Equiv.Base
private
variable
ℓ ℓ' : Level
A B C : Type ℓ
-- Section and retract
module _ {ℓ ℓ'} {A : Type ℓ} {B : Type ℓ'} where
section : (f : A → B) → (g : B → A) → Type ℓ'
section f g = ∀ b → f (g b) ≡ b
-- NB: `g` is the retraction!
retract : (f : A → B) → (g : B → A) → Type ℓ
retract f g = ∀ a → g (f a) ≡ a
record Iso {ℓ ℓ'} (A : Type ℓ) (B : Type ℓ') : Type (ℓ-max ℓ ℓ') where
no-eta-equality
constructor iso
field
fun : A → B
inv : B → A
sec : section fun inv
ret : retract fun inv
isIso : (A → B) → Type _
isIso {A = A} {B = B} f = Σ[ g ∈ (B → A) ] Σ[ _ ∈ section f g ] retract f g
isoFunInjective : (f : Iso A B) → (x y : A) → Iso.fun f x ≡ Iso.fun f y → x ≡ y
isoFunInjective f x y h = sym (Iso.ret f x) ∙∙ cong (Iso.inv f) h ∙∙ Iso.ret f y
isoInvInjective : (f : Iso A B) → (x y : B) → Iso.inv f x ≡ Iso.inv f y → x ≡ y
isoInvInjective f x y h = sym (Iso.sec f x) ∙∙ cong (Iso.fun f) h ∙∙ Iso.sec f y
-- Any iso is an equivalence
module _ (i : Iso A B) where
open Iso i renaming ( fun to f
; inv to g
; sec to s
; ret to t)
private
module _ (y : B) (x0 x1 : A) (p0 : f x0 ≡ y) (p1 : f x1 ≡ y) where
fill0 : I → I → A
fill0 i = hfill (λ k → λ { (i = i1) → t x0 k
; (i = i0) → g y })
(inS (g (p0 (~ i))))
fill1 : I → I → A
fill1 i = hfill (λ k → λ { (i = i1) → t x1 k
; (i = i0) → g y })
(inS (g (p1 (~ i))))
fill2 : I → I → A
fill2 i = hfill (λ k → λ { (i = i1) → fill1 k i1
; (i = i0) → fill0 k i1 })
(inS (g y))
p : x0 ≡ x1
p i = fill2 i i1
sq : I → I → A
sq i j = hcomp (λ k → λ { (i = i1) → fill1 j (~ k)
; (i = i0) → fill0 j (~ k)
; (j = i1) → t (fill2 i i1) (~ k)
; (j = i0) → g y })
(fill2 i j)
sq1 : I → I → B
sq1 i j = hcomp (λ k → λ { (i = i1) → s (p1 (~ j)) k
; (i = i0) → s (p0 (~ j)) k
; (j = i1) → s (f (p i)) k
; (j = i0) → s y k })
(f (sq i j))
lemIso : (x0 , p0) ≡ (x1 , p1)
lemIso i .fst = p i
lemIso i .snd = λ j → sq1 i (~ j)
isoToIsEquiv : isEquiv f
isoToIsEquiv .equiv-proof y .fst .fst = g y
isoToIsEquiv .equiv-proof y .fst .snd = s y
isoToIsEquiv .equiv-proof y .snd z = lemIso y (g y) (fst z) (s y) (snd z)
isoToEquiv : Iso A B → A ≃ B
isoToEquiv i .fst = i .Iso.fun
isoToEquiv i .snd = isoToIsEquiv i
IsoToIsIso : (f : Iso A B) → isIso (f .Iso.fun)
IsoToIsIso f .fst = f .Iso.inv
IsoToIsIso f .snd .fst = f .Iso.sec
IsoToIsIso f .snd .snd = f .Iso.ret
isIsoToIso : {f : A → B} → isIso f → Iso A B
isIsoToIso {f = f} fIsIso .Iso.fun = f
isIsoToIso fIsIso .Iso.inv = fIsIso .fst
isIsoToIso fIsIso .Iso.sec = fIsIso .snd .fst
isIsoToIso fIsIso .Iso.ret = fIsIso .snd .snd
isIsoToIsEquiv : {f : A → B} → isIso f → isEquiv f
isIsoToIsEquiv fIsIso = isoToIsEquiv (isIsoToIso fIsIso)
isoToPath : Iso A B → A ≡ B
isoToPath {A = A} {B = B} f i =
Glue B (λ { (i = i0) → (A , isoToEquiv f)
; (i = i1) → (B , idEquiv B) })
open Iso
invIso : Iso A B → Iso B A
fun (invIso f) = inv f
inv (invIso f) = fun f
sec (invIso f) = ret f
ret (invIso f) = sec f
compIso : Iso A B → Iso B C → Iso A C
fun (compIso i j) = fun j ∘ fun i
inv (compIso i j) = inv i ∘ inv j
sec (compIso i j) b = cong (fun j) (sec i (inv j b)) ∙ sec j b
ret (compIso i j) a = cong (inv i) (ret j (fun i a)) ∙ ret i a
composesToId→Iso : (G : Iso A B) (g : B → A) → G .fun ∘ g ≡ idfun B → Iso B A
fun (composesToId→Iso _ g _) = g
inv (composesToId→Iso j _ _) = fun j
sec (composesToId→Iso i g path) b =
sym (ret i (g (fun i b))) ∙∙ cong (λ g → inv i (g (fun i b))) path ∙∙ ret i b
ret (composesToId→Iso _ _ path) b i = path i b
idIso : Iso A A
fun idIso = idfun _
inv idIso = idfun _
sec idIso _ = refl
ret idIso _ = refl
compIsoIdL : (isom : Iso A B) → compIso idIso isom ≡ isom
fun (compIsoIdL isom i) = fun isom
inv (compIsoIdL isom i) = inv isom
sec (compIsoIdL isom i) b = lUnit (isom .sec b) (~ i)
ret (compIsoIdL isom i) a = rUnit (isom .ret a) (~ i)
compIsoIdR : (isom : Iso A B) → compIso isom idIso ≡ isom
fun (compIsoIdR isom i) = fun isom
inv (compIsoIdR isom i) = inv isom
sec (compIsoIdR isom i) b = rUnit (isom .sec b) (~ i)
ret (compIsoIdR isom i) a = lUnit (isom .ret a) (~ i)
LiftIso : Iso A (Lift {i = ℓ} {j = ℓ'} A)
fun LiftIso = lift
inv LiftIso = lower
sec LiftIso _ = refl
ret LiftIso _ = refl
isContr→Iso : isContr A → isContr B → Iso A B
fun (isContr→Iso _ Bctr) _ = Bctr .fst
inv (isContr→Iso Actr _) _ = Actr .fst
sec (isContr→Iso _ Bctr) = Bctr .snd
ret (isContr→Iso Actr _) = Actr .snd
isContr→Iso' : isContr A → isContr B → (A → B) → Iso A B
fun (isContr→Iso' _ Bctr f) = f
inv (isContr→Iso' Actr _ _) _ = Actr .fst
sec (isContr→Iso' _ Bctr f) = isContr→isProp Bctr _
ret (isContr→Iso' Actr _ _) = Actr .snd
isProp→Iso : (Aprop : isProp A) (Bprop : isProp B) (f : A → B) (g : B → A) → Iso A B
fun (isProp→Iso _ _ f _) = f
inv (isProp→Iso _ _ _ g) = g
sec (isProp→Iso _ Bprop f g) b = Bprop (f (g b)) b
ret (isProp→Iso Aprop _ f g) a = Aprop (g (f a)) a
domIso : ∀ {ℓ} {C : Type ℓ} → Iso A B → Iso (A → C) (B → C)
fun (domIso e) f b = f (inv e b)
inv (domIso e) f a = f (fun e a)
sec (domIso e) f i x = f (sec e x i)
ret (domIso e) f i x = f (ret e x i)
-- Helpful notation
_Iso⟨_⟩_ : ∀ {ℓ ℓ' ℓ''} {B : Type ℓ'} {C : Type ℓ''} (X : Type ℓ) → Iso X B → Iso B C → Iso X C
_ Iso⟨ f ⟩ g = compIso f g
_∎Iso : ∀ {ℓ} (A : Type ℓ) → Iso A A
A ∎Iso = idIso {A = A}
infixr 0 _Iso⟨_⟩_
infix 1 _∎Iso
codomainIsoDep : ∀ {ℓ ℓ' ℓ''} {A : Type ℓ} {B : A → Type ℓ'} {C : A → Type ℓ''}
→ ((a : A) → Iso (B a) (C a))
→ Iso ((a : A) → B a) ((a : A) → C a)
fun (codomainIsoDep is) f a = fun (is a) (f a)
inv (codomainIsoDep is) f a = inv (is a) (f a)
sec (codomainIsoDep is) f = funExt λ a → sec (is a) (f a)
ret (codomainIsoDep is) f = funExt λ a → ret (is a) (f a)
codomainIso : ∀ {ℓ ℓ' ℓ''} {A : Type ℓ} {B : Type ℓ'} {C : Type ℓ''}
→ Iso B C
→ Iso (A → B) (A → C)
codomainIso z = codomainIsoDep λ _ → z
endoIso : Iso A B → Iso (A → A) (B → B)
endoIso is = compIso (domIso is) (codomainIso is)
binaryOpIso : Iso A B → Iso (A → A → A) (B → B → B)
binaryOpIso is = compIso (domIso is) (codomainIso (endoIso is))
Iso≡Set : isSet A → isSet B → (f g : Iso A B)
→ ((x : A) → f .fun x ≡ g .fun x)
→ ((x : B) → f .inv x ≡ g .inv x)
→ f ≡ g
fun (Iso≡Set hA hB f g hfun hinv i) x = hfun x i
inv (Iso≡Set hA hB f g hfun hinv i) x = hinv x i
sec (Iso≡Set hA hB f g hfun hinv i) x j =
isSet→isSet' hB (sec f x) (sec g x) (λ i → hfun (hinv x i) i) refl i j
ret (Iso≡Set hA hB f g hfun hinv i) x j =
isSet→isSet' hA (ret f x) (ret g x) (λ i → hinv (hfun x i) i) refl i j
transportIsoToPath : (f : Iso A B) (x : A) → transport (isoToPath f) x ≡ f .fun x
transportIsoToPath f x = transportRefl _
transportIsoToPath⁻ : (f : Iso A B) (x : B) → transport (sym (isoToPath f)) x ≡ f .inv x
transportIsoToPath⁻ f x = cong (f .inv) (transportRefl _)-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Foundations.Pointed.Homogeneous.html`
{-
Definition of a homogeneous pointed type, and proofs that pi, product, path, and discrete types are homogeneous
Portions of this file adapted from Nicolai Kraus' code here:
https://bitbucket.org/nicolaikraus/agda/src/e30d70c72c6af8e62b72eefabcc57623dd921f04/trunc-inverse.lagda
-}
module Cubical.Foundations.Pointed.Homogeneous where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Univalence
open import Cubical.Foundations.Path
open import Cubical.Data.Sigma
open import Cubical.Data.Empty as ⊥
open import Cubical.Relation.Nullary
open import Cubical.Foundations.GroupoidLaws
open import Cubical.Foundations.Pointed.Base
open import Cubical.Foundations.Pointed.Properties
open import Cubical.Structures.Pointed
{-
We might say that a type is homogeneous if its automorphism group acts transitively;
this could be phrased with a propositional truncation.
Here we demand something much stronger, namely that we are given automorphisms
that carry the base point to any given point y.
If in addition we require this automorphism to be the identity for the base point,
then we recover the notion of a left-invertible H-space, and indeed,
any homogeneous type in our sense gives rise to such, as shown in:
Cubical.Homotopy.HSpace
-}
isHomogeneous : ∀ {ℓ} → Pointed ℓ → Type (ℓ-suc ℓ)
isHomogeneous {ℓ} (A , x) = ∀ y → Path (Pointed ℓ) (A , x) (A , y)
-- Pointed functions into a homogeneous type are equal as soon as they are equal
-- as unpointed functions
→∙Homogeneous≡ : ∀ {ℓ ℓ'} {A∙ : Pointed ℓ} {B∙ : Pointed ℓ'} {f∙ g∙ : A∙ →∙ B∙}
(h : isHomogeneous B∙) → f∙ .fst ≡ g∙ .fst → f∙ ≡ g∙
→∙Homogeneous≡ {A∙ = A∙@(_ , a₀)} {B∙@(B , _)} {f∙@(_ , f₀)} {g∙@(_ , g₀)} h p =
subst (λ Q∙ → PathP (λ i → A∙ →∙ Q∙ i) f∙ g∙) (sym (flipSquare fix)) badPath
where
badPath : PathP (λ i → A∙ →∙ (B , (sym f₀ ∙∙ funExt⁻ p a₀ ∙∙ g₀) i)) f∙ g∙
badPath i .fst = p i
badPath i .snd j = doubleCompPath-filler (sym f₀) (funExt⁻ p a₀) g₀ j i
fix : PathP (λ i → B∙ ≡ (B , (sym f₀ ∙∙ funExt⁻ p a₀ ∙∙ g₀) i)) refl refl
fix i =
hcomp
(λ j → λ
{ (i = i0) → lCancel (h (pt B∙)) j
; (i = i1) → lCancel (h (pt B∙)) j
})
(sym (h (pt B∙)) ∙ h ((sym f₀ ∙∙ funExt⁻ p a₀ ∙∙ g₀) i))
→∙HomogeneousPathP :
∀ {ℓ ℓ'} {A∙ A∙' : Pointed ℓ} {B∙ B∙' : Pointed ℓ'}
{f∙ : A∙ →∙ B∙} {g∙ : A∙' →∙ B∙'} (p : A∙ ≡ A∙') (q : B∙ ≡ B∙')
(h : isHomogeneous B∙')
→ PathP (λ i → fst (p i) → fst (q i)) (f∙ .fst) (g∙ .fst)
→ PathP (λ i → p i →∙ q i) f∙ g∙
→∙HomogeneousPathP p q h r = toPathP (→∙Homogeneous≡ h (fromPathP r))
→∙Homogeneous≡Path : ∀ {ℓ ℓ'} {A∙ : Pointed ℓ} {B∙ : Pointed ℓ'} {f∙ g∙ : A∙ →∙ B∙}
(h : isHomogeneous B∙) → (p q : f∙ ≡ g∙) → cong fst p ≡ cong fst q → p ≡ q
→∙Homogeneous≡Path {A∙ = A∙@(A , a₀)} {B∙@(B , b)} {f∙@(f , f₀)} {g∙@(g , g₀)} h p q r =
transport (λ k
→ PathP (λ i
→ PathP (λ j → (A , a₀) →∙ newPath-refl p q r i j (~ k))
(f , f₀) (g , g₀)) p q)
(badPath p q r)
where
newPath : (p q : f∙ ≡ g∙) (r : cong fst p ≡ cong fst q)
→ Square (refl {x = b}) refl refl refl
newPath p q r i j =
hcomp (λ k → λ {(i = i0) → cong snd p j k
; (i = i1) → cong snd q j k
; (j = i0) → f₀ k
; (j = i1) → g₀ k})
(r i j a₀)
newPath-refl : (p q : f∙ ≡ g∙) (r : cong fst p ≡ cong fst q)
→ PathP (λ i → (PathP (λ j → B∙ ≡ (B , newPath p q r i j))) refl refl) refl refl
newPath-refl p q r i j k =
hcomp (λ w → λ { (i = i0) → lCancel (h b) w k
; (i = i1) → lCancel (h b) w k
; (j = i0) → lCancel (h b) w k
; (j = i1) → lCancel (h b) w k
; (k = i0) → lCancel (h b) w k
; (k = i1) → B , newPath p q r i j})
((sym (h b) ∙ h (newPath p q r i j)) k)
badPath : (p q : f∙ ≡ g∙) (r : cong fst p ≡ cong fst q)
→ PathP (λ i →
PathP (λ j → A∙ →∙ (B , newPath p q r i j))
(f , f₀) (g , g₀))
p q
fst (badPath p q r i j) = r i j
snd (badPath p q s i j) k =
hcomp (λ r → λ { (i = i0) → snd (p j) (r ∧ k)
; (i = i1) → snd (q j) (r ∧ k)
; (j = i0) → f₀ (k ∧ r)
; (j = i1) → g₀ (k ∧ r)
; (k = i0) → s i j a₀})
(s i j a₀)
→∙HomogeneousSquare : ∀ {ℓ ℓ'} {A∙ : Pointed ℓ} {B∙ : Pointed ℓ'} {f∙ g∙ h∙ l∙ : A∙ →∙ B∙}
(h : isHomogeneous B∙) → (s : f∙ ≡ h∙) (t : g∙ ≡ l∙) (p : f∙ ≡ g∙) (q : h∙ ≡ l∙)
→ Square (cong fst p) (cong fst q) (cong fst s) (cong fst t)
→ Square p q s t
→∙HomogeneousSquare {f∙ = f∙} {g∙ = g∙} {h∙ = h∙} {l∙ = l∙} h =
J (λ h∙ s → (t : g∙ ≡ l∙) (p : f∙ ≡ g∙) (q : h∙ ≡ l∙) →
Square (cong fst p) (cong fst q) (cong fst s) (cong fst t) →
Square p q s t)
(J (λ l∙ t → (p : f∙ ≡ g∙) (q : f∙ ≡ l∙)
→ Square (cong fst p) (cong fst q) refl (cong fst t)
→ Square p q refl t)
(→∙Homogeneous≡Path {f∙ = f∙} {g∙ = g∙} h))
isHomogeneousPi : ∀ {ℓ ℓ'} {A : Type ℓ} {B∙ : A → Pointed ℓ'}
→ (∀ a → isHomogeneous (B∙ a)) → isHomogeneous (Πᵘ∙ A B∙)
isHomogeneousPi h f i .fst = ∀ a → typ (h a (f a) i)
isHomogeneousPi h f i .snd a = pt (h a (f a) i)
isHomogeneousΠ∙ : ∀ {ℓ ℓ'} (A : Pointed ℓ) (B : typ A → Type ℓ')
→ (b₀ : B (pt A))
→ ((a : typ A) (x : B a) → isHomogeneous (B a , x))
→ (f : Π∙ A B b₀)
→ isHomogeneous (Π∙ A B b₀ , f)
fst (isHomogeneousΠ∙ A B b₀ h f g i) =
Σ[ r ∈ ((a : typ A) → fst ((h a (fst f a) (fst g a)) i)) ]
r (pt A) ≡ hcomp (λ k → λ {(i = i0) → snd f k
; (i = i1) → snd g k})
(snd (h (pt A) (fst f (pt A)) (fst g (pt A)) i))
snd (isHomogeneousΠ∙ A B b₀ h f g i) =
(λ a → snd (h a (fst f a) (fst g a) i))
, λ j → hcomp (λ k → λ { (i = i0) → snd f (k ∧ j)
; (i = i1) → snd g (k ∧ j)
; (j = i0) → snd (h (pt A) (fst f (pt A))
(fst g (pt A)) i)})
(snd (h (pt A) (fst f (pt A)) (fst g (pt A)) i))
isHomogeneous→∙ : ∀ {ℓ ℓ'} {A∙ : Pointed ℓ} {B∙ : Pointed ℓ'}
→ isHomogeneous B∙ → isHomogeneous (A∙ →∙ B∙ ∙)
isHomogeneous→∙ {A∙ = A∙} {B∙} h f∙ =
ΣPathP
( (λ i → Π∙ A∙ (λ a → T a i) (t₀ i))
, PathPIsoPath _ _ _ .Iso.inv
(→∙Homogeneous≡ h
(PathPIsoPath (λ i → (a : typ A∙) → T a i) (λ _ → pt B∙) _ .Iso.fun
(λ i a → pt (h (f∙ .fst a) i))))
)
where
T : ∀ a → typ B∙ ≡ typ B∙
T a i = typ (h (f∙ .fst a) i)
t₀ : PathP (λ i → T (pt A∙) i) (pt B∙) (pt B∙)
t₀ = cong pt (h (f∙ .fst (pt A∙))) ▷ f∙ .snd
isHomogeneousProd : ∀ {ℓ ℓ'} {A∙ : Pointed ℓ} {B∙ : Pointed ℓ'}
→ isHomogeneous A∙ → isHomogeneous B∙ → isHomogeneous (A∙ ×∙ B∙)
isHomogeneousProd hA hB (a , b) i .fst = typ (hA a i) × typ (hB b i)
isHomogeneousProd hA hB (a , b) i .snd .fst = pt (hA a i)
isHomogeneousProd hA hB (a , b) i .snd .snd = pt (hB b i)
isHomogeneousPath : ∀ {ℓ} (A : Type ℓ) {x y : A} (p : x ≡ y) → isHomogeneous ((x ≡ y) , p)
isHomogeneousPath A {x} {y} p q
= pointed-sip ((x ≡ y) , p) ((x ≡ y) , q) (eqv , compPathr-cancel p q)
where eqv : (x ≡ y) ≃ (x ≡ y)
eqv = compPathlEquiv (q ∙ sym p)
module HomogeneousDiscrete {ℓ} {A∙ : Pointed ℓ} (dA : Discrete (typ A∙)) (y : typ A∙) where
-- switches pt A∙ with y
switch : typ A∙ → typ A∙
switch x with dA x (pt A∙)
... | yes _ = y
... | no _ with dA x y
... | yes _ = pt A∙
... | no _ = x
switch-ptA∙ : switch (pt A∙) ≡ y
switch-ptA∙ with dA (pt A∙) (pt A∙)
... | yes _ = refl
... | no ¬p = ⊥.rec (¬p refl)
switch-idp : ∀ x → switch (switch x) ≡ x
switch-idp x with dA x (pt A∙)
switch-idp x | yes p with dA y (pt A∙)
switch-idp x | yes p | yes q = q ∙ sym p
switch-idp x | yes p | no _ with dA y y
switch-idp x | yes p | no _ | yes _ = sym p
switch-idp x | yes p | no _ | no ¬p = ⊥.rec (¬p refl)
switch-idp x | no ¬p with dA x y
switch-idp x | no ¬p | yes p with dA y (pt A∙)
switch-idp x | no ¬p | yes p | yes q = ⊥.rec (¬p (p ∙ q))
switch-idp x | no ¬p | yes p | no _ with dA (pt A∙) (pt A∙)
switch-idp x | no ¬p | yes p | no _ | yes _ = sym p
switch-idp x | no ¬p | yes p | no _ | no ¬q = ⊥.rec (¬q refl)
switch-idp x | no ¬p | no ¬q with dA x (pt A∙)
switch-idp x | no ¬p | no ¬q | yes p = ⊥.rec (¬p p)
switch-idp x | no ¬p | no ¬q | no _ with dA x y
switch-idp x | no ¬p | no ¬q | no _ | yes q = ⊥.rec (¬q q)
switch-idp x | no ¬p | no ¬q | no _ | no _ = refl
switch-eqv : typ A∙ ≃ typ A∙
switch-eqv = isoToEquiv (iso switch switch switch-idp switch-idp)
isHomogeneousDiscrete : ∀ {ℓ} {A∙ : Pointed ℓ} (dA : Discrete (typ A∙)) → isHomogeneous A∙
isHomogeneousDiscrete {ℓ} {A∙} dA y
= pointed-sip (typ A∙ , pt A∙) (typ A∙ , y) (switch-eqv , switch-ptA∙)
where open HomogeneousDiscrete {ℓ} {A∙} dA y-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Foundations.Powerset.html`
{-
This file introduces the "powerset" of a type in the style of
Escardó's lecture notes:
https://www.cs.bham.ac.uk/~mhe/HoTT-UF-in-Agda-Lecture-Notes/HoTT-UF-Agda.html#propositionalextensionality
-}
module Cubical.Foundations.Powerset where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.HLevels
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Structure
open import Cubical.Foundations.Function
open import Cubical.Foundations.Univalence using (hPropExt)
open import Cubical.Data.Sigma
private
variable
ℓ : Level
X : Type ℓ
ℙ : Type ℓ → Type (ℓ-suc ℓ)
ℙ X = X → hProp _
isSetℙ : isSet (ℙ X)
isSetℙ = isSetΠ λ x → isSetHProp
infix 5 _∈_
_∈_ : {X : Type ℓ} → X → ℙ X → Type ℓ
x ∈ A = ⟨ A x ⟩
_⊆_ : {X : Type ℓ} → ℙ X → ℙ X → Type ℓ
A ⊆ B = ∀ x → x ∈ A → x ∈ B
∈-isProp : (A : ℙ X) (x : X) → isProp (x ∈ A)
∈-isProp A = snd ∘ A
⊆-isProp : (A B : ℙ X) → isProp (A ⊆ B)
⊆-isProp A B = isPropΠ2 (λ x _ → ∈-isProp B x)
⊆-refl : (A : ℙ X) → A ⊆ A
⊆-refl A x = idfun (x ∈ A)
subst-∈ : (A : ℙ X) {x y : X} → x ≡ y → x ∈ A → y ∈ A
subst-∈ A = subst (_∈ A)
⊆-refl-consequence : (A B : ℙ X) → A ≡ B → (A ⊆ B) × (B ⊆ A)
⊆-refl-consequence A B p = subst (A ⊆_) p (⊆-refl A)
, subst (B ⊆_) (sym p) (⊆-refl B)
⊆-extensionality : (A B : ℙ X) → (A ⊆ B) × (B ⊆ A) → A ≡ B
⊆-extensionality A B (φ , ψ) =
funExt (λ x → TypeOfHLevel≡ 1 (hPropExt (A x .snd) (B x .snd) (φ x) (ψ x)))
⊆-trans : (A B C : ℙ X) → A ⊆ B → B ⊆ C → A ⊆ C
⊆-trans A B C φ ψ x = ψ x ∘ φ x
⊆-antisym : (A B : ℙ X) → A ⊆ B → B ⊆ A → A ≡ B
⊆-antisym A B φ ψ = ⊆-extensionality A B (φ , ψ)
⊆-extensionalityEquiv : (A B : ℙ X) → (A ⊆ B) × (B ⊆ A) ≃ (A ≡ B)
⊆-extensionalityEquiv A B = isoToEquiv (iso (⊆-extensionality A B)
(⊆-refl-consequence A B)
(λ _ → isSetℙ A B _ _)
(λ _ → isPropΣ (⊆-isProp A B) (λ _ → ⊆-isProp B A) _ _))-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Foundations.SIP.html`
{-
In this file we apply the cubical machinery to Martin Hötzel-Escardó's
structure identity principle:
https://www.cs.bham.ac.uk/~mhe/HoTT-UF-in-Agda-Lecture-Notes/HoTT-UF-Agda.html#sns
-}
module Cubical.Foundations.SIP where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Univalence renaming (ua-pathToEquiv to ua-pathToEquiv')
open import Cubical.Foundations.Transport
open import Cubical.Foundations.Function
open import Cubical.Foundations.Path
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Equiv
open import Cubical.Data.Sigma
open import Cubical.Foundations.Structure public
private
variable
ℓ ℓ₁ ℓ₂ ℓ₃ ℓ₄ ℓ₅ : Level
S : Type ℓ₁ → Type ℓ₂
-- Note that for any equivalence (f , e) : X ≃ Y the type ι (X , s) (Y , t) (f , e) need not to be
-- a proposition. Indeed this type should correspond to the ways s and t can be identified
-- as S-structures. This we call a standard notion of structure or SNS.
-- We will use a different definition, but the two definitions are interchangeable.
SNS : (S : Type ℓ₁ → Type ℓ₂) (ι : StrEquiv S ℓ₃) → Type (ℓ-max (ℓ-max (ℓ-suc ℓ₁) ℓ₂) ℓ₃)
SNS {ℓ₁} S ι = ∀ {X : Type ℓ₁} (s t : S X) → ι (X , s) (X , t) (idEquiv X) ≃ (s ≡ t)
-- We introduce the notation for structure preserving equivalences a
-- bit differently, but this definition doesn't actually change from
-- Escardó's notes.
_≃[_]_ : (A : TypeWithStr ℓ₁ S) (ι : StrEquiv S ℓ₂) (B : TypeWithStr ℓ₁ S) → Type (ℓ-max ℓ₁ ℓ₂)
A ≃[ ι ] B = Σ[ e ∈ typ A ≃ typ B ] (ι A B e)
-- The following PathP version of SNS is a bit easier to work with
-- for the proof of the SIP
UnivalentStr : (S : Type ℓ₁ → Type ℓ₂) (ι : StrEquiv S ℓ₃) → Type (ℓ-max (ℓ-max (ℓ-suc ℓ₁) ℓ₂) ℓ₃)
UnivalentStr {ℓ₁} S ι =
{A B : TypeWithStr ℓ₁ S} (e : typ A ≃ typ B)
→ ι A B e ≃ PathP (λ i → S (ua e i)) (str A) (str B)
-- A quick sanity-check that our definition is interchangeable with
-- Escardó's. The direction SNS→UnivalentStr corresponds more or less
-- to a dependent EquivJ formulation of Escardó's homomorphism-lemma.
UnivalentStr→SNS : (S : Type ℓ₁ → Type ℓ₂) (ι : StrEquiv S ℓ₃)
→ UnivalentStr S ι → SNS S ι
UnivalentStr→SNS S ι θ {X = X} s t =
ι (X , s) (X , t) (idEquiv X)
≃⟨ θ (idEquiv X) ⟩
PathP (λ i → S (ua (idEquiv X) i)) s t
≃⟨ pathToEquiv (λ j → PathP (λ i → S (uaIdEquiv {A = X} j i)) s t) ⟩
s ≡ t
■
SNS→UnivalentStr : (ι : StrEquiv S ℓ₃) → SNS S ι → UnivalentStr S ι
SNS→UnivalentStr {S = S} ι θ {A = A} {B = B} e = EquivJ P C e (str A) (str B)
where
Y = typ B
P : (X : Type _) → X ≃ Y → Type _
P X e' = (s : S X) (t : S Y) → ι (X , s) (Y , t) e' ≃ PathP (λ i → S (ua e' i)) s t
C : (s t : S Y) → ι (Y , s) (Y , t) (idEquiv Y) ≃ PathP (λ i → S (ua (idEquiv Y) i)) s t
C s t =
ι (Y , s) (Y , t) (idEquiv Y)
≃⟨ θ s t ⟩
s ≡ t
≃⟨ pathToEquiv (λ j → PathP (λ i → S (uaIdEquiv {A = Y} (~ j) i)) s t) ⟩
PathP (λ i → S (ua (idEquiv Y) i)) s t
■
TransportStr : {S : Type ℓ → Type ℓ₁} (α : EquivAction S) → Type (ℓ-max (ℓ-suc ℓ) ℓ₁)
TransportStr {ℓ} {S = S} α =
{X Y : Type ℓ} (e : X ≃ Y) (s : S X) → equivFun (α e) s ≡ subst S (ua e) s
TransportStr→UnivalentStr : {S : Type ℓ → Type ℓ₁} (α : EquivAction S)
→ TransportStr α → UnivalentStr S (EquivAction→StrEquiv α)
TransportStr→UnivalentStr {S = S} α τ {X , s} {Y , t} e =
equivFun (α e) s ≡ t
≃⟨ pathToEquiv (cong (_≡ t) (τ e s)) ⟩
subst S (ua e) s ≡ t
≃⟨ invEquiv (PathP≃Path _ _ _) ⟩
PathP (λ i → S (ua e i)) s t
■
UnivalentStr→TransportStr : {S : Type ℓ → Type ℓ₁} (α : EquivAction S)
→ UnivalentStr S (EquivAction→StrEquiv α) → TransportStr α
UnivalentStr→TransportStr {S = S} α θ e s =
invEq (θ e) (transport-filler (cong S (ua e)) s)
invTransportStr : {S : Type ℓ → Type ℓ₂} (α : EquivAction S) (τ : TransportStr α)
{X Y : Type ℓ} (e : X ≃ Y) (t : S Y) → invEq (α e) t ≡ subst⁻ S (ua e) t
invTransportStr {S = S} α τ e t =
sym (transport⁻Transport (cong S (ua e)) (invEq (α e) t))
∙∙ sym (cong (subst⁻ S (ua e)) (τ e (invEq (α e) t)))
∙∙ cong (subst⁻ S (ua e)) (secEq (α e) t)
--- We can now define an invertible function
---
--- sip : A ≃[ ι ] B → A ≡ B
module _ {S : Type ℓ₁ → Type ℓ₂} {ι : StrEquiv S ℓ₃}
(θ : UnivalentStr S ι) (A B : TypeWithStr ℓ₁ S)
where
sip : A ≃[ ι ] B → A ≡ B
sip (e , p) i = ua e i , θ e .fst p i
SIP : A ≃[ ι ] B ≃ (A ≡ B)
SIP =
sip , isoToIsEquiv (compIso (Σ-cong-iso (invIso univalenceIso) (equivToIso ∘ θ)) ΣPathIsoPathΣ)
sip⁻ : A ≡ B → A ≃[ ι ] B
sip⁻ = invEq SIP-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Foundations.Transport.html`
{- Basic theory about transport:
- transport is invertible
- transport is an equivalence ([pathToEquiv])
-}
module Cubical.Foundations.Transport where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Equiv as Equiv hiding (transpEquiv)
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Univalence
open import Cubical.Foundations.GroupoidLaws
open import Cubical.Foundations.Function using (_∘_)
-- Direct definition of transport filler, note that we have to
-- explicitly tell Agda that the type is constant (like in CHM)
transpFill : ∀ {ℓ} {A : Type ℓ}
(φ : I)
(A : (i : I) → Type ℓ [ φ ↦ (λ _ → A) ])
(u0 : outS (A i0))
→ --------------------------------------
PathP (λ i → outS (A i)) u0 (transp (λ i → outS (A i)) φ u0)
transpFill φ A u0 i = transp (λ j → outS (A (i ∧ j))) (~ i ∨ φ) u0
transport⁻ : ∀ {ℓ} {A B : Type ℓ} → A ≡ B → B → A
transport⁻ p = transport (λ i → p (~ i))
subst⁻ : ∀ {ℓ ℓ'} {A : Type ℓ} {x y : A} (B : A → Type ℓ') (p : x ≡ y) → B y → B x
subst⁻ B p pa = transport⁻ (λ i → B (p i)) pa
subst⁻-filler : ∀ {ℓ ℓ'} {A : Type ℓ} {x y : A} (B : A → Type ℓ') (p : x ≡ y) (b : B y)
→ PathP (λ i → B (p (~ i))) b (subst⁻ B p b)
subst⁻-filler B p = subst-filler B (sym p)
transport-fillerExt : ∀ {ℓ} {A B : Type ℓ} (p : A ≡ B)
→ PathP (λ i → A → p i) (λ x → x) (transport p)
transport-fillerExt p i x = transport-filler p x i
transport⁻-fillerExt : ∀ {ℓ} {A B : Type ℓ} (p : A ≡ B)
→ PathP (λ i → p i → A) (λ x → x) (transport⁻ p)
transport⁻-fillerExt p i x = transp (λ j → p (i ∧ ~ j)) (~ i) x
transport-fillerExt⁻ : ∀ {ℓ} {A B : Type ℓ} (p : A ≡ B)
→ PathP (λ i → p i → B) (transport p) (λ x → x)
transport-fillerExt⁻ p = symP (transport⁻-fillerExt (sym p))
transport⁻-fillerExt⁻ : ∀ {ℓ} {A B : Type ℓ} (p : A ≡ B)
→ PathP (λ i → B → p i) (transport⁻ p) (λ x → x)
transport⁻-fillerExt⁻ p = symP (transport-fillerExt (sym p))
transport⁻-filler : ∀ {ℓ} {A B : Type ℓ} (p : A ≡ B) (x : B)
→ PathP (λ i → p (~ i)) x (transport⁻ p x)
transport⁻-filler p x = transport-filler (λ i → p (~ i)) x
transport⁻Transport : ∀ {ℓ} {A B : Type ℓ} → (p : A ≡ B) → (a : A) →
transport⁻ p (transport p a) ≡ a
transport⁻Transport p a j = transport⁻-fillerExt p (~ j) (transport-fillerExt p (~ j) a)
transportTransport⁻ : ∀ {ℓ} {A B : Type ℓ} → (p : A ≡ B) → (b : B) →
transport p (transport⁻ p b) ≡ b
transportTransport⁻ p b j = transport-fillerExt⁻ p j (transport⁻-fillerExt⁻ p j b)
subst⁻Subst : ∀ {ℓ ℓ'} {A : Type ℓ} {x y : A} (B : A → Type ℓ') (p : x ≡ y)
→ (u : B x) → subst⁻ B p (subst B p u) ≡ u
subst⁻Subst {x = x} {y = y} B p u = transport⁻Transport {A = B x} {B = B y} (cong B p) u
substSubst⁻ : ∀ {ℓ ℓ'} {A : Type ℓ} {x y : A} (B : A → Type ℓ') (p : x ≡ y)
→ (v : B y) → subst B p (subst⁻ B p v) ≡ v
substSubst⁻ {x = x} {y = y} B p v = transportTransport⁻ {A = B x} {B = B y} (cong B p) v
substEquiv : ∀ {ℓ ℓ'} {A : Type ℓ} {a a' : A} (P : A → Type ℓ') (p : a ≡ a') → P a ≃ P a'
substEquiv P p = (subst P p , isEquivTransport (λ i → P (p i)))
subst2Equiv : ∀ {ℓ ℓ' ℓ''} {A : Type ℓ} {B : Type ℓ'} {a a' : A} {b b' : B} (P : A → B → Type ℓ'')
(p : a ≡ a') (q : b ≡ b') → P a b ≃ P a' b'
subst2Equiv P p q = (subst2 P p q , isEquivTransport (λ i → P (p i) (q i)))
liftEquiv : ∀ {ℓ ℓ'} {A B : Type ℓ} (P : Type ℓ → Type ℓ') (e : A ≃ B) → P A ≃ P B
liftEquiv P e = substEquiv P (ua e)
transpEquiv : ∀ {ℓ} {A B : Type ℓ} (p : A ≡ B) → ∀ i → p i ≃ B
transpEquiv p = Equiv.transpEquiv (λ i → p i)
{-# WARNING_ON_USAGE transpEquiv "Deprecated: Use the more general `transpEquiv` from `Cubical.Foundations.Equiv` instead" #-}
uaTransportη : ∀ {ℓ} {A B : Type ℓ} (P : A ≡ B) → ua (pathToEquiv P) ≡ P
uaTransportη = uaη
{-# WARNING_ON_USAGE uaTransportη "Deprecated: Use `uaη` from `Cubical.Foundations.Univalence` instead of `uaTransportη`" #-}
pathToIso : ∀ {ℓ} {A B : Type ℓ} → A ≡ B → Iso A B
Iso.fun (pathToIso x) = transport x
Iso.inv (pathToIso x) = transport⁻ x
Iso.sec (pathToIso x) = transportTransport⁻ x
Iso.ret (pathToIso x) = transport⁻Transport x
substIso : ∀ {ℓ ℓ'} {A : Type ℓ} (B : A → Type ℓ') {x y : A} (p : x ≡ y) → Iso (B x) (B y)
substIso B p = pathToIso (cong B p)
-- Redefining substEquiv in terms of substIso gives an explicit inverse
substEquiv' : ∀ {ℓ ℓ'} {A : Type ℓ} (B : A → Type ℓ') {x y : A} (p : x ≡ y) → B x ≃ B y
substEquiv' B p = isoToEquiv (substIso B p)
isInjectiveTransport : ∀ {ℓ : Level} {A B : Type ℓ} {p q : A ≡ B}
→ transport p ≡ transport q → p ≡ q
isInjectiveTransport {p = p} {q} α i =
hcomp
(λ j → λ
{ (i = i0) → retEq univalence p j
; (i = i1) → retEq univalence q j
})
(invEq univalence ((λ a → α i a) , t i))
where
t : PathP (λ i → isEquiv (λ a → α i a)) (pathToEquiv p .snd) (pathToEquiv q .snd)
t = isProp→PathP (λ i → isPropIsEquiv (λ a → α i a)) _ _
transportUaInv : ∀ {ℓ} {A B : Type ℓ} (e : A ≃ B) → transport (ua (invEquiv e)) ≡ transport (sym (ua e))
transportUaInv e = cong transport (uaInvEquiv e)
-- notice that transport (ua e) would reduce, thus an alternative definition using EquivJ can give
-- refl for the case of idEquiv:
-- transportUaInv e = EquivJ (λ _ e → transport (ua (invEquiv e)) ≡ transport (sym (ua e))) refl e
isSet-subst : ∀ {ℓ ℓ'} {A : Type ℓ} {B : A → Type ℓ'}
→ (isSet-A : isSet A)
→ ∀ {a : A}
→ (p : a ≡ a) → (x : B a) → subst B p x ≡ x
isSet-subst {B = B} isSet-A p x = subst (λ p′ → subst B p′ x ≡ x) (isSet-A _ _ refl p) (substRefl {B = B} x)
-- substituting along a composite path is equivalent to substituting twice
substComposite : ∀ {ℓ ℓ'} {A : Type ℓ} → (B : A → Type ℓ')
→ {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)
substComposite B p q Bx i =
transport (cong B (compPath-filler' p q (~ i))) (transport-fillerExt (cong B p) i Bx)
-- transporting along a composite path is equivalent to transporting twice
transportComposite : ∀ {ℓ} {A B C : Type ℓ} (p : A ≡ B) (q : B ≡ C) (x : A)
→ transport (p ∙ q) x ≡ transport q (transport p x)
transportComposite = substComposite (λ D → D)
-- substitution commutes with morphisms in slices
substCommSlice : ∀ {ℓ ℓ' ℓ''} {A : Type ℓ}
→ (B : A → Type ℓ') (C : A → Type ℓ'')
→ (F : ∀ a → B a → C a)
→ {x y : A} (p : x ≡ y) (u : B x)
→ subst C p (F x u) ≡ F y (subst B p u)
substCommSlice B C F p Bx a =
transport-fillerExt⁻ (cong C p) a (F _ (transport-fillerExt (cong B p) a Bx))
constSubstCommSlice : ∀ {ℓ ℓ' ℓ''} {A : Type ℓ}
→ (B : A → Type ℓ')
→ (C : Type ℓ'')
→ (F : ∀ a → B a → C)
→ {x y : A} (p : x ≡ y) (u : B x)
→ (F x u) ≡ F y (subst B p u)
constSubstCommSlice B C F p Bx = (sym (transportRefl (F _ Bx)) ∙ substCommSlice B (λ _ → C) F p Bx)
-- transporting over (λ i → B (p i) → C (p i)) divides the transport into
-- transports over (λ i → C (p i)) and (λ i → B (p (~ i)))
funTypeTransp : ∀ {ℓ ℓ' ℓ''} {A : Type ℓ} (B : A → Type ℓ') (C : A → Type ℓ'') {x y : A} (p : x ≡ y) (f : B x → C x)
→ PathP (λ i → B (p i) → C (p i)) f (subst C p ∘ f ∘ subst B (sym p))
funTypeTransp B C {x = x} p f i b =
transp (λ j → C (p (j ∧ i))) (~ i) (f (transp (λ j → B (p (i ∧ ~ j))) (~ i) b))
-- transports between loop spaces preserve path composition
overPathFunct : ∀ {ℓ} {A : Type ℓ} {x y : A} (p q : x ≡ x) (P : x ≡ y)
→ transport (λ i → P i ≡ P i) (p ∙ q)
≡ transport (λ i → P i ≡ P i) p ∙ transport (λ i → P i ≡ P i) q
overPathFunct p q =
J (λ y P → transport (λ i → P i ≡ P i) (p ∙ q) ≡ transport (λ i → P i ≡ P i) p ∙ transport (λ i → P i ≡ P i) q)
(transportRefl (p ∙ q) ∙ cong₂ _∙_ (sym (transportRefl p)) (sym (transportRefl q)))
-- substition over families of paths
-- theorem 2.11.3 in The Book
substInPaths : ∀ {ℓ ℓ'} {A : Type ℓ} {B : Type ℓ'} {a a' : A}
→ (f g : A → B) → (p : a ≡ a') (q : f a ≡ g a)
→ subst (λ x → f x ≡ g x) p q ≡ sym (cong f p) ∙ q ∙ cong g p
substInPaths {a = a} f g p q =
J (λ x p' → (subst (λ y → f y ≡ g y) p' q) ≡ (sym (cong f p') ∙ q ∙ cong g p'))
p=refl p
where
p=refl : subst (λ y → f y ≡ g y) refl q
≡ refl ∙ q ∙ refl
p=refl = subst (λ y → f y ≡ g y) refl q
≡⟨ substRefl {B = (λ y → f y ≡ g y)} q ⟩ q
≡⟨ (rUnit q) ∙ lUnit (q ∙ refl) ⟩ refl ∙ q ∙ refl ∎
flipTransport : ∀ {ℓ} {A : I → Type ℓ} {x : A i0} {y : A i1}
→ x ≡ transport⁻ (λ i → A i) y
→ transport (λ i → A i) x ≡ y
flipTransport {A = A} {y = y} p =
cong (transport (λ i → A i)) p ∙ transportTransport⁻ (λ i → A i) y
-- special cases of substInPaths from lemma 2.11.2 in The Book
module _ {ℓ : Level} {A : Type ℓ} {a x1 x2 : A} (p : x1 ≡ x2) where
substInPathsL : (q : a ≡ x1) → subst (λ x → a ≡ x) p q ≡ q ∙ p
substInPathsL q = subst (λ x → a ≡ x) p q
≡⟨ substInPaths (λ _ → a) (λ x → x) p q ⟩
sym (cong (λ _ → a) p) ∙ q ∙ cong (λ x → x) p
≡⟨ assoc (λ _ → a) q p ⟩
(refl ∙ q) ∙ p
≡⟨ cong (_∙ p) (sym (lUnit q)) ⟩ q ∙ p ∎
substInPathsR : (q : x1 ≡ a) → subst (λ x → x ≡ a) p q ≡ sym p ∙ q
substInPathsR q = subst (λ x → x ≡ a) p q
≡⟨ substInPaths (λ x → x) (λ _ → a) p q ⟩
sym (cong (λ x → x) p) ∙ q ∙ cong (λ _ → a) p
≡⟨ assoc (sym p) q refl ⟩
(sym p ∙ q) ∙ refl
≡⟨ sym (rUnit (sym p ∙ q))⟩ sym p ∙ q ∎
transport-filler-ua : ∀ {ℓ} {A B : Type ℓ} (e : A ≃ B) (a : A)
→ SquareP (λ _ i → ua e i)
(transport-filler (ua e) a)
(ua-gluePath e refl)
refl
(transportRefl (fst e a))
transport-filler-ua {A = A} {B = B} (e , _) a j i =
let b = e a
tr = transportRefl b
z = tr (j ∧ ~ i)
in glue (λ { (i = i0) → a ; (i = i1) → tr j })
(hcomp (λ k → λ { (i = i0) → b ; (i = i1) → tr (j ∧ k) ; (j = i1) → tr (~ i ∨ k) })
(hcomp (λ k → λ { (i = i0) → tr (j ∨ k) ; (i = i1) → z ; (j = i1) → z }) z))-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Foundations.Univalence.Dependent.html`
{-
Dependent Version of Univalence
The univalence corresponds to the dependent equivalences/isomorphisms,
c.f. `Cubical.Foundations.Equiv.Dependent`.
-}
module Cubical.Foundations.Univalence.Dependent where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Equiv.HalfAdjoint
open import Cubical.Foundations.Equiv.Dependent
open import Cubical.Foundations.Univalence
private
variable
ℓ ℓ' : Level
-- Dependent Univalence
--
-- Given families `P` and `Q` over base types `A` and `B`
-- respectively, and given
-- * an equivalence of base types `e : A ≃ B`,
-- * and and a pointwise equivalence of the families,
-- construct a dependent path over `ua e` between the families.
module _
{A B : Type ℓ} {P : A → Type ℓ'} {Q : B → Type ℓ'}
(e : A ≃ B) (F : mapOver (e .fst) P Q)
(equiv : isEquivOver {P = P} {Q = Q} F)
where
private
-- Bundle `F` and `equiv` into a pointwise equivalence of `P` and `Q`:
Γ : (a : A) → P a ≃ Q (equivFun e a)
Γ a = F a , equiv a
-- A quick proof provided by @ecavallo.
-- Unfortunately it gives a larger term overall.
_ : PathP (λ i → ua e i → Type ℓ') P Q
_ = ua→ (λ a → ua (Γ a))
uaOver : PathP (λ i → ua e i → Type ℓ') P Q
uaOver i x = Glue Base {φ} equiv-boundary where
-- Like `ua`, `uaOver` is obtained from a line of
-- Glue-types, except that they are glued
-- over a line dependent on `ua e : A ≡ B`.
-- `x` is a point along the path `A ≡ B` obtained
-- from univalence, i.e. glueing over `B`:
--
-- A = = (ua e) = = B
-- | |
-- (e) (idEquiv B)
-- | |
-- v v
-- B =====(B)====== B
_ : Glue B {φ = i ∨ ~ i} (λ { (i = i0) → A , e ; (i = i1) → B , idEquiv B })
_ = x
-- We can therefore `unglue` it to obtain a term in the base line of `ua e`,
-- i.e. term of type `B`:
φ = i ∨ ~ i
b : B
b = unglue φ x
-- This gives us a line `(i : I) ⊢ Base` in the universe of types,
-- along which we can glue the equivalences `Γ x` and `idEquiv (Q x)`:
--
-- P (e x) = = = = = = Q x
-- | |
-- (Γ x) (idEquiv (Q x))
-- | |
-- v v
-- Q x ===(Base)=== Q x
Base : Type ℓ'
Base = Q b
equiv-boundary : Partial φ (Σ[ T ∈ Type ℓ' ] T ≃ Base)
equiv-boundary (i = i0) = P x , Γ x
equiv-boundary (i = i1) = Q x , idEquiv (Q x)
-- Note that above `(i = i0) ⊢ x : A` and `(i = i1) ⊢ x : B`,
-- thus `P x` and `Q x` are well-typed.
_ : Partial i B
_ = λ { (i = i1) → x }
_ : Partial (~ i) A
_ = λ { (i = i0) → x }
-- Dependent `isoToPath`
open isHAEquiv
isoToPathOver :
{A B : Type ℓ} {P : A → Type ℓ'} {Q : B → Type ℓ'}
(f : A → B) (hae : isHAEquiv f)
(isom : IsoOver (isHAEquiv→Iso hae) P Q)
→ PathP (λ i → ua (_ , isHAEquiv→isEquiv hae) i → Type ℓ') P Q
isoToPathOver f hae isom = uaOver _ _ (isoToEquivOver f hae isom)-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Foundations.Univalence.html`
{-
Proof of the standard formulation of the univalence theorem and
various consequences of univalence
- Re-exports Glue types from Cubical.Core.Glue
- The ua constant and its computation rule (up to a path)
- Proof of univalence using that unglue is an equivalence ([EquivContr])
- Equivalence induction ([EquivJ], [elimEquiv])
- Univalence theorem ([univalence])
- The computation rule for ua ([uaβ])
- Isomorphism induction ([elimIso])
-}
module Cubical.Foundations.Univalence where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Function
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.GroupoidLaws
open import Cubical.Data.Sigma.Base
open import Cubical.Core.Glue public
using (Glue ; glue ; unglue)
open import Cubical.Reflection.StrictEquiv
private
variable
ℓ ℓ' : Level
-- The ua constant
ua : ∀ {A B : Type ℓ} → A ≃ B → A ≡ B
ua {A = A} {B = B} e i = Glue B (λ { (i = i0) → (A , e)
; (i = i1) → (B , idEquiv B) })
uaIdEquiv : {A : Type ℓ} → ua (idEquiv A) ≡ refl
uaIdEquiv {A = A} i j = Glue A {φ = i ∨ ~ j ∨ j} (λ _ → A , idEquiv A)
-- Propositional extensionality
hPropExt : {A B : Type ℓ} → isProp A → isProp B → (A → B) → (B → A) → A ≡ B
hPropExt Aprop Bprop f g = ua (propBiimpl→Equiv Aprop Bprop f g)
-- the unglue and glue primitives specialized to the case of ua
ua-unglue : ∀ {A B : Type ℓ} (e : A ≃ B) (i : I) (x : ua e i)
→ B {- [ _ ↦ (λ { (i = i0) → e .fst x ; (i = i1) → x }) ] -}
ua-unglue e i x = unglue (i ∨ ~ i) x
ua-glue : ∀ {A B : Type ℓ} (e : A ≃ B) (i : I) (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 }) ] -}
ua-glue e i x y = glue {φ = i ∨ ~ i} (λ { (i = i0) → x 1=1 ; (i = i1) → outS y }) (outS y)
module _ {A B : Type ℓ} (e : A ≃ B) {x : A} {y : B} where
-- sometimes more useful are versions of these functions with the (i : I) factored in
ua-ungluePath : PathP (λ i → ua e i) x y → e .fst x ≡ y
ua-ungluePath p i = ua-unglue e i (p i)
ua-gluePath : e .fst x ≡ y → PathP (λ i → ua e i) x y
ua-gluePath p i = ua-glue e i (λ { (i = i0) → x }) (inS (p i))
-- ua-ungluePath and ua-gluePath are definitional inverses
ua-ungluePath-Equiv : (PathP (λ i → ua e i) x y) ≃ (e .fst x ≡ y)
unquoteDef ua-ungluePath-Equiv =
defStrictEquiv ua-ungluePath-Equiv ua-ungluePath ua-gluePath
ua-ungluePathExt : {A B : Type ℓ} (e : A ≃ B) → PathP (λ i → ua e i → B) (fst e) (idfun B)
ua-ungluePathExt e i = ua-unglue e i
ua-gluePathExt : {A B : Type ℓ} (e : A ≃ B) → PathP (λ i → A → ua e i) (idfun _) (fst e)
ua-gluePathExt e i x =
ua-glue e i (λ { (i = i0) → x }) (inS (fst e x))
-- ua-unglue and ua-glue are also definitional inverses, in a way
-- strengthening the types of ua-unglue and ua-glue gives a nicer formulation of this, see below
ua-unglue-glue : ∀ {A B : Type ℓ} (e : A ≃ B) (i : I) (x : Partial (~ i) A) (y : B [ _ ↦ _ ])
→ ua-unglue e i (ua-glue e i x y) ≡ outS y
ua-unglue-glue _ _ _ _ = refl
ua-glue-unglue : ∀ {A B : Type ℓ} (e : A ≃ B) (i : I) (x : ua e i)
→ ua-glue e i (λ { (i = i0) → x }) (inS (ua-unglue e i x)) ≡ x
ua-glue-unglue _ _ _ = refl
-- mainly for documentation purposes, ua-unglue and ua-glue wrapped in cubical subtypes
ua-unglueS : ∀ {A B : Type ℓ} (e : A ≃ B) (i : I) (x : A) (y : B)
→ ua e i [ _ ↦ (λ { (i = i0) → x ; (i = i1) → y }) ]
→ B [ _ ↦ (λ { (i = i0) → e .fst x ; (i = i1) → y }) ]
ua-unglueS e i x y s = inS (ua-unglue e i (outS s))
ua-glueS : ∀ {A B : Type ℓ} (e : A ≃ B) (i : I) (x : A) (y : B)
→ B [ _ ↦ (λ { (i = i0) → e .fst x ; (i = i1) → y }) ]
→ ua e i [ _ ↦ (λ { (i = i0) → x ; (i = i1) → y }) ]
ua-glueS e i x y s = inS (ua-glue e i (λ { (i = i0) → x }) (inS (outS s)))
ua-unglueS-glueS : ∀ {A B : Type ℓ} (e : A ≃ B) (i : I) (x : A) (y : B)
(s : B [ _ ↦ (λ { (i = i0) → e .fst x ; (i = i1) → y }) ])
→ outS (ua-unglueS e i x y (ua-glueS e i x y s)) ≡ outS s
ua-unglueS-glueS _ _ _ _ _ = refl
ua-glueS-unglueS : ∀ {A B : Type ℓ} (e : A ≃ B) (i : I) (x : A) (y : B)
(s : ua e i [ _ ↦ (λ { (i = i0) → x ; (i = i1) → y }) ])
→ outS (ua-glueS e i x y (ua-unglueS e i x y s)) ≡ outS s
ua-glueS-unglueS _ _ _ _ _ = refl
-- a version of ua-glue with a single endpoint, identical to `ua-gluePath e {x} refl i`
ua-gluePt : ∀ {A B : Type ℓ} (e : A ≃ B) (i : I) (x : A)
→ ua e i {- [ _ ↦ (λ { (i = i0) → x ; (i = i1) → e .fst x }) ] -}
ua-gluePt e i x = ua-glue e i (λ { (i = i0) → x }) (inS (e .fst x))
-- Proof of univalence using that unglue is an equivalence:
-- unglue is an equivalence
unglueIsEquiv : ∀ (A : Type ℓ) (φ : I)
(f : PartialP φ (λ o → Σ[ T ∈ Type ℓ ] T ≃ A)) →
isEquiv {A = Glue A f} (unglue φ)
equiv-proof (unglueIsEquiv A φ f) = λ (b : A) →
let u : I → Partial φ A
u i = λ{ (φ = i1) → equivCtr (f 1=1 .snd) b .snd (~ i) }
ctr : fiber (unglue φ) b
ctr = ( glue (λ { (φ = i1) → equivCtr (f 1=1 .snd) b .fst }) (hcomp u b)
, λ j → hfill u (inS b) (~ j))
in ( ctr
, λ (v : fiber (unglue φ) b) i →
let u' : I → Partial (φ ∨ ~ i ∨ i) A
u' j = λ { (φ = i1) → equivCtrPath (f 1=1 .snd) b v i .snd (~ j)
; (i = i0) → hfill u (inS b) j
; (i = i1) → v .snd (~ j) }
in ( glue (λ { (φ = i1) → equivCtrPath (f 1=1 .snd) b v i .fst }) (hcomp u' b)
, λ j → hfill u' (inS b) (~ j)))
-- Any partial family of equivalences can be extended to a total one
-- from Glue [ φ ↦ (T,f) ] A to A
unglueEquiv : ∀ (A : Type ℓ) (φ : I)
(f : PartialP φ (λ o → Σ[ T ∈ Type ℓ ] T ≃ A)) →
(Glue A f) ≃ A
unglueEquiv A φ f = ( unglue φ , unglueIsEquiv A φ f )
ua-unglueEquiv : ∀ {A B : Type ℓ} (e : A ≃ B) →
PathP (λ i → ua e i ≃ B)
e
(idEquiv _)
fst (ua-unglueEquiv e i) = ua-unglue e i
snd (ua-unglueEquiv e i) =
isProp→PathP (λ i → isPropIsEquiv (ua-unglue e i))
(snd e) (idIsEquiv _) i
-- The following is a formulation of univalence proposed by Martín Escardó:
-- https://groups.google.com/forum/#!msg/homotopytypetheory/HfCB_b-PNEU/Ibb48LvUMeUJ
-- See also Theorem 5.8.4 of the HoTT Book.
--
-- The reason we have this formulation in the core library and not the
-- standard one is that this one is more direct to prove using that
-- unglue is an equivalence. The standard formulation can be found in
-- Cubical/Basics/Univalence.
--
EquivContr : ∀ (A : Type ℓ) → ∃![ T ∈ Type ℓ ] (T ≃ A)
EquivContr {ℓ = ℓ} A =
( (A , idEquiv A)
, idEquiv≡ )
where
idEquiv≡ : (y : Σ (Type ℓ) (λ T → T ≃ A)) → (A , idEquiv A) ≡ y
idEquiv≡ w = \ { i .fst → Glue A (f i)
; i .snd .fst → unglueEquiv _ _ (f i) .fst
; i .snd .snd .equiv-proof → unglueEquiv _ _ (f i) .snd .equiv-proof
}
where
f : ∀ i → PartialP (~ i ∨ i) (λ x → Σ[ T ∈ Type ℓ ] T ≃ A)
f i = λ { (i = i0) → A , idEquiv A ; (i = i1) → w }
contrSinglEquiv : {A B : Type ℓ} (e : A ≃ B) → (B , idEquiv B) ≡ (A , e)
contrSinglEquiv {A = A} {B = B} e =
isContr→isProp (EquivContr B) (B , idEquiv B) (A , e)
-- Equivalence induction
EquivJ : {A B : Type ℓ} (P : (A : Type ℓ) → (e : A ≃ B) → Type ℓ')
→ (r : P B (idEquiv B)) → (e : A ≃ B) → P A e
EquivJ P r e = subst (λ x → P (x .fst) (x .snd)) (contrSinglEquiv e) r
-- Transport along a path is an equivalence.
-- The proof is a special case of isEquivTransp where the line of types is
-- given by p, and the extend φ -- where the transport is constant -- is i0.
isEquivTransport : {A B : Type ℓ} (p : A ≡ B) → isEquiv (transport p)
isEquivTransport p = isEquivTransp A φ where
A : I → Type _
A i = p i
φ : I
φ = i0
pathToEquiv : {A B : Type ℓ} → A ≡ B → A ≃ B
pathToEquiv p .fst = transport p
pathToEquiv p .snd = isEquivTransport p
pathToEquivRefl : {A : Type ℓ} → pathToEquiv refl ≡ idEquiv A
pathToEquivRefl {A = A} = equivEq (λ i x → transp (λ _ → A) i x)
-- The computation rule for ua. Because of "ghcomp" it is now very
-- simple compared to cubicaltt:
-- https://github.com/mortberg/cubicaltt/blob/master/examples/univalence.ctt#L202
uaβ : {A B : Type ℓ} (e : A ≃ B) (x : A) → transport (ua e) x ≡ equivFun e x
uaβ e x = transportRefl (equivFun e x)
~uaβ : {A B : Type ℓ} (e : A ≃ B) (x : B) → transport (sym (ua e)) x ≡ invEq e x
~uaβ e x = cong (invEq e) (transportRefl x)
uaη : ∀ {A B : Type ℓ} → (P : A ≡ B) → ua (pathToEquiv P) ≡ P
uaη {A = A} {B = B} P i j = Glue B {φ = φ} sides where
-- Adapted from a proof by @dolio, cf. commit e42a6fa1
φ = i ∨ j ∨ ~ j
sides : Partial φ (Σ[ T ∈ Type _ ] T ≃ B)
sides (i = i1) = P j , transpEquiv (λ k → P k) j
sides (j = i0) = A , pathToEquiv P
sides (j = i1) = B , idEquiv B
pathToEquiv-ua : {A B : Type ℓ} (e : A ≃ B) → pathToEquiv (ua e) ≡ e
pathToEquiv-ua e = equivEq (funExt (uaβ e))
ua-pathToEquiv : {A B : Type ℓ} (p : A ≡ B) → ua (pathToEquiv p) ≡ p
ua-pathToEquiv = uaη
-- Univalence
univalenceIso : {A B : Type ℓ} → Iso (A ≡ B) (A ≃ B)
univalenceIso .Iso.fun = pathToEquiv
univalenceIso .Iso.inv = ua
univalenceIso .Iso.sec = pathToEquiv-ua
univalenceIso .Iso.ret = ua-pathToEquiv
isEquivPathToEquiv : {A B : Type ℓ} → isEquiv (pathToEquiv {A = A} {B = B})
isEquivPathToEquiv = isoToIsEquiv univalenceIso
univalence : {A B : Type ℓ} → (A ≡ B) ≃ (A ≃ B)
univalence .fst = pathToEquiv
univalence .snd = isEquivPathToEquiv
-- Assuming that we have an inverse to ua we can easily prove univalence
module Univalence (au : ∀ {ℓ} {A B : Type ℓ} → A ≡ B → A ≃ B)
(aurefl : ∀ {ℓ} {A : Type ℓ} → au refl ≡ idEquiv A) where
ua-au : {A B : Type ℓ} (p : A ≡ B) → ua (au p) ≡ p
ua-au {B = B} = J (λ _ p → ua (au p) ≡ p)
(cong ua aurefl ∙ uaIdEquiv)
au-ua : {A B : Type ℓ} (e : A ≃ B) → au (ua e) ≡ e
au-ua {B = B} = EquivJ (λ _ f → au (ua f) ≡ f)
(subst (λ r → au r ≡ idEquiv _) (sym uaIdEquiv) aurefl)
isoThm : ∀ {ℓ} {A B : Type ℓ} → Iso (A ≡ B) (A ≃ B)
isoThm .Iso.fun = au
isoThm .Iso.inv = ua
isoThm .Iso.sec = au-ua
isoThm .Iso.ret = ua-au
thm : ∀ {ℓ} {A B : Type ℓ} → isEquiv au
thm {A = A} {B = B} = isoToIsEquiv {B = A ≃ B} isoThm
-- The original map from UniMath/Foundations
eqweqmap : {A B : Type ℓ} → A ≡ B → A ≃ B
eqweqmap {A = A} e = J (λ X _ → A ≃ X) (idEquiv A) e
eqweqmapid : {A : Type ℓ} → eqweqmap refl ≡ idEquiv A
eqweqmapid {A = A} = JRefl (λ X _ → A ≃ X) (idEquiv A)
univalenceStatement : {A B : Type ℓ} → isEquiv (eqweqmap {ℓ} {A} {B})
univalenceStatement = Univalence.thm eqweqmap eqweqmapid
univalenceUAH : {A B : Type ℓ} → (A ≡ B) ≃ (A ≃ B)
univalenceUAH = ( _ , univalenceStatement )
univalencePath : {A B : Type ℓ} → (A ≡ B) ≡ Lift (A ≃ B)
univalencePath = ua (compEquiv univalence LiftEquiv)
-- Lemmas for constructing and destructing dependent paths in a function type where the domain is ua.
ua→ : ∀ {ℓ ℓ'} {A₀ A₁ : Type ℓ} {e : A₀ ≃ A₁} {B : (i : I) → Type ℓ'}
{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₁
ua→ {e = e} {f₀ = f₀} {f₁} h i a =
hcomp
(λ j → λ
{ (i = i0) → f₀ a
; (i = i1) → f₁ (lem a j)
})
(h (transp (λ j → ua e (~ j ∧ i)) (~ i) a) i)
where
lem : ∀ a₁ → e .fst (transport (sym (ua e)) a₁) ≡ a₁
lem a₁ = secEq e _ ∙ transportRefl _
ua→⁻ : ∀ {ℓ ℓ'} {A₀ A₁ : Type ℓ} {e : A₀ ≃ A₁} {B : (i : I) → Type ℓ'}
{f₀ : A₀ → B i0} {f₁ : A₁ → B i1}
→ PathP (λ i → ua e i → B i) f₀ f₁
→ ((a : A₀) → PathP B (f₀ a) (f₁ (e .fst a)))
ua→⁻ {e = e} {f₀ = f₀} {f₁} p a i =
hcomp
(λ k → λ
{ (i = i0) → f₀ a
; (i = i1) → f₁ (uaβ e a k)
})
(p i (transp (λ j → ua e (j ∧ i)) (~ i) a))
ua→2 : ∀ {ℓ ℓ' ℓ''} {A₀ A₁ : Type ℓ} {e₁ : A₀ ≃ A₁}
{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→2 h = ua→ (ua→ ∘ h)
-- Useful lemma for unfolding a transported function over ua
-- If we would have regularity this would be refl
transportUAop₁ : ∀ {A B : Type ℓ} → (e : A ≃ B) (f : A → A) (x : B)
→ transport (λ i → ua e i → ua e i) f x ≡ equivFun e (f (invEq e x))
transportUAop₁ e f x i = transportRefl (equivFun e (f (invEq e (transportRefl x i)))) i
-- Binary version
transportUAop₂ : ∀ {ℓ} {A B : Type ℓ} → (e : A ≃ B) (f : A → A → A) (x y : B)
→ transport (λ i → ua e i → ua e i → ua e i) f x y ≡
equivFun e (f (invEq e x) (invEq e y))
transportUAop₂ e f x y i =
transportRefl (equivFun e (f (invEq e (transportRefl x i))
(invEq e (transportRefl y i)))) i
-- Alternative version of EquivJ that only requires a predicate on functions
elimEquivFun : {A B : Type ℓ} (P : (A : Type ℓ) → (A → B) → Type ℓ')
→ (r : P B (idfun B)) → (e : A ≃ B) → P A (e .fst)
elimEquivFun P r e = subst (λ x → P (x .fst) (x .snd .fst)) (contrSinglEquiv e) r
-- Isomorphism induction
elimIso : {B : Type ℓ} → (Q : {A : Type ℓ} → (A → B) → (B → A) → Type ℓ') →
(h : Q (idfun B) (idfun B)) → {A : Type ℓ} →
(f : A → B) → (g : B → A) → section f g → retract f g → Q f g
elimIso {ℓ} {ℓ'} {B} Q h {A} f g sfg rfg = rem1 f g sfg rfg
where
P : (A : Type ℓ) → (f : A → B) → Type (ℓ-max ℓ' ℓ)
P A f = (g : B → A) → section f g → retract f g → Q f g
rem : P B (idfun B)
rem g sfg rfg = subst (Q (idfun B)) (λ i b → (sfg b) (~ i)) h
rem1 : {A : Type ℓ} → (f : A → B) → P A f
rem1 f g sfg rfg = elimEquivFun P rem (f , isoToIsEquiv (iso f g sfg rfg)) g sfg rfg
uaInvEquiv : ∀ {A B : Type ℓ} → (e : A ≃ B) → ua (invEquiv e) ≡ sym (ua e)
uaInvEquiv {B = B} = EquivJ (λ _ e → ua (invEquiv e) ≡ sym (ua e))
(cong ua (invEquivIdEquiv B))
uaCompEquiv : ∀ {A B C : Type ℓ} → (e : A ≃ B) (f : B ≃ C) → ua (compEquiv e f) ≡ ua e ∙ ua f
uaCompEquiv {B = B} {C} = EquivJ (λ _ e → (f : B ≃ C) → ua (compEquiv e f) ≡ ua e ∙ ua f)
(λ f → cong ua (compEquivIdEquiv f)
∙ sym (cong (λ x → x ∙ ua f) uaIdEquiv
∙ sym (lUnit (ua f))))-- SOURCE URL: `https://agda.github.io/cubical/Cubical.HITs.AssocList.Properties.html`
module Cubical.HITs.AssocList.Properties where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Function
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.HLevels
open import Cubical.Foundations.Univalence
open import Cubical.Foundations.SIP
open import Cubical.Relation.Nullary
open import Cubical.Structures.MultiSet
open import Cubical.Data.Nat using (ℕ; zero; suc; _+_; +-assoc; isSetℕ)
open import Cubical.HITs.AssocList.Base as AL
open import Cubical.HITs.FiniteMultiset as FMS
hiding (_++_; unitl-++; unitr-++; assoc-++; cons-++; comm-++)
private
variable
ℓ : Level
A : Type ℓ
multiPer : (a b : A) (m n : ℕ) (xs : AssocList A)
→ ⟨ a , m ⟩∷ ⟨ b , n ⟩∷ xs ≡ ⟨ b , n ⟩∷ ⟨ a , m ⟩∷ xs
multiPer a b zero n xs = del a (⟨ b , n ⟩∷ xs) ∙ cong (λ ys → ⟨ b , n ⟩∷ ys) (sym (del a xs))
multiPer a b (suc m) zero xs = cong (λ ys → ⟨ a , suc m ⟩∷ ys) (del b xs) ∙ sym (del b (⟨ a , suc m ⟩∷ xs))
multiPer a b (suc m) (suc n) xs =
⟨ a , suc m ⟩∷ ⟨ b , suc n ⟩∷ xs ≡⟨ sym (agg a 1 m (⟨ b , suc n ⟩∷ xs)) ⟩
⟨ a , 1 ⟩∷ ⟨ a , m ⟩∷ ⟨ b , suc n ⟩∷ xs ≡⟨ cong (λ ys → ⟨ a , 1 ⟩∷ ys) (multiPer a b m (suc n) xs) ⟩
⟨ a , 1 ⟩∷ ⟨ b , suc n ⟩∷ ⟨ a , m ⟩∷ xs ≡⟨ cong (λ ys → ⟨ a , 1 ⟩∷ ys) (sym (agg b 1 n (⟨ a , m ⟩∷ xs))) ⟩
⟨ a , 1 ⟩∷ ⟨ b , 1 ⟩∷ ⟨ b , n ⟩∷ ⟨ a , m ⟩∷ xs ≡⟨ per a b (⟨ b , n ⟩∷ ⟨ a , m ⟩∷ xs) ⟩
⟨ b , 1 ⟩∷ ⟨ a , 1 ⟩∷ ⟨ b , n ⟩∷ ⟨ a , m ⟩∷ xs ≡⟨ cong (λ ys → ⟨ b , 1 ⟩∷ ⟨ a , 1 ⟩∷ ys) (multiPer b a n m xs) ⟩
⟨ b , 1 ⟩∷ ⟨ a , 1 ⟩∷ ⟨ a , m ⟩∷ ⟨ b , n ⟩∷ xs ≡⟨ cong (λ ys → ⟨ b , 1 ⟩∷ ys) (agg a 1 m (⟨ b , n ⟩∷ xs)) ⟩
⟨ b , 1 ⟩∷ ⟨ a , suc m ⟩∷ ⟨ b , n ⟩∷ xs ≡⟨ cong (λ ys → ⟨ b , 1 ⟩∷ ys) (multiPer a b (suc m) n xs) ⟩
⟨ b , 1 ⟩∷ ⟨ b , n ⟩∷ ⟨ a , suc m ⟩∷ xs ≡⟨ agg b 1 n (⟨ a , suc m ⟩∷ xs) ⟩
⟨ b , suc n ⟩∷ ⟨ a , suc m ⟩∷ xs ∎
-- Show that association lists and finite multisets are equivalent
multi-∷ : A → ℕ → FMSet A → FMSet A
multi-∷ x zero xs = xs
multi-∷ x (suc n) xs = x ∷ multi-∷ x n xs
multi-∷-agg : (x : A) (m n : ℕ) (b : FMSet A) → multi-∷ x m (multi-∷ x n b) ≡ multi-∷ x (m + n) b
multi-∷-agg x zero n b = refl
multi-∷-agg x (suc m) n b i = x ∷ (multi-∷-agg x m n b i)
infixr 30 _++_
_++_ : (xs ys : AssocList A) → AssocList A
⟨⟩ ++ ys = ys
(⟨ a , n ⟩∷ xs) ++ ys = ⟨ a , n ⟩∷ (xs ++ ys)
per a b xs i ++ ys = per a b (xs ++ ys) i
agg a m n xs i ++ ys = agg a m n (xs ++ ys) i
del a xs i ++ ys = del a (xs ++ ys) i
trunc xs ys p q i j ++ zs =
trunc (xs ++ zs) (ys ++ zs) (cong (_++ _) p) (cong (_++ _) q) i j
unitl-++ : (xs : AssocList A) → ⟨⟩ ++ xs ≡ xs
unitl-++ xs = refl
unitr-++ : (xs : AssocList A) → xs ++ ⟨⟩ ≡ xs
unitr-++ = AL.ElimProp.f (trunc _ _) refl λ _ _ → cong (⟨ _ , _ ⟩∷_)
assoc-++ : (xs ys zs : AssocList A) → xs ++ (ys ++ zs) ≡ (xs ++ ys) ++ zs
assoc-++ = AL.ElimProp.f (isPropΠ2 (λ _ _ → trunc _ _))
(λ ys zs → refl)
λ x n p ys zs → cong (⟨ _ , _ ⟩∷_) (p ys zs)
cons-++ : ∀ x n (xs : AssocList A) → ⟨ x , n ⟩∷ xs ≡ xs ++ (⟨ x , n ⟩∷ ⟨⟩)
cons-++ x n = AL.ElimProp.f (trunc _ _) refl
λ y m p → multiPer _ _ _ _ _ ∙ cong (⟨ _ , _ ⟩∷_) p
comm-++ : (xs ys : AssocList A) → xs ++ ys ≡ ys ++ xs
comm-++ = AL.ElimProp.f (isPropΠ (λ _ → trunc _ _))
(sym ∘ unitr-++)
λ x n {xs} p ys → cong (⟨ _ , _ ⟩∷_) (p ys)
∙ cong (_++ _) (cons-++ x n ys)
∙ sym (assoc-++ ys _ xs)
AL→FMS : AssocList A → FMSet A
AL→FMS = AL.Rec.f FMS.trunc [] multi-∷ comm multi-∷-agg λ _ _ → refl
FMS→AL : FMSet A → AssocList A
FMS→AL = FMS.Rec.f AL.trunc ⟨⟩ (λ x xs → ⟨ x , 1 ⟩∷ xs) per
AL→FMS∘FMS→AL≡id : section {A = AssocList A} AL→FMS FMS→AL
AL→FMS∘FMS→AL≡id = FMS.ElimProp.f (FMS.trunc _ _) refl (λ x p → cong (λ ys → x ∷ ys) p)
-- need a little lemma for other direction
multi-∷-id : (x : A) (n : ℕ) (u : FMSet A)
→ FMS→AL (multi-∷ x n u) ≡ ⟨ x , n ⟩∷ FMS→AL u
multi-∷-id x zero u = sym (del x (FMS→AL u))
multi-∷-id x (suc n) u = FMS→AL (multi-∷ x (suc n) u) ≡⟨ cong (λ ys → ⟨ x , 1 ⟩∷ ys) (multi-∷-id x n u) ⟩
⟨ x , 1 ⟩∷ ⟨ x , n ⟩∷ (FMS→AL u) ≡⟨ agg x 1 n (FMS→AL u) ⟩
⟨ x , (suc n) ⟩∷ (FMS→AL u) ∎
FMS→AL∘AL→FMS≡id : retract {A = AssocList A} AL→FMS FMS→AL
FMS→AL∘AL→FMS≡id = AL.ElimProp.f (AL.trunc _ _) refl (λ x n {xs} p → (multi-∷-id x n (AL→FMS xs)) ∙ cong (λ ys → ⟨ x , n ⟩∷ ys) p)
AssocList≃FMSet : AssocList A ≃ FMSet A
AssocList≃FMSet = isoToEquiv (iso AL→FMS FMS→AL AL→FMS∘FMS→AL≡id FMS→AL∘AL→FMS≡id)
FMSet≃AssocList : FMSet A ≃ AssocList A
FMSet≃AssocList = isoToEquiv (iso FMS→AL AL→FMS FMS→AL∘AL→FMS≡id AL→FMS∘FMS→AL≡id)
AssocList≡FMSet : AssocList A ≡ FMSet A
AssocList≡FMSet = ua AssocList≃FMSet
-- We want to define a multiset structure on AssocList A, we use the recursor to define the count-function
module _(discA : Discrete A) where
setA = Discrete→isSet discA
ALcount-⟨,⟩∷* : A → A → ℕ → ℕ → ℕ
ALcount-⟨,⟩∷* a x n xs with discA a x
... | yes a≡x = n + xs
... | no a≢x = xs
ALcount-per* : (a x y : A) (xs : ℕ)
→ ALcount-⟨,⟩∷* a x 1 (ALcount-⟨,⟩∷* a y 1 xs)
≡ ALcount-⟨,⟩∷* a y 1 (ALcount-⟨,⟩∷* a x 1 xs)
ALcount-per* a x y xs with discA a x | discA a y
ALcount-per* a x y xs | yes a≡x | yes a≡y = refl
ALcount-per* a x y xs | yes a≡x | no a≢y = refl
ALcount-per* a x y xs | no a≢x | yes a≡y = refl
ALcount-per* a x y xs | no a≢x | no a≢y = refl
ALcount-agg* : (a x : A) (m n xs : ℕ)
→ ALcount-⟨,⟩∷* a x m (ALcount-⟨,⟩∷* a x n xs)
≡ ALcount-⟨,⟩∷* a x (m + n) xs
ALcount-agg* a x m n xs with discA a x
... | yes _ = +-assoc m n xs
... | no _ = refl
ALcount-del* : (a x : A) (xs : ℕ) → ALcount-⟨,⟩∷* a x 0 xs ≡ xs
ALcount-del* a x xs with discA a x
... | yes _ = refl
... | no _ = refl
ALcount : A → AssocList A → ℕ
ALcount a = AL.Rec.f isSetℕ 0 (ALcount-⟨,⟩∷* a) (ALcount-per* a) (ALcount-agg* a) (ALcount-del* a)
AL-with-str : MultiSet A setA
AL-with-str = (AssocList A , ⟨⟩ , ⟨_, 1 ⟩∷_ , ALcount)
-- We want to show that Al-with-str ≅ FMS-with-str as multiset-structures
FMS→AL-EquivStr : MultiSetEquivStr A setA (FMS-with-str discA) (AL-with-str) FMSet≃AssocList
FMS→AL-EquivStr = refl , (λ a xs → refl) , φ
where
φ : ∀ a xs → FMScount discA a xs ≡ ALcount a (FMS→AL xs)
φ a = FMS.ElimProp.f (isSetℕ _ _) refl ψ
where
ψ : (x : A) {xs : FMSet A}
→ FMScount discA a xs ≡ ALcount a (FMS→AL xs)
→ FMScount discA a (x ∷ xs) ≡ ALcount a (FMS→AL (x ∷ xs))
ψ x {xs} p = subst B α θ
where
B = λ ys → FMScount discA a (x ∷ xs) ≡ ALcount a ys
α : ⟨ x , 1 ⟩∷ FMS→AL xs ≡ FMS→AL (x ∷ xs)
α = sym (multi-∷-id x 1 xs)
θ : FMScount discA a (x ∷ xs) ≡ ALcount a (⟨ x , 1 ⟩∷ (FMS→AL xs))
θ with discA a x
... | yes _ = cong suc p
... | no ¬p = p
FMS-with-str≡AL-with-str : FMS-with-str discA ≡ AL-with-str
FMS-with-str≡AL-with-str = sip (multiSetUnivalentStr A setA)
(FMS-with-str discA) AL-with-str
(FMSet≃AssocList , FMS→AL-EquivStr)-- SOURCE URL: `https://agda.github.io/cubical/Cubical.HITs.James.Inductive.Reduced.html`
{-
This file contains:
- Some alternative inductive definitions of James, and they give the same results.
The most relevant one is called `𝕁Red` because it is much simpler.
It has fewer constructors, among which the 2-dimensional constructor `coh`
has a form essentially more clearer, and it avoids indexes.
-}
module Cubical.HITs.James.Inductive.Reduced where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Pointed
open import Cubical.Foundations.Univalence
open import Cubical.Data.Nat
open import Cubical.HITs.SequentialColimit
open import Cubical.HITs.James.Inductive.Base
renaming (𝕁ames to 𝕁amesConstruction ; 𝕁ames∞ to 𝕁ames∞Construction)
private
variable
ℓ : Level
module _
((X , x₀) : Pointed ℓ) where
infixr 5 _∷_
-- Inductive James with fewer constructors
data 𝕁Red : Type ℓ where
[] : 𝕁Red
_∷_ : X → 𝕁Red → 𝕁Red
unit : (x : X)(xs : 𝕁Red) → x₀ ∷ x ∷ xs ≡ x ∷ x₀ ∷ xs
coh : (xs : 𝕁Red) → refl ≡ unit x₀ xs
data 𝕁Red∞ : Type ℓ where
incl : 𝕁Red → 𝕁Red∞
push : (xs : 𝕁Red) → incl xs ≡ incl (x₀ ∷ xs)
-- Auxiliary constructions
-- The following square of types is defined as HIT over I × I.
-- Notice that the constructor `incl∷` can be seen parametrized by i, `coh` by both i j,
-- and other constructors are constant.
data 𝕁Square (i j : I) : Type ℓ where
[] : 𝕁Square i j
_∷_ : X → 𝕁Square i j → 𝕁Square i j
incl : 𝕁Square i j → 𝕁Square i j
unit : (xs : 𝕁Square i j) → incl xs ≡ x₀ ∷ xs
incl∷ : (x : X)(xs : 𝕁Square i j) → unit (x ∷ xs) i ≡ x ∷ unit xs i
coh : (xs : 𝕁Square i j) →
PathP (λ k → unit (unit xs (i ∨ k)) i ≡ unit (unit xs i) (i ∨ j ∨ k))
(λ k → unit (unit xs i) (i ∨ j ∧ k)) (incl∷ x₀ xs)
-- What we need actually is its diagonal.
𝕁Path : I → Type ℓ
𝕁Path i = 𝕁Square i (~ i)
-- If you expand the very definition at end points,
-- you will find that `𝕁Red` is almost a deformation retraction of `𝕁1`,
-- and `𝕁0` is almost the same as the original inductive definition of James.
-- That explains why the isomorphisms given bellow are mainly of c-c, c-v and refls.
𝕁0 = 𝕁Path i0
𝕁1 = 𝕁Path i1
data 𝕁Path∞ (i : I) : Type ℓ where
incl : 𝕁Path i → 𝕁Path∞ i
push : (xs : 𝕁Path i) → incl xs ≡ incl (unit xs i)
𝕁0∞ = 𝕁Path∞ i0
𝕁1∞ = 𝕁Path∞ i1
-- The equivalence 𝕁1 ≃ 𝕁Red
-- This part reduces the constructors.
𝕁1→𝕁Red : 𝕁1 → 𝕁Red
𝕁1→𝕁Red [] = []
𝕁1→𝕁Red (x ∷ xs) = x ∷ 𝕁1→𝕁Red xs
𝕁1→𝕁Red (incl xs) = x₀ ∷ 𝕁1→𝕁Red xs
𝕁1→𝕁Red (incl∷ x xs i) = unit x (𝕁1→𝕁Red xs) i
𝕁1→𝕁Red (unit xs i) = x₀ ∷ 𝕁1→𝕁Red xs
𝕁1→𝕁Red (coh xs i j) = coh (𝕁1→𝕁Red xs) i j
𝕁Red→𝕁1 : 𝕁Red → 𝕁1
𝕁Red→𝕁1 [] = []
𝕁Red→𝕁1 (x ∷ xs) = x ∷ 𝕁Red→𝕁1 xs
𝕁Red→𝕁1 (unit x xs i) = incl∷ x (𝕁Red→𝕁1 xs) i
𝕁Red→𝕁1 (coh xs i j) = coh (𝕁Red→𝕁1 xs) i j
𝕁Red→𝕁1→𝕁Red : (xs : 𝕁Red) → 𝕁1→𝕁Red (𝕁Red→𝕁1 xs) ≡ xs
𝕁Red→𝕁1→𝕁Red [] = refl
𝕁Red→𝕁1→𝕁Red (x ∷ xs) t = x ∷ 𝕁Red→𝕁1→𝕁Red xs t
𝕁Red→𝕁1→𝕁Red (unit x xs i) t = unit x (𝕁Red→𝕁1→𝕁Red xs t) i
𝕁Red→𝕁1→𝕁Red (coh xs i j) t = coh (𝕁Red→𝕁1→𝕁Red xs t) i j
𝕁1→𝕁Red→𝕁1 : (xs : 𝕁1) → 𝕁Red→𝕁1 (𝕁1→𝕁Red xs) ≡ xs
𝕁1→𝕁Red→𝕁1 [] = refl
𝕁1→𝕁Red→𝕁1 (x ∷ xs) t = x ∷ 𝕁1→𝕁Red→𝕁1 xs t
𝕁1→𝕁Red→𝕁1 (incl xs) = (λ t → x₀ ∷ 𝕁1→𝕁Red→𝕁1 xs t) ∙ sym (unit xs)
𝕁1→𝕁Red→𝕁1 (incl∷ x xs i) t = incl∷ x (𝕁1→𝕁Red→𝕁1 xs t) i
𝕁1→𝕁Red→𝕁1 (unit xs i) j =
hcomp (λ k → λ
{ (i = i0) → compPath-filler (λ t → x₀ ∷ 𝕁1→𝕁Red→𝕁1 xs t) (sym (unit xs)) k j
; (i = i1) → x₀ ∷ 𝕁1→𝕁Red→𝕁1 xs j
; (j = i0) → x₀ ∷ 𝕁Red→𝕁1 (𝕁1→𝕁Red xs)
; (j = i1) → unit xs (i ∨ ~ k)})
(x₀ ∷ 𝕁1→𝕁Red→𝕁1 xs j)
𝕁1→𝕁Red→𝕁1 (coh xs i j) t = coh (𝕁1→𝕁Red→𝕁1 xs t) i j
𝕁Red∞→𝕁1∞ : 𝕁Red∞ → 𝕁1∞
𝕁Red∞→𝕁1∞ (incl xs) = incl (𝕁Red→𝕁1 xs)
𝕁Red∞→𝕁1∞ (push xs i) = push (𝕁Red→𝕁1 xs) i
𝕁1∞→𝕁Red∞ : 𝕁1∞ → 𝕁Red∞
𝕁1∞→𝕁Red∞ (incl xs) = incl (𝕁1→𝕁Red xs)
𝕁1∞→𝕁Red∞ (push xs i) = push (𝕁1→𝕁Red xs) i
𝕁Red∞→𝕁1∞→𝕁Red∞ : (xs : 𝕁Red∞) → 𝕁1∞→𝕁Red∞ (𝕁Red∞→𝕁1∞ xs) ≡ xs
𝕁Red∞→𝕁1∞→𝕁Red∞ (incl xs) t = incl (𝕁Red→𝕁1→𝕁Red xs t)
𝕁Red∞→𝕁1∞→𝕁Red∞ (push xs i) t = push (𝕁Red→𝕁1→𝕁Red xs t) i
𝕁1∞→𝕁Red∞→𝕁1∞ : (xs : 𝕁1∞) → 𝕁Red∞→𝕁1∞ (𝕁1∞→𝕁Red∞ xs) ≡ xs
𝕁1∞→𝕁Red∞→𝕁1∞ (incl xs) t = incl (𝕁1→𝕁Red→𝕁1 xs t)
𝕁1∞→𝕁Red∞→𝕁1∞ (push xs i) t = push (𝕁1→𝕁Red→𝕁1 xs t) i
𝕁1∞≃𝕁Red∞ : 𝕁1∞ ≃ 𝕁Red∞
𝕁1∞≃𝕁Red∞ = isoToEquiv (iso 𝕁1∞→𝕁Red∞ 𝕁Red∞→𝕁1∞ 𝕁Red∞→𝕁1∞→𝕁Red∞ 𝕁1∞→𝕁Red∞→𝕁1∞)
-- The equivalence 𝕁ames ≃ 𝕁0
-- This part removes the indexes.
private
𝕁ames = 𝕁amesConstruction (X , x₀)
𝕁ames∞ = 𝕁ames∞Construction (X , x₀)
index : 𝕁0 → ℕ
index [] = 0
index (x ∷ xs) = 1 + index xs
index (incl xs) = 1 + index xs
index (incl∷ x xs i) = 2 + index xs
index (unit xs i) = 1 + index xs
index (coh xs i j) = 2 + index xs
𝕁ames→𝕁0 : {n : ℕ} → 𝕁ames n → 𝕁0
𝕁ames→𝕁0 [] = []
𝕁ames→𝕁0 (x ∷ xs) = x ∷ 𝕁ames→𝕁0 xs
𝕁ames→𝕁0 (incl xs) = incl (𝕁ames→𝕁0 xs)
𝕁ames→𝕁0 (incl∷ x xs i) = incl∷ x (𝕁ames→𝕁0 xs) i
𝕁ames→𝕁0 (unit xs i) = unit (𝕁ames→𝕁0 xs) i
𝕁ames→𝕁0 (coh xs i j) = coh (𝕁ames→𝕁0 xs) i j
𝕁0→𝕁ames : (xs : 𝕁0) → 𝕁ames (index xs)
𝕁0→𝕁ames [] = []
𝕁0→𝕁ames (x ∷ xs) = x ∷ 𝕁0→𝕁ames xs
𝕁0→𝕁ames (incl xs) = incl (𝕁0→𝕁ames xs)
𝕁0→𝕁ames (incl∷ x xs i) = incl∷ x (𝕁0→𝕁ames xs) i
𝕁0→𝕁ames (unit xs i) = unit (𝕁0→𝕁ames xs) i
𝕁0→𝕁ames (coh xs i j) = coh (𝕁0→𝕁ames xs) i j
𝕁0→𝕁ames→𝕁0 : (xs : 𝕁0) → 𝕁ames→𝕁0 (𝕁0→𝕁ames xs) ≡ xs
𝕁0→𝕁ames→𝕁0 [] = refl
𝕁0→𝕁ames→𝕁0 (x ∷ xs) t = x ∷ 𝕁0→𝕁ames→𝕁0 xs t
𝕁0→𝕁ames→𝕁0 (incl xs) t = incl (𝕁0→𝕁ames→𝕁0 xs t)
𝕁0→𝕁ames→𝕁0 (incl∷ x xs i) t = incl∷ x (𝕁0→𝕁ames→𝕁0 xs t) i
𝕁0→𝕁ames→𝕁0 (unit xs i) t = unit (𝕁0→𝕁ames→𝕁0 xs t) i
𝕁0→𝕁ames→𝕁0 (coh xs i j) t = coh (𝕁0→𝕁ames→𝕁0 xs t) i j
index-path : {n : ℕ}(xs : 𝕁ames n) → index (𝕁ames→𝕁0 xs) ≡ n
index-path [] = refl
index-path (x ∷ xs) t = 1 + index-path xs t
index-path (incl xs) t = 1 + index-path xs t
index-path (incl∷ x xs i) t = 2 + index-path xs t
index-path (unit xs i) t = 1 + index-path xs t
index-path (coh xs i j) t = 2 + index-path xs t
𝕁ames→𝕁0→𝕁ames : {n : ℕ}(xs : 𝕁ames n)
→ PathP (λ i → 𝕁ames (index-path xs i)) (𝕁0→𝕁ames (𝕁ames→𝕁0 xs)) xs
𝕁ames→𝕁0→𝕁ames [] = refl
𝕁ames→𝕁0→𝕁ames (x ∷ xs) t = x ∷ 𝕁ames→𝕁0→𝕁ames xs t
𝕁ames→𝕁0→𝕁ames (incl xs) t = incl (𝕁ames→𝕁0→𝕁ames xs t)
𝕁ames→𝕁0→𝕁ames (incl∷ x xs i) t = incl∷ x (𝕁ames→𝕁0→𝕁ames xs t) i
𝕁ames→𝕁0→𝕁ames (unit xs i) t = unit (𝕁ames→𝕁0→𝕁ames xs t) i
𝕁ames→𝕁0→𝕁ames (coh xs i j) t = coh (𝕁ames→𝕁0→𝕁ames xs t) i j
𝕁ames∞→𝕁0∞ : 𝕁ames∞ → 𝕁0∞
𝕁ames∞→𝕁0∞ (incl xs) = incl (𝕁ames→𝕁0 xs)
𝕁ames∞→𝕁0∞ (push xs i) = push (𝕁ames→𝕁0 xs) i
𝕁0∞→𝕁ames∞ : 𝕁0∞ → 𝕁ames∞
𝕁0∞→𝕁ames∞ (incl xs) = incl (𝕁0→𝕁ames xs)
𝕁0∞→𝕁ames∞ (push xs i) = push (𝕁0→𝕁ames xs) i
𝕁ames∞→𝕁0∞→𝕁ames∞ : (xs : 𝕁ames∞) → 𝕁0∞→𝕁ames∞ (𝕁ames∞→𝕁0∞ xs) ≡ xs
𝕁ames∞→𝕁0∞→𝕁ames∞ (incl xs) t = incl (𝕁ames→𝕁0→𝕁ames xs t)
𝕁ames∞→𝕁0∞→𝕁ames∞ (push xs i) t = push (𝕁ames→𝕁0→𝕁ames xs t) i
𝕁0∞→𝕁ames∞→𝕁0∞ : (xs : 𝕁0∞) → 𝕁ames∞→𝕁0∞ (𝕁0∞→𝕁ames∞ xs) ≡ xs
𝕁0∞→𝕁ames∞→𝕁0∞ (incl xs) t = incl (𝕁0→𝕁ames→𝕁0 xs t)
𝕁0∞→𝕁ames∞→𝕁0∞ (push xs i) t = push (𝕁0→𝕁ames→𝕁0 xs t) i
𝕁ames∞≃𝕁0∞ : 𝕁ames∞ ≃ 𝕁0∞
𝕁ames∞≃𝕁0∞ = isoToEquiv (iso 𝕁ames∞→𝕁0∞ 𝕁0∞→𝕁ames∞ 𝕁0∞→𝕁ames∞→𝕁0∞ 𝕁ames∞→𝕁0∞→𝕁ames∞)
-- The main equivalence:
𝕁ames∞≃𝕁Red∞ : 𝕁ames∞ ≃ 𝕁Red∞
𝕁ames∞≃𝕁Red∞ = compEquiv 𝕁ames∞≃𝕁0∞ (compEquiv (pathToEquiv (λ i → 𝕁Path∞ i)) 𝕁1∞≃𝕁Red∞)
-- Test of canonicity
private
-- It's good for [].
eq1 : 𝕁ames∞≃𝕁Red∞ .fst (incl []) ≡ incl []
eq1 = refl
-- Without regularity, "obvious" equality doesn't hold definitionally.
eq2 : (x : X) → 𝕁ames∞≃𝕁Red∞ .fst (incl (x ∷ [])) ≡ incl (x ∷ [])
eq2 _ = transportRefl _-- SOURCE URL: `https://agda.github.io/cubical/Cubical.HITs.James.Properties.html`
{-
Basic properties of James construction
This file contains:
- The type James X has h-monoid structure, namely being a monoid in "homotopy category".
- The equivalence "James X₊ ≃ List X" for type X,
where X₊ denotes the type formed by freely adjoining a base point to X.
-}
module Cubical.HITs.James.Properties where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Pointed
open import Cubical.Data.Maybe
open import Cubical.Data.List hiding (_++_)
open import Cubical.HITs.James.Base
private
variable
ℓ : Level
-- The h-monoid structure on James X
module _
(X∙@(X , x₀) : Pointed ℓ) where
++lUnit : (xs : James X∙) → xs ≡ [] ++ xs
++lUnit _ = refl
++rUnit : (xs : James X∙) → xs ≡ xs ++ []
++rUnit [] = refl
++rUnit (x ∷ xs) t = x ∷ ++rUnit xs t
++rUnit (unit xs i) t = unit (++rUnit xs t) i
++Assoc : (xs ys zs : James X∙) → (xs ++ ys) ++ zs ≡ xs ++ (ys ++ zs)
++Assoc [] _ _ = refl
++Assoc (x ∷ xs) ys zs t = x ∷ ++Assoc xs ys zs t
++Assoc (unit xs i) ys zs t = unit (++Assoc xs ys zs t) i
-- Freely adjoining a point
module _
(X : Type ℓ) where
private
X₊ = Maybe∙ X
J₊→List : James X₊ → List X
J₊→List [] = []
J₊→List (just x ∷ xs) = x ∷ J₊→List xs
J₊→List (nothing ∷ xs) = J₊→List xs
J₊→List (unit xs i) = J₊→List xs
List→J₊ : List X → James X₊
List→J₊ [] = []
List→J₊ (x ∷ xs) = just x ∷ List→J₊ xs
List→J₊→List : (xs : List X) → J₊→List (List→J₊ xs) ≡ xs
List→J₊→List [] = refl
List→J₊→List (x ∷ xs) i = x ∷ List→J₊→List xs i
J₊→List→J₊ : (xs : James X₊) → List→J₊ (J₊→List xs) ≡ xs
J₊→List→J₊ [] = refl
J₊→List→J₊ (just x ∷ xs) i = just x ∷ J₊→List→J₊ xs i
J₊→List→J₊ (nothing ∷ xs) = J₊→List→J₊ xs ∙ unit xs
J₊→List→J₊ (unit xs i) j =
hcomp (λ k → λ
{ (i = i0) → J₊→List→J₊ xs j
; (i = i1) → compPath-filler (J₊→List→J₊ xs) (unit xs) k j
; (j = i0) → List→J₊ (J₊→List xs)
; (j = i1) → unit xs (i ∧ k) })
(J₊→List→J₊ xs j)
J₊≃List : James X₊ ≃ List X
J₊≃List = isoToEquiv (iso J₊→List List→J₊ List→J₊→List J₊→List→J₊)-- SOURCE URL: `https://agda.github.io/cubical/Cubical.HITs.PropositionalTruncation.Properties.html`
{-
This file contains:
- Eliminator for propositional truncation
-}
module Cubical.HITs.PropositionalTruncation.Properties where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Function
open import Cubical.Foundations.HLevels
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Univalence
open import Cubical.Data.Sigma
open import Cubical.Data.Sum hiding (rec ; elim ; map)
open import Cubical.Data.Nat using (ℕ ; zero ; suc)
open import Cubical.Data.FinData using (Fin ; zero ; suc)
open import Cubical.HITs.PropositionalTruncation.Base
private
variable
ℓ ℓ' : Level
A B C : Type ℓ
A′ : Type ℓ'
∥∥-isPropDep : (P : A → Type ℓ) → isOfHLevelDep 1 (λ x → ∥ P x ∥₁)
∥∥-isPropDep P = isOfHLevel→isOfHLevelDep 1 (λ _ → squash₁)
rec : {P : Type ℓ} → isProp P → (A → P) → ∥ A ∥₁ → P
rec Pprop f ∣ x ∣₁ = f x
rec Pprop f (squash₁ x y i) = Pprop (rec Pprop f x) (rec Pprop f y) i
rec2 : {P : Type ℓ} → isProp P → (A → B → P) → ∥ A ∥₁ → ∥ B ∥₁ → P
rec2 Pprop f ∣ x ∣₁ ∣ y ∣₁ = f x y
rec2 Pprop f ∣ x ∣₁ (squash₁ y z i) = Pprop (rec2 Pprop f ∣ x ∣₁ y) (rec2 Pprop f ∣ x ∣₁ z) i
rec2 Pprop f (squash₁ x y i) z = Pprop (rec2 Pprop f x z) (rec2 Pprop f y z) i
rec3 : {P : Type ℓ} → isProp P → (A → B → C → P) → ∥ A ∥₁ → ∥ B ∥₁ → ∥ C ∥₁ → P
rec3 Pprop f ∣ x ∣₁ ∣ y ∣₁ ∣ z ∣₁ = f x y z
rec3 Pprop f ∣ x ∣₁ ∣ y ∣₁ (squash₁ z w i) = Pprop (rec3 Pprop f ∣ x ∣₁ ∣ y ∣₁ z) (rec3 Pprop f ∣ x ∣₁ ∣ y ∣₁ w) i
rec3 Pprop f ∣ x ∣₁ (squash₁ y z i) w = Pprop (rec3 Pprop f ∣ x ∣₁ y w) (rec3 Pprop f ∣ x ∣₁ z w) i
rec3 Pprop f (squash₁ x y i) z w = Pprop (rec3 Pprop f x z w) (rec3 Pprop f y z w) i
∃-rec : {B : A → Type ℓ'} {P : Type ℓ} → isProp P → (∀ x → B x → P) → ∃[ x ∈ A ] B x → P
∃-rec Pprop f = rec Pprop (uncurry f)
-- Old version
-- rec2 : ∀ {P : Type ℓ} → isProp P → (A → A → P) → ∥ A ∥ → ∥ A ∥ → P
-- rec2 Pprop f = rec (isProp→ Pprop) (λ a → rec Pprop (f a))
-- n-ary recursor, stated using a dependent FinVec
recFin : {m : ℕ} {P : Fin m → Type ℓ}
{B : Type ℓ'} (isPropB : isProp B)
→ ((∀ i → P i) → B)
---------------------
→ ((∀ i → ∥ P i ∥₁) → B)
recFin {m = zero} _ untruncHyp _ = untruncHyp (λ ())
recFin {m = suc m} {P = P} {B = B} isPropB untruncHyp truncFam =
curriedishTrunc (truncFam zero) (truncFam ∘ suc)
where
curriedish : P zero → (∀ i → ∥ P (suc i) ∥₁) → B
curriedish p₀ = recFin isPropB
(λ famSuc → untruncHyp (λ { zero → p₀ ; (suc i) → famSuc i }))
curriedishTrunc : ∥ P zero ∥₁ → (∀ i → ∥ P (suc i) ∥₁) → B
curriedishTrunc = rec (isProp→ isPropB) curriedish
recFin2 : {m1 m2 : ℕ} {P : Fin m1 → Fin m2 → Type ℓ}
{B : Type ℓ'} (isPropB : isProp B)
→ ((∀ i j → P i j) → B)
--------------------------
→ (∀ i j → ∥ P i j ∥₁)
→ B
recFin2 {m1 = zero} _ untruncHyp _ = untruncHyp λ ()
recFin2 {m1 = suc m1} {P = P} {B = B} isPropB untruncHyp truncFam =
curriedishTrunc (truncFam zero) (truncFam ∘ suc)
where
curriedish : (∀ j → P zero j) → (∀ i j → ∥ P (suc i) j ∥₁) → B
curriedish p₀ truncFamSuc = recFin2 isPropB
(λ famSuc → untruncHyp λ { zero → p₀ ; (suc i) → famSuc i })
truncFamSuc
curriedishTrunc : (∀ j → ∥ P zero j ∥₁) → (∀ i j → ∥ P (suc i) j ∥₁) → B
curriedishTrunc = recFin (isProp→ isPropB) curriedish
elim : {P : ∥ A ∥₁ → Type ℓ} → ((a : ∥ A ∥₁) → isProp (P a))
→ ((x : A) → P ∣ x ∣₁) → (a : ∥ A ∥₁) → P a
elim Pprop f ∣ x ∣₁ = f x
elim Pprop f (squash₁ x y i) =
isOfHLevel→isOfHLevelDep 1 Pprop
(elim Pprop f x) (elim Pprop f y) (squash₁ x y) i
elim2 : {P : ∥ A ∥₁ → ∥ B ∥₁ → Type ℓ}
(Pprop : (x : ∥ A ∥₁) (y : ∥ B ∥₁) → isProp (P x y))
(f : (a : A) (b : B) → P ∣ a ∣₁ ∣ b ∣₁)
(x : ∥ A ∥₁) (y : ∥ B ∥₁) → P x y
elim2 Pprop f =
elim (λ _ → isPropΠ (λ _ → Pprop _ _))
(λ a → elim (λ _ → Pprop _ _) (f a))
elim3 : {P : ∥ A ∥₁ → ∥ B ∥₁ → ∥ C ∥₁ → Type ℓ}
(Pprop : ((x : ∥ A ∥₁) (y : ∥ B ∥₁) (z : ∥ C ∥₁) → isProp (P x y z)))
(g : (a : A) (b : B) (c : C) → P (∣ a ∣₁) ∣ b ∣₁ ∣ c ∣₁)
(x : ∥ A ∥₁) (y : ∥ B ∥₁) (z : ∥ C ∥₁) → P x y z
elim3 Pprop g = elim2 (λ _ _ → isPropΠ (λ _ → Pprop _ _ _))
(λ a b → elim (λ _ → Pprop _ _ _) (g a b))
-- n-ary eliminator, stated using a dependent FinVec
elimFin : {m : ℕ} {P : Fin m → Type ℓ}
{B : (∀ i → ∥ P i ∥₁) → Type ℓ'}
(isPropB : ∀ x → isProp (B x))
→ ((x : ∀ i → P i) → B (λ i → ∣ x i ∣₁))
----------------------------------------
→ ((x : ∀ i → ∥ P i ∥₁) → B x)
elimFin {m = zero} {B = B} _ untruncHyp _ = subst B (funExt (λ ())) (untruncHyp (λ ()))
elimFin {m = suc m} {P = P} {B = B} isPropB untruncHyp x =
subst B (funExt (λ { zero → refl ; (suc i) → refl}))
(curriedishTrunc (x zero) (x ∘ suc))
where
curriedish : (x₀ : P zero) (xₛ : ∀ i → ∥ P (suc i) ∥₁)
→ B (λ { zero → ∣ x₀ ∣₁ ; (suc i) → xₛ i})
curriedish x₀ xₛ = subst B (funExt (λ { zero → refl ; (suc i) → refl}))
(elimFin (λ xₛ → isPropB (λ { zero → ∣ x₀ ∣₁ ; (suc i) → xₛ i}))
(λ y → subst B (funExt (λ { zero → refl ; (suc i) → refl}))
(untruncHyp (λ { zero → x₀ ; (suc i) → y i }))) xₛ)
curriedishTrunc : (x₀ : ∥ P zero ∥₁) (xₛ : ∀ i → ∥ P (suc i) ∥₁)
→ B (λ { zero → x₀ ; (suc i) → xₛ i})
curriedishTrunc = elim (λ _ → isPropΠ λ _ → isPropB _)
λ x₀ xₛ → subst B (funExt (λ { zero → refl ; (suc i) → refl}))
(curriedish x₀ xₛ)
∃-elim : {B : A → Type ℓ'} {P : ∃[ x ∈ A ] B x → Type ℓ} (Pprop : ∀ s → isProp (P s))
→ (∀ x y → P ∣ x , y ∣₁) → ∀ s → P s
∃-elim Pprop f = elim Pprop (uncurry f)
isPropPropTrunc : isProp ∥ A ∥₁
isPropPropTrunc x y = squash₁ x y
propTrunc≃ : A ≃ B → ∥ A ∥₁ ≃ ∥ B ∥₁
propTrunc≃ e =
propBiimpl→Equiv
isPropPropTrunc isPropPropTrunc
(rec isPropPropTrunc (λ a → ∣ e .fst a ∣₁))
(rec isPropPropTrunc (λ b → ∣ invEq e b ∣₁))
propTruncIdempotent≃ : isProp A → ∥ A ∥₁ ≃ A
propTruncIdempotent≃ {A = A} hA = isoToEquiv f
where
f : Iso ∥ A ∥₁ A
Iso.fun f = rec hA (idfun A)
Iso.inv f x = ∣ x ∣₁
Iso.sec f _ = refl
Iso.ret f = elim (λ _ → isProp→isSet isPropPropTrunc _ _) (λ _ → refl)
propTruncIdempotent : isProp A → ∥ A ∥₁ ≡ A
propTruncIdempotent hA = ua (propTruncIdempotent≃ hA)
-- We could also define the eliminator using the recursor
elim' : {P : ∥ A ∥₁ → Type ℓ} → ((a : ∥ A ∥₁) → isProp (P a)) →
((x : A) → P ∣ x ∣₁) → (a : ∥ A ∥₁) → P a
elim' {P = P} Pprop f a =
rec (Pprop a) (λ x → transp (λ i → P (squash₁ ∣ x ∣₁ a i)) i0 (f x)) a
map : (A → B) → (∥ A ∥₁ → ∥ B ∥₁)
map f = rec squash₁ (∣_∣₁ ∘ f)
map2 : (A → B → C) → (∥ A ∥₁ → ∥ B ∥₁ → ∥ C ∥₁)
map2 f = rec (isPropΠ λ _ → squash₁) (map ∘ f)
-- The propositional truncation can be eliminated into non-propositional
-- types as long as the function used in the eliminator is 'coherently
-- constant.' The details of this can be found in the following paper:
--
-- https://arxiv.org/pdf/1411.2682.pdf
module SetElim (Bset : isSet B) where
Bset' : isSet' B
Bset' = isSet→isSet' Bset
rec→Set : (f : A → B) (kf : 2-Constant f) → ∥ A ∥₁ → B
helper : (f : A → B) (kf : 2-Constant f) → (t u : ∥ A ∥₁)
→ rec→Set f kf t ≡ rec→Set f kf u
rec→Set f kf ∣ x ∣₁ = f x
rec→Set f kf (squash₁ t u i) = helper f kf t u i
helper f kf ∣ x ∣₁ ∣ y ∣₁ = kf x y
helper f kf (squash₁ t u i) v
= Bset' (helper f kf t v) (helper f kf u v) (helper f kf t u) refl i
helper f kf t (squash₁ u v i)
= Bset' (helper f kf t u) (helper f kf t v) refl (helper f kf u v) i
kcomp : (f : ∥ A ∥₁ → B) → 2-Constant (f ∘ ∣_∣₁)
kcomp f x y = cong f (squash₁ ∣ x ∣₁ ∣ y ∣₁)
Fset : isSet (A → B)
Fset = isSetΠ (const Bset)
Kset : (f : A → B) → isSet (2-Constant f)
Kset f = isSetΠ (λ _ → isSetΠ (λ _ → isProp→isSet (Bset _ _)))
setRecLemma
: (f : ∥ A ∥₁ → B)
→ rec→Set (f ∘ ∣_∣₁) (kcomp f) ≡ f
setRecLemma f i t
= elim {P = λ t → rec→Set (f ∘ ∣_∣₁) (kcomp f) t ≡ f t}
(λ t → Bset _ _) (λ x → refl) t i
mkKmap : (∥ A ∥₁ → B) → Σ (A → B) 2-Constant
mkKmap f = f ∘ ∣_∣₁ , kcomp f
fib : (g : Σ (A → B) 2-Constant) → fiber mkKmap g
fib (g , kg) = rec→Set g kg , refl
eqv : (g : Σ (A → B) 2-Constant) → ∀ fi → fib g ≡ fi
eqv g (f , p) =
Σ≡Prop (λ f → isOfHLevelΣ 2 Fset Kset _ _)
(cong (uncurry rec→Set) (sym p) ∙ setRecLemma f)
trunc→Set≃ : (∥ A ∥₁ → B) ≃ (Σ (A → B) 2-Constant)
trunc→Set≃ .fst = mkKmap
trunc→Set≃ .snd .equiv-proof g = fib g , eqv g
-- The strategy of this equivalence proof follows the paper more closely.
-- It is used further down for the groupoid version, because the above
-- strategy does not generalize so easily.
e : B → Σ (A → B) 2-Constant
e b = const b , λ _ _ → refl
eval : A → (γ : Σ (A → B) 2-Constant) → B
eval a₀ (g , _) = g a₀
e-eval : ∀ (a₀ : A) γ → e (eval a₀ γ) ≡ γ
e-eval a₀ (g , kg) i .fst a₁ = kg a₀ a₁ i
e-eval a₀ (g , kg) i .snd a₁ a₂ = Bset' refl (kg a₁ a₂) (kg a₀ a₁) (kg a₀ a₂) i
e-isEquiv : A → isEquiv (e {A = A})
e-isEquiv a₀ = isoToIsEquiv (iso e (eval a₀) (e-eval a₀) λ _ → refl)
preEquiv₁ : ∥ A ∥₁ → B ≃ Σ (A → B) 2-Constant
preEquiv₁ t = e , rec (isPropIsEquiv e) e-isEquiv t
preEquiv₂ : (∥ A ∥₁ → Σ (A → B) 2-Constant) ≃ Σ (A → B) 2-Constant
preEquiv₂ = isoToEquiv (iso to const (λ _ → refl) retr)
where
to : (∥ A ∥₁ → Σ (A → B) 2-Constant) → Σ (A → B) 2-Constant
to f .fst x = f ∣ x ∣₁ .fst x
to f .snd x y i = f (squash₁ ∣ x ∣₁ ∣ y ∣₁ i) .snd x y i
retr : retract to const
retr f i t .fst x = f (squash₁ ∣ x ∣₁ t i) .fst x
retr f i t .snd x y
= Bset'
(λ j → f (squash₁ ∣ x ∣₁ ∣ y ∣₁ j) .snd x y j)
(f t .snd x y)
(λ j → f (squash₁ ∣ x ∣₁ t j) .fst x)
(λ j → f (squash₁ ∣ y ∣₁ t j) .fst y)
i
trunc→Set≃₂ : (∥ A ∥₁ → B) ≃ Σ (A → B) 2-Constant
trunc→Set≃₂ = compEquiv (equivΠCod preEquiv₁) preEquiv₂
open SetElim public using (rec→Set; trunc→Set≃)
elim→Set : ∀ {ℓ'} {A : Type ℓ'} {P : ∥ A ∥₁ → Type ℓ}
→ (∀ t → isSet (P t))
→ (f : (x : A) → P ∣ x ∣₁)
→ (kf : ∀ x y → PathP (λ i → P (squash₁ ∣ x ∣₁ ∣ y ∣₁ i)) (f x) (f y))
→ (t : ∥ A ∥₁) → P t
elim→Set {A = A} {P = P} Pset f kf t = main t .fst .fst
where
main : (t : ∥ A ∥₁)
→ isContr (Σ[ x ∈ P t ]
((a : A) → PathP (λ i → P (squash₁ t ∣ a ∣₁ i)) x (f a)))
main = elim (λ _ → isPropIsContr)
λ a →
(((f a) , kf a)
, λ {(x , p) → Σ≡Prop (λ _ → isPropΠ
λ _ → isOfHLevelPathP' 1 (Pset _) _ _)
(sym (transport (λ j → PathP (λ i → P (sq a j i)) x (f a)) (p a)))
})
where
sq : (a : A) → squash₁ ∣ a ∣₁ ∣ a ∣₁ ≡ refl
sq a = isProp→isSet squash₁ _ _ _ _
elim2→Set :
{P : ∥ A ∥₁ → ∥ B ∥₁ → Type ℓ}
→ (∀ t u → isSet (P t u))
→ (f : (x : A) (y : B) → P ∣ x ∣₁ ∣ y ∣₁)
→ (kf₁ : ∀ x y v → PathP (λ i → P (squash₁ ∣ x ∣₁ ∣ y ∣₁ i) ∣ v ∣₁) (f x v) (f y v))
→ (kf₂ : ∀ x v w → PathP (λ i → P ∣ x ∣₁ (squash₁ ∣ v ∣₁ ∣ w ∣₁ i)) (f x v) (f x w))
→ (sf : ∀ x y v w → SquareP (λ i j → P (squash₁ ∣ x ∣₁ ∣ y ∣₁ i) (squash₁ ∣ v ∣₁ ∣ w ∣₁ j))
(kf₂ x v w) (kf₂ y v w) (kf₁ x y v) (kf₁ x y w))
→ (t : ∥ A ∥₁) → (u : ∥ B ∥₁) → P t u
elim2→Set {A = A} {B = B} {P = P} Pset f kf₁ kf₂ sf =
elim→Set (λ _ → isSetΠ (λ _ → Pset _ _)) mapHelper squareHelper
where
mapHelper : (x : A) (u : ∥ B ∥₁) → P ∣ x ∣₁ u
mapHelper x = elim→Set (λ _ → Pset _ _) (f x) (kf₂ x)
squareHelper : (x y : A)
→ PathP (λ i → (u : ∥ B ∥₁) → P (squash₁ ∣ x ∣₁ ∣ y ∣₁ i) u) (mapHelper x) (mapHelper y)
squareHelper x y i = elim→Set (λ _ → Pset _ _) (λ v → kf₁ x y v i) λ v w → sf x y v w i
RecHProp : (P : A → hProp ℓ) (kP : ∀ x y → P x ≡ P y) → ∥ A ∥₁ → hProp ℓ
RecHProp P kP = rec→Set isSetHProp P kP
squash₁ᵗ
: ∀(x y z : A)
→ Square (squash₁ ∣ x ∣₁ ∣ y ∣₁) (squash₁ ∣ x ∣₁ ∣ z ∣₁) refl (squash₁ ∣ y ∣₁ ∣ z ∣₁)
squash₁ᵗ x y z i = squash₁ ∣ x ∣₁ (squash₁ ∣ y ∣₁ ∣ z ∣₁ i)
module _ (B : ∥ A ∥₁ → Type ℓ)
(B-gpd : (a : _) → isGroupoid (B a))
(f : (a : A) → B ∣ a ∣₁)
(f-coh : (x y : A) → PathP (λ i → B (squash₁ ∣ x ∣₁ ∣ y ∣₁ i)) (f x) (f y))
(f-coh-coh : (x y z : A) → SquareP
(λ i j → B (squash₁ ∣ x ∣₁ (squash₁ ∣ y ∣₁ ∣ z ∣₁ i) j))
(f-coh x y) (f-coh x z) refl (f-coh y z))
where
elim→Gpd : (t : ∥ A ∥₁) → B t
private
pathHelper : (t u : ∥ A ∥₁) → PathP (λ i → B (squash₁ t u i)) (elim→Gpd t) (elim→Gpd u)
triHelper₁
: (t u v : ∥ A ∥₁)
→ SquareP (λ i j → B (squash₁ t (squash₁ u v i) j))
(pathHelper t u) (pathHelper t v)
refl (pathHelper u v)
triHelper₂
: (t u v : ∥ A ∥₁)
→ SquareP (λ i j → B (squash₁ (squash₁ t u i) v j))
(pathHelper t v) (pathHelper u v)
(pathHelper t u) refl
triHelper₂Cube : (x y z : ∥ A ∥₁)
→ Cube (λ j k → squash₁ x z (k ∧ j))
(λ j k → squash₁ y z j)
(λ i k → squash₁ x y i)
(λ i k → squash₁ x z (i ∨ k))
(λ i j → squash₁ x (squash₁ y z j) i)
(λ i j → squash₁ (squash₁ x y i) z j)
elim→Gpd ∣ x ∣₁ = f x
elim→Gpd (squash₁ t u i) = pathHelper t u i
triHelper₂Cube x y z =
isProp→PathP (λ _ → isOfHLevelPathP 1 (isOfHLevelPath 1 squash₁ _ _) _ _) _ _
pathHelper ∣ x ∣₁ ∣ y ∣₁ = f-coh x y
pathHelper (squash₁ t u j) v = triHelper₂ t u v j
pathHelper ∣ x ∣₁ (squash₁ u v j) = triHelper₁ ∣ x ∣₁ u v j
triHelper₁ ∣ x ∣₁ ∣ y ∣₁ ∣ z ∣₁ = f-coh-coh x y z
triHelper₁ (squash₁ s t i) u v
= isGroupoid→CubeP (λ i i₁ j → B (squash₁ (squash₁ s t i) (squash₁ u v i₁) j))
(triHelper₁ s u v) (triHelper₁ t u v)
(triHelper₂ s t u)
(triHelper₂ s t v)
(λ i j → pathHelper s t i)
(λ i j → pathHelper u v j)
(B-gpd v) i
triHelper₁ ∣ x ∣₁ (squash₁ t u i) v
= isGroupoid→CubeP (λ i i₁ j → B (squash₁ ∣ x ∣₁ (squash₁ (squash₁ t u i) v i₁) j))
(triHelper₁ ∣ x ∣₁ t v) (triHelper₁ ∣ x ∣₁ u v)
(triHelper₁ ∣ x ∣₁ t u)
(λ i j → pathHelper ∣ x ∣₁ v j)
refl (triHelper₂ t u v)
(B-gpd v) i
triHelper₁ ∣ x ∣₁ ∣ y ∣₁ (squash₁ u v i)
= isGroupoid→CubeP (λ i i₁ j → B (squash₁ ∣ x ∣₁ (squash₁ ∣ y ∣₁ (squash₁ u v i) i₁) j))
(triHelper₁ ∣ x ∣₁ ∣ y ∣₁ u) (triHelper₁ ∣ x ∣₁ ∣ y ∣₁ v)
(λ i j → f-coh x y j) (triHelper₁ ∣ x ∣₁ u v)
refl (triHelper₁ ∣ y ∣₁ u v)
(B-gpd v) i
triHelper₂ ∣ x ∣₁ ∣ y ∣₁ ∣ z ∣₁ i j =
comp (λ k → B (triHelper₂Cube ∣ x ∣₁ ∣ y ∣₁ ∣ z ∣₁ i j k))
(λ k → λ {(i = i0) → f-coh x z (k ∧ j)
; (i = i1) → f-coh y z j
; (j = i0) → f-coh x y i
; (j = i1) → f-coh x z (i ∨ k)})
(f-coh-coh x y z j i)
triHelper₂ (squash₁ s t i) u v
= isGroupoid→CubeP (λ i i₁ j → B (squash₁ (squash₁ (squash₁ s t i) u i₁) v j))
(triHelper₂ s u v) (triHelper₂ t u v)
(triHelper₂ s t v) (λ i j → pathHelper u v j)
(triHelper₂ s t u) refl
(B-gpd v) i
triHelper₂ ∣ x ∣₁ (squash₁ t u i) v
= isGroupoid→CubeP (λ i i₁ j → B (squash₁ (squash₁ ∣ x ∣₁ (squash₁ t u i) i₁) v j))
(triHelper₂ ∣ x ∣₁ t v) (triHelper₂ ∣ x ∣₁ u v)
(λ i j → pathHelper ∣ x ∣₁ v j) (triHelper₂ t u v)
(triHelper₁ ∣ x ∣₁ t u) refl
(B-gpd v) i
triHelper₂ ∣ x ∣₁ ∣ y ∣₁ (squash₁ u v i)
= isGroupoid→CubeP (λ i i₁ j → B (squash₁ (squash₁ ∣ x ∣₁ ∣ y ∣₁ i₁) (squash₁ u v i) j))
(triHelper₂ ∣ x ∣₁ ∣ y ∣₁ u) (triHelper₂ ∣ x ∣₁ ∣ y ∣₁ v)
(triHelper₁ ∣ x ∣₁ u v) (triHelper₁ ∣ y ∣₁ u v)
refl (λ i j → pathHelper u v i)
(B-gpd v) i
module GpdElim (Bgpd : isGroupoid B) where
Bgpd' : isGroupoid' B
Bgpd' = isGroupoid→isGroupoid' Bgpd
module _ (f : A → B) (3kf : 3-Constant f) where
open 3-Constant 3kf
rec→Gpd : ∥ A ∥₁ → B
rec→Gpd = elim→Gpd (λ _ → B) (λ _ → Bgpd) f link coh₁
preEquiv₁ : (∥ A ∥₁ → Σ (A → B) 3-Constant) ≃ Σ (A → B) 3-Constant
preEquiv₁ = isoToEquiv (iso fn const (λ _ → refl) retr)
where
open 3-Constant
fn : (∥ A ∥₁ → Σ (A → B) 3-Constant) → Σ (A → B) 3-Constant
fn f .fst x = f ∣ x ∣₁ .fst x
fn f .snd .link x y i = f (squash₁ ∣ x ∣₁ ∣ y ∣₁ i) .snd .link x y i
fn f .snd .coh₁ x y z i j
= f (squash₁ ∣ x ∣₁ (squash₁ ∣ y ∣₁ ∣ z ∣₁ i) j) .snd .coh₁ x y z i j
retr : retract fn const
retr f i t .fst x = f (squash₁ ∣ x ∣₁ t i) .fst x
retr f i t .snd .link x y j
= f (squash₁ (squash₁ ∣ x ∣₁ ∣ y ∣₁ j) t i) .snd .link x y j
retr f i t .snd .coh₁ x y z
= Bgpd'
(λ k j → f (cb k j i0) .snd .coh₁ x y z k j )
(λ k j → f (cb k j i1) .snd .coh₁ x y z k j)
(λ k j → f (cb i0 j k) .snd .link x y j)
(λ k j → f (cb i1 j k) .snd .link x z j)
(λ _ → refl)
(λ k j → f (cb j i1 k) .snd .link y z j)
i
where
cb : I → I → I → ∥ _ ∥₁
cb i j k = squash₁ (squash₁ ∣ x ∣₁ (squash₁ ∣ y ∣₁ ∣ z ∣₁ i) j) t k
e : B → Σ (A → B) 3-Constant
e b .fst _ = b
e b .snd = record
{ link = λ _ _ _ → b
; coh₁ = λ _ _ _ _ _ → b
}
eval : A → Σ (A → B) 3-Constant → B
eval a₀ (g , _) = g a₀
module _ where
open 3-Constant
e-eval : ∀(a₀ : A) γ → e (eval a₀ γ) ≡ γ
e-eval a₀ (g , 3kg) i .fst x = 3kg .link a₀ x i
e-eval a₀ (g , 3kg) i .snd .link x y = λ j → 3kg .coh₁ a₀ x y j i
e-eval a₀ (g , 3kg) i .snd .coh₁ x y z
= Bgpd'
(λ _ _ → g a₀)
(3kg .coh₁ x y z)
(λ k j → 3kg .coh₁ a₀ x y j k)
(λ k j → 3kg .coh₁ a₀ x z j k)
(λ _ → refl)
(λ k j → 3kg .coh₁ a₀ y z j k)
i
e-isEquiv : A → isEquiv (e {A = A})
e-isEquiv a₀ = isoToIsEquiv (iso e (eval a₀) (e-eval a₀) λ _ → refl)
preEquiv₂ : ∥ A ∥₁ → B ≃ Σ (A → B) 3-Constant
preEquiv₂ t = e , rec (isPropIsEquiv e) e-isEquiv t
trunc→Gpd≃ : (∥ A ∥₁ → B) ≃ Σ (A → B) 3-Constant
trunc→Gpd≃ = compEquiv (equivΠCod preEquiv₂) preEquiv₁
open GpdElim using (rec→Gpd; trunc→Gpd≃) public
RecHSet : (P : A → TypeOfHLevel ℓ 2) → 3-Constant P → ∥ A ∥₁ → TypeOfHLevel ℓ 2
RecHSet P 3kP = rec→Gpd (isOfHLevelTypeOfHLevel 2) P 3kP
∥∥-IdempotentL-⊎-≃ : ∥ ∥ A ∥₁ ⊎ A′ ∥₁ ≃ ∥ A ⊎ A′ ∥₁
∥∥-IdempotentL-⊎-≃ = isoToEquiv ∥∥-IdempotentL-⊎-Iso
where ∥∥-IdempotentL-⊎-Iso : Iso (∥ ∥ A ∥₁ ⊎ A′ ∥₁) (∥ A ⊎ A′ ∥₁)
Iso.fun ∥∥-IdempotentL-⊎-Iso x = rec squash₁ lem x
where lem : ∥ A ∥₁ ⊎ A′ → ∥ A ⊎ A′ ∥₁
lem (inl x) = map (λ a → inl a) x
lem (inr x) = ∣ inr x ∣₁
Iso.inv ∥∥-IdempotentL-⊎-Iso x = map lem x
where lem : A ⊎ A′ → ∥ A ∥₁ ⊎ A′
lem (inl x) = inl ∣ x ∣₁
lem (inr x) = inr x
Iso.sec ∥∥-IdempotentL-⊎-Iso x = squash₁ (Iso.fun ∥∥-IdempotentL-⊎-Iso (Iso.inv ∥∥-IdempotentL-⊎-Iso x)) x
Iso.ret ∥∥-IdempotentL-⊎-Iso x = squash₁ (Iso.inv ∥∥-IdempotentL-⊎-Iso (Iso.fun ∥∥-IdempotentL-⊎-Iso x)) x
∥∥-IdempotentL-⊎ : ∥ ∥ A ∥₁ ⊎ A′ ∥₁ ≡ ∥ A ⊎ A′ ∥₁
∥∥-IdempotentL-⊎ = ua ∥∥-IdempotentL-⊎-≃
∥∥-IdempotentR-⊎-≃ : ∥ A ⊎ ∥ A′ ∥₁ ∥₁ ≃ ∥ A ⊎ A′ ∥₁
∥∥-IdempotentR-⊎-≃ = isoToEquiv ∥∥-IdempotentR-⊎-Iso
where ∥∥-IdempotentR-⊎-Iso : Iso (∥ A ⊎ ∥ A′ ∥₁ ∥₁) (∥ A ⊎ A′ ∥₁)
Iso.fun ∥∥-IdempotentR-⊎-Iso x = rec squash₁ lem x
where lem : A ⊎ ∥ A′ ∥₁ → ∥ A ⊎ A′ ∥₁
lem (inl x) = ∣ inl x ∣₁
lem (inr x) = map (λ a → inr a) x
Iso.inv ∥∥-IdempotentR-⊎-Iso x = map lem x
where lem : A ⊎ A′ → A ⊎ ∥ A′ ∥₁
lem (inl x) = inl x
lem (inr x) = inr ∣ x ∣₁
Iso.sec ∥∥-IdempotentR-⊎-Iso x = squash₁ (Iso.fun ∥∥-IdempotentR-⊎-Iso (Iso.inv ∥∥-IdempotentR-⊎-Iso x)) x
Iso.ret ∥∥-IdempotentR-⊎-Iso x = squash₁ (Iso.inv ∥∥-IdempotentR-⊎-Iso (Iso.fun ∥∥-IdempotentR-⊎-Iso x)) x
∥∥-IdempotentR-⊎ : ∥ A ⊎ ∥ A′ ∥₁ ∥₁ ≡ ∥ A ⊎ A′ ∥₁
∥∥-IdempotentR-⊎ = ua ∥∥-IdempotentR-⊎-≃
∥∥-Idempotent-⊎ : {A : Type ℓ} {A′ : Type ℓ'} → ∥ ∥ A ∥₁ ⊎ ∥ A′ ∥₁ ∥₁ ≡ ∥ A ⊎ A′ ∥₁
∥∥-Idempotent-⊎ {A = A} {A′} = ∥ ∥ A ∥₁ ⊎ ∥ A′ ∥₁ ∥₁ ≡⟨ ∥∥-IdempotentR-⊎ ⟩
∥ ∥ A ∥₁ ⊎ A′ ∥₁ ≡⟨ ∥∥-IdempotentL-⊎ ⟩
∥ A ⊎ A′ ∥₁ ∎
∥∥-IdempotentL-×-≃ : ∥ ∥ A ∥₁ × A′ ∥₁ ≃ ∥ A × A′ ∥₁
∥∥-IdempotentL-×-≃ = isoToEquiv ∥∥-IdempotentL-×-Iso
where ∥∥-IdempotentL-×-Iso : Iso (∥ ∥ A ∥₁ × A′ ∥₁) (∥ A × A′ ∥₁)
Iso.fun ∥∥-IdempotentL-×-Iso x = rec squash₁ lem x
where lem : ∥ A ∥₁ × A′ → ∥ A × A′ ∥₁
lem (a , a′) = map2 (λ a a′ → a , a′) a ∣ a′ ∣₁
Iso.inv ∥∥-IdempotentL-×-Iso x = map lem x
where lem : A × A′ → ∥ A ∥₁ × A′
lem (a , a′) = ∣ a ∣₁ , a′
Iso.sec ∥∥-IdempotentL-×-Iso x = squash₁ (Iso.fun ∥∥-IdempotentL-×-Iso (Iso.inv ∥∥-IdempotentL-×-Iso x)) x
Iso.ret ∥∥-IdempotentL-×-Iso x = squash₁ (Iso.inv ∥∥-IdempotentL-×-Iso (Iso.fun ∥∥-IdempotentL-×-Iso x)) x
∥∥-IdempotentL-× : ∥ ∥ A ∥₁ × A′ ∥₁ ≡ ∥ A × A′ ∥₁
∥∥-IdempotentL-× = ua ∥∥-IdempotentL-×-≃
∥∥-IdempotentR-×-≃ : ∥ A × ∥ A′ ∥₁ ∥₁ ≃ ∥ A × A′ ∥₁
∥∥-IdempotentR-×-≃ = isoToEquiv ∥∥-IdempotentR-×-Iso
where ∥∥-IdempotentR-×-Iso : Iso (∥ A × ∥ A′ ∥₁ ∥₁) (∥ A × A′ ∥₁)
Iso.fun ∥∥-IdempotentR-×-Iso x = rec squash₁ lem x
where lem : A × ∥ A′ ∥₁ → ∥ A × A′ ∥₁
lem (a , a′) = map2 (λ a a′ → a , a′) ∣ a ∣₁ a′
Iso.inv ∥∥-IdempotentR-×-Iso x = map lem x
where lem : A × A′ → A × ∥ A′ ∥₁
lem (a , a′) = a , ∣ a′ ∣₁
Iso.sec ∥∥-IdempotentR-×-Iso x = squash₁ (Iso.fun ∥∥-IdempotentR-×-Iso (Iso.inv ∥∥-IdempotentR-×-Iso x)) x
Iso.ret ∥∥-IdempotentR-×-Iso x = squash₁ (Iso.inv ∥∥-IdempotentR-×-Iso (Iso.fun ∥∥-IdempotentR-×-Iso x)) x
∥∥-IdempotentR-× : ∥ A × ∥ A′ ∥₁ ∥₁ ≡ ∥ A × A′ ∥₁
∥∥-IdempotentR-× = ua ∥∥-IdempotentR-×-≃
∥∥-Idempotent-× : {A : Type ℓ} {A′ : Type ℓ'} → ∥ ∥ A ∥₁ × ∥ A′ ∥₁ ∥₁ ≡ ∥ A × A′ ∥₁
∥∥-Idempotent-× {A = A} {A′} = ∥ ∥ A ∥₁ × ∥ A′ ∥₁ ∥₁ ≡⟨ ∥∥-IdempotentR-× ⟩
∥ ∥ A ∥₁ × A′ ∥₁ ≡⟨ ∥∥-IdempotentL-× ⟩
∥ A × A′ ∥₁ ∎
∥∥-Idempotent-×-≃ : {A : Type ℓ} {A′ : Type ℓ'} → ∥ ∥ A ∥₁ × ∥ A′ ∥₁ ∥₁ ≃ ∥ A × A′ ∥₁
∥∥-Idempotent-×-≃ {A = A} {A′} = compEquiv ∥∥-IdempotentR-×-≃ ∥∥-IdempotentL-×-≃
∥∥-×-≃ : {A : Type ℓ} {A′ : Type ℓ'} → ∥ A ∥₁ × ∥ A′ ∥₁ ≃ ∥ A × A′ ∥₁
∥∥-×-≃ {A = A} {A′} = compEquiv (invEquiv (propTruncIdempotent≃ (isProp× isPropPropTrunc isPropPropTrunc))) ∥∥-Idempotent-×-≃
∥∥-× : {A : Type ℓ} {A′ : Type ℓ'} → ∥ A ∥₁ × ∥ A′ ∥₁ ≡ ∥ A × A′ ∥₁
∥∥-× = ua ∥∥-×-≃
-- using this we get a convenient recursor/eliminator for binary functions into sets
rec2→Set : {A B C : Type ℓ} (Cset : isSet C)
→ (f : A → B → C)
→ (∀ (a a' : A) (b b' : B) → f a b ≡ f a' b')
→ ∥ A ∥₁ → ∥ B ∥₁ → C
rec2→Set {A = A} {B = B} {C = C} Cset f fconst = curry (g ∘ ∥∥-×-≃ .fst)
where
g : ∥ A × B ∥₁ → C
g = rec→Set Cset (uncurry f) λ x y → fconst (fst x) (fst y) (snd x) (snd y)-- SOURCE URL: `https://agda.github.io/cubical/Cubical.HITs.Pushout.PushoutProduct.html`
{-
This file contains:
- Pushout-products of two maps;
- The connectivity of pushout-product maps.
-}
module Cubical.HITs.Pushout.PushoutProduct where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Equiv.Properties
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Function
open import Cubical.Foundations.HLevels
open import Cubical.Data.Nat
open import Cubical.Data.Sigma
open import Cubical.HITs.Pushout.Base
open import Cubical.HITs.Pushout.Properties
open import Cubical.Homotopy.Connected
private
variable
ℓ ℓ' ℓ'' ℓ''' : Level
A : Type ℓ
B : Type ℓ'
X : Type ℓ''
Y : Type ℓ'''
-- The definition of pushout-product
PushProd : (f : X → A)(g : Y → B) → Type _
PushProd f g = Pushout (map-× (idfun _) g) (map-× f (idfun _))
_×̂_ : (f : X → A)(g : Y → B) → PushProd f g → A × B
(f ×̂ g) (inl (x , b)) = f x , b
(f ×̂ g) (inr (a , y)) = a , g y
(f ×̂ g) (push (x , y) i) = f x , g y
infixr 5 _×̂_
module _
(m n : ℕ)(f : X → A)(g : Y → B)
(connf : isConnectedFun m f)
(conng : isConnectedFun n g)
(P : A × B → TypeOfHLevel ℓ (m + n)) where
module _
(sec : (x : PushProd f g) → P ((f ×̂ g) x) .fst) where
private
fam : A → Type _
fam a = Σ[ k ∈ ((b : B) → P (a , b) .fst) ] ((y : Y) → k (g y) ≡ sec (inr (a , y)))
fiberEquiv : (a : A)
→ fam a ≃ fiber (λ(s : (b : B) → P (a , b) .fst) → s ∘ g) (λ y → sec (inr (a , y)))
fiberEquiv a = isoToEquiv
(iso (λ (k , p) → k , λ i y → p y i)
(λ (k , p) → k , λ y i → p i y)
(λ _ → refl) (λ _ → refl))
is-m-trunc-fam : (a : A) → isOfHLevel m (fam a)
is-m-trunc-fam a =
isOfHLevelRespectEquiv _ (invEquiv (fiberEquiv a))
(isOfHLevelPrecomposeConnected m n (λ b → P (a , b)) g conng _)
sec-fam : (x : X) → fam (f x)
sec-fam x = (λ b → sec (inl (x , b))) , (λ y i → sec (push (x , y) i))
map-iso = elim.isIsoPrecompose f _ (λ a → fam a , is-m-trunc-fam a) connf
k = map-iso .Iso.inv sec-fam
ϕ = map-iso .Iso.sec sec-fam
ext : (x : A × B) → P x .fst
ext (a , b) = k a .fst b
ext-path : (x : PushProd f g) → ext ((f ×̂ g) x) ≡ sec x
ext-path (inl (x , b)) i = ϕ i x .fst b
ext-path (inr (a , y)) i = k a .snd y i
ext-path (push (x , y) i) j =
hcomp (λ k → λ
{ (i = i0) → ϕ j x .snd y i0
; (i = i1) → ϕ i0 x .snd y (j ∨ ~ k)
; (j = i0) → ϕ i0 x .snd y (i ∧ ~ k)
; (j = i1) → ϕ i1 x .snd y i })
(ϕ j x .snd y i)
lifting : hasSection (λ(s : (x : A × B) → P x .fst) → s ∘ (f ×̂ g))
lifting .fst sec = ext sec
lifting .snd sec i x = ext-path sec x i
-- The connectivity of pushout-product
isConnected×̂ : {m n : ℕ}{f : A → B}{g : X → Y}
→ isConnectedFun m f → isConnectedFun n g
→ isConnectedFun (m + n) (f ×̂ g)
isConnected×̂ congf congg =
elim.isConnectedPrecompose _ _ (lifting _ _ _ _ congf congg)-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Homotopy.Group.Pi4S3.BrunerieNumber.html`
{-
The goal of this file is to prove the iso π₄S³≅ℤ/β
where β is a natural number (aka "the Brunerie number",
defined below).
-}
{-# OPTIONS --lossy-unification #-}
module Cubical.Homotopy.Group.Pi4S3.BrunerieNumber where
open import Cubical.Homotopy.Loopspace
open import Cubical.Homotopy.Group.Base
open import Cubical.Homotopy.HopfInvariant.Base
open import Cubical.Homotopy.Group.Pi3S2
open import Cubical.Homotopy.Group.PinSn
open import Cubical.Homotopy.BlakersMassey
open import Cubical.Homotopy.Whitehead
open import Cubical.Homotopy.Connected
open import Cubical.Homotopy.Group.LES
open import Cubical.Homotopy.Group.Pi4S3.S3PushoutIso2
open import Cubical.Homotopy.Group.Pi4S3.S3PushoutIso
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Pointed
open import Cubical.Foundations.Function
open import Cubical.Foundations.HLevels
open import Cubical.Foundations.GroupoidLaws
open import Cubical.Foundations.Path
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Equiv
open import Cubical.Data.Unit
open import Cubical.Data.Sigma
open import Cubical.Data.Nat
open import Cubical.Data.Int
renaming (ℤ to Z ; _·_ to _·Z_ ; _+_ to _+Z_)
open import Cubical.HITs.S1
open import Cubical.HITs.Sn
open import Cubical.HITs.Sn.Multiplication
open import Cubical.HITs.Join
open import Cubical.HITs.Susp
open import Cubical.HITs.Wedge
open import Cubical.HITs.Pushout
open import Cubical.HITs.PropositionalTruncation
renaming (rec to pRec ; elim to pElim ; map to pMap)
open import Cubical.HITs.SetTruncation
renaming (rec to sRec ; rec2 to sRec2
; elim to sElim ; elim2 to sElim2 ; elim3 to sElim3
; map to sMap)
open import Cubical.HITs.Truncation renaming
(rec to trRec ; elim to trElim ; elim2 to trElim2 ; map to trMap)
open import Cubical.Algebra.Group
open import Cubical.Algebra.Group.Exact
open import Cubical.Algebra.Group.ZAction
open import Cubical.Algebra.Group.Instances.IntMod
open import Cubical.Algebra.Group.Morphisms
open import Cubical.Algebra.Group.MorphismProperties
open import Cubical.Algebra.Group.Instances.Unit
open import Cubical.Algebra.Group.GroupPath
open Iso
open Exact4
-- The Brunerie number (see Corollary 3.4.5 in Brunerie's PhD thesis)
Brunerie : ℕ
Brunerie =
abs (HopfInvariant-π' 0 [ ∣ idfun∙ (S₊∙ 2) ∣₂ ∣ ∣ idfun∙ (S₊∙ 2) ∣₂ ]π')
-- First we need to define the following maps.
W : S₊ 3 → (S₊∙ 2 ⋁ S₊∙ 2)
W = joinTo⋁ {A = S₊∙ 1} {B = S₊∙ 1} ∘ Iso.inv (IsoSphereJoin 1 1)
fold∘W : S₊ 3 → S₊ 2
fold∘W = fold⋁ ∘ W
{-
We will now instantiate Blakers Massey to get a square:
fold∘W
S³ --------------> S²
|\ ↗ |
| \ ↗ |
| \ ↗ |
| X | inr
| / |
| / |
| / |
v / v
1 -----------> coFib fold∘W
inl
where X is the pullback of inl and inr and the map S³ → X is
surjective on π₃. This will give us a sequence
π₃ S³ --ᶠ→ π₃ S² → π₃ (coFib fold∘W) → π₂ X ≅ 0, where f is
the function induced by fold∘W. From this, we can deduce that
π₃ (coFib fold∘W) ≅ ℤ/ f(1) where f(1) is interpreted as an
integer via the isos π₃ S³ ≅ π₃ S² ≅ ℤ
(Recall that π₃(coFib fold∘W) ≅ π₄S³)
For clarity:
X, above will have two names (via a trivial iso) below:
TotalPushoutPath× (the version the falls out of BM)
P = fiber inr (Same name as in Brunerie's prop 4.3.4.)
-}
-- Before instantiating, we need to show that
-- any map S³ → S² is 0-connected
isConnectedS3→S2 : (f : S₊ 3 → S₊ 2) → isConnectedFun 2 f
isConnectedS3→S2 f p =
trRec (isProp→isOfHLevelSuc 1 isPropIsContr)
(J (λ p _ → isConnected 2 (fiber f p))
(∣ north , refl ∣
, (trElim (λ _ → isOfHLevelPath 2 (isOfHLevelTrunc 2) _ _)
(uncurry
(sphereElim 2
(λ _ → isOfHLevelΠ 3
λ _ → isOfHLevelPath 3
(isOfHLevelSuc 2 (isOfHLevelTrunc 2)) _ _)
λ p → trRec (isOfHLevelTrunc 2 _ _)
(λ r → cong ∣_∣ₕ (ΣPathP (refl , r)))
(fun (PathIdTruncIso 1)
(isContr→isProp
(isConnectedPath 2 (sphereConnected 2)
(f north) (f north)) ∣ refl ∣ ∣ p ∣)))))))
(fun (PathIdTruncIso 2)
(isContr→isProp (sphereConnected 2) ∣ f north ∣ ∣ p ∣))
-- We get our square
module BM-inst =
BlakersMassey□
(λ _ → tt) fold∘W 3 1
(λ _ → subst (isConnected 4)
(isoToPath (invIso fiberUnitIso))
(sphereConnected 3))
(isConnectedS3→S2 fold∘W)
open BM-inst
-- The central types
coFib-fold∘W : Type
coFib-fold∘W = Pushout (λ _ → tt) fold∘W
coFib-fold∘W∙ : Pointed₀
coFib-fold∘W∙ = coFib-fold∘W , inl tt
TotalPushoutPath×∙ : Pointed ℓ-zero
fst TotalPushoutPath×∙ = Σ (Unit × S₊ 2) PushoutPath×
snd TotalPushoutPath×∙ = (tt , north) , push north
S³→TotalPushoutPath× : S₊ 3 → Σ (Unit × S₊ 2) PushoutPath×
S³→TotalPushoutPath× = toPullback
private
inr' : S₊ 2 → coFib-fold∘W
inr' = inr
inr∙ : S₊∙ 2 →∙ coFib-fold∘W∙
fst inr∙ = inr'
snd inr∙ = sym (push north)
fiberinr'Iso' : Iso (fiber inr' (inl tt))
(Σ (Unit × S₊ 2) PushoutPath×)
fiberinr'Iso' =
compIso (Σ-cong-iso-snd (λ x → symIso))
(Σ-cong-iso-fst (invIso lUnit×Iso))
fiberinr'Iso : Iso (fiber inr' (inl tt))
(Σ (Unit × S₊ 2) PushoutPath×)
fun fiberinr'Iso (x , p) = (tt , x) , (sym p)
inv fiberinr'Iso ((tt , x) , p) = x , (sym p)
sec fiberinr'Iso _ = refl
ret fiberinr'Iso _ = refl
P : Pointed₀
P = (fiber inr' (inl tt) , north , (sym (push north)))
π'P→π'TotalPath× : (n : ℕ)
→ GroupEquiv (π'Gr n TotalPushoutPath×∙) (π'Gr n P)
fst (fst (π'P→π'TotalPath× n)) =
π'eqFun n ((invEquiv (isoToEquiv fiberinr'Iso)) , refl)
snd (fst (π'P→π'TotalPath× n)) = π'eqFunIsEquiv n _
snd (π'P→π'TotalPath× n) = π'eqFunIsHom n _
-- Time to invoke the long exact sequence of homotopy groups on
-- inr : S² → coFib-fold∘W
module LESinst = πLES {A = S₊∙ 2} {B = coFib-fold∘W∙} inr∙
-- We instantiate the sequence
-- π₃ P → π₃ S² → π₃ coFib-fold∘W∙ → π₂ P
P→S²→Pushout :
Exact4 (πGr 2 P) (πGr 2 (S₊∙ 2)) (πGr 2 coFib-fold∘W∙) (πGr 1 P)
(LESinst.fib→A 2)
(LESinst.A→B 2)
(LESinst.B→fib 1)
Exact4.ImG→H⊂KerH→L P→S²→Pushout = LESinst.Im-fib→A⊂Ker-A→B 2
Exact4.KerH→L⊂ImG→H P→S²→Pushout = LESinst.Ker-A→B⊂Im-fib→A 2
Exact4.ImH→L⊂KerL→R P→S²→Pushout = LESinst.Im-A→B⊂Ker-B→fib 1
Exact4.KerL→R⊂ImH→L P→S²→Pushout = LESinst.Ker-B→fib⊂Im-A→B 1
-- The goal now is to rewrite it as
-- π₃ S³ → π₃ S² → π₃ coFib-fold∘W∙ → Unit using the
-- "functions from spheres"-definition of πₙ.
-- Here, the first map is the one induced by fold∘W. We do this by:
-- (1) showing that π₂ P is trivial
-- (2) extending the sequence by appending surjections
-- π₃ S³ → π₃ TotalPushoutPath×∙ → π₃ P on the left.
-- (3) proving that this new composition is indeed the appropriate map
-- Step 1: π₂ P is trivial
π₂P≅0 : GroupEquiv (πGr 1 P) UnitGroup₀
π₂P≅0 = compGroupEquiv (πIso (isoToEquiv fiberinr'Iso , refl) 1)
(GroupIso→GroupEquiv
(contrGroupIsoUnit
(isOfHLevelRetractFromIso 0 (invIso iso₂) isContrπ₂S³)))
where
iso₁ : Iso (hLevelTrunc 4 (S₊ 3))
(hLevelTrunc 4 (Σ (Unit × S₊ 2) PushoutPath×))
iso₁ = connectedTruncIso 4 S³→TotalPushoutPath× isConnected-toPullback
iso₂ : Iso (π 2 (hLevelTrunc∙ 4 (S₊∙ 3)))
(π 2 TotalPushoutPath×∙)
iso₂ =
(compIso (setTruncIso
(equivToIso (_ ,
(isEquivΩ^→ 2 (fun iso₁ , refl) (isoToIsEquiv iso₁)))))
(invIso (πTruncIso 2)))
isContrπ₂S³ : isContr (π 2 (hLevelTrunc∙ 4 (S₊∙ 3)))
isContrπ₂S³ =
subst (λ x → isContr (π 2 x))
(λ i → ((sym (isContr→≡Unit (sphereConnected 3))) i)
, transp (λ j → isContr→≡Unit
(sphereConnected 3) (~ i ∧ j)) i ∣ north ∣)
(∣ refl ∣₂ , sElim (λ _ → isSetPathImplicit)
λ p → cong ∣_∣₂
(isProp→isSet
(isOfHLevelPath 1 isPropUnit _ _) _ _ _ p))
-- Step 2. We transform our original sequence to one for the
-- the "maps from spheres" definition of πₙ and where π₂ P is
-- replaced by the trivial group:
-- π₃ P → π₃ S² → π₃ coFib-fold∘W∙ → 0
P→S²→Pushout→P' :
Exact4 (π'Gr 2 P) (π'Gr 2 (S₊∙ 2)) (π'Gr 2 coFib-fold∘W∙) UnitGroup₀
(π'∘∙Hom 2 (fst , refl))
(π'∘∙Hom 2 inr∙)
(→UnitHom _)
P→S²→Pushout→P' =
transportExact4
(sym (GroupPath _ _ .fst ((GroupIso→GroupEquiv (π'Gr≅πGr 2 P)))))
(sym (GroupPath _ _ .fst ((GroupIso→GroupEquiv (π'Gr≅πGr 2 (S₊∙ 2))))))
(sym (GroupPath _ _ .fst ((GroupIso→GroupEquiv (π'Gr≅πGr 2 coFib-fold∘W∙)))))
(sym (GroupPath _ _ .fst π₂P≅0))
_ _ _ _ _
P→S²→Pushout
(ΣPathPProp (λ _ → isPropIsGroupHom _ _)
λ i → fst (π∘∙fib→A-PathP 2 inr∙ i))
(ΣPathPProp (λ _ → isPropIsGroupHom _ _)
λ i → fst (π∘∙A→B-PathP 2 inr∙ i))
-- The two surjections in question
π₃S³→π₃P : GroupHom (π'Gr 2 (S₊∙ 3)) (π'Gr 2 TotalPushoutPath×∙)
π₃S³→π₃P = π'∘∙Hom 2 (S³→TotalPushoutPath× , refl)
TotalPushoutPath×∙→P : TotalPushoutPath×∙ →∙ P -- Surjective, and in particular on π₃
fst TotalPushoutPath×∙→P x = (snd (fst x)) , (sym (snd x))
snd TotalPushoutPath×∙→P = refl
-- This surjectivity is where Blakers-Massey is used
-- In particular, it uses isConnected-toPullback
isSurjective-π₃S³→π₃TotalPushoutPath× : isSurjective π₃S³→π₃P
isSurjective-π₃S³→π₃TotalPushoutPath× =
transport (λ i → isSurjective (transportLem i))
isSurjective-π₃S³→π₃TotalPushoutPath×'
where
π₃S³→π₃TotalPushoutPath× : GroupHom (πGr 2 (S₊∙ 3)) (πGr 2 TotalPushoutPath×∙)
π₃S³→π₃TotalPushoutPath× = πHom 2 (S³→TotalPushoutPath× , refl)
isSurjective-π₃S³→π₃TotalPushoutPath×' : isSurjective π₃S³→π₃TotalPushoutPath×
isSurjective-π₃S³→π₃TotalPushoutPath×' =
sElim (λ _ → isProp→isSet squash₁)
λ p → trRec squash₁
(λ s → ∣ ∣ fst s ∣₂ , (cong ∣_∣₂ (snd s)) ∣₁)
(((isConnectedΩ^→ 3 3 (S³→TotalPushoutPath× , refl)
isConnected-toPullback) p) .fst)
transportLem : PathP (λ i → GroupHomπ≅π'PathP (S₊∙ 3) TotalPushoutPath×∙ 2 2 i)
π₃S³→π₃TotalPushoutPath× π₃S³→π₃P
transportLem =
toPathP (Σ≡Prop (λ _ → isPropIsGroupHom _ _)
(π'∘∙Hom'≡π'∘∙fun {A = S₊∙ 3} {B = TotalPushoutPath×∙}
2 (S³→TotalPushoutPath× , refl)))
-- We get a sequence on the right form π₃S³ → π₃S² → π₃ Pushout → Unit
S³→S²→Pushout→Unit'' :
Exact4 (π'Gr 2 (S₊∙ 3)) (π'Gr 2 (S₊∙ 2)) (π'Gr 2 coFib-fold∘W∙) UnitGroup₀
(compGroupHom π₃S³→π₃P
(compGroupHom
(π'∘∙Hom 2 TotalPushoutPath×∙→P) (π'∘∙Hom 2 (fst , refl))))
(π'∘∙Hom 2 inr∙)
(→UnitHom (π'Gr 2 coFib-fold∘W∙))
S³→S²→Pushout→Unit'' =
extendExact4Surjective _ _ _ _ _ _ _ _ _
isSurjective-π₃S³→π₃TotalPushoutPath×
(extendExact4Surjective _ _ _ _ _ _ _ _ _
((sElim (λ _ → isProp→isSet squash₁)
(λ f → ∣ ∣ (λ x → (tt , fst f x .fst) , sym (fst f x .snd))
, ΣPathP ((ΣPathP (refl , cong fst (snd f)))
, λ j i → snd f j .snd (~ i)) ∣₂
, cong ∣_∣₂ (ΣPathP (refl , sym (rUnit _))) ∣₁)))
P→S²→Pushout→P')
-- Step 3: We need to show that the map π₃S³ → π₃S² in the above sequence
-- indeed comes from fold∘W
tripleComp≡ :
(compGroupHom π₃S³→π₃P
(compGroupHom
(π'∘∙Hom 2 TotalPushoutPath×∙→P) (π'∘∙Hom 2 (fst , refl))))
≡ π'∘∙Hom 2 (fold∘W , refl)
tripleComp≡ =
Σ≡Prop (λ _ → isPropIsGroupHom _ _)
(funExt (sElim (λ _ → isSetPathImplicit)
λ f → cong ∣_∣₂ (ΣPathP (refl , (cong (_∙ refl)
(λ j → cong fst (rUnit (cong (fst TotalPushoutPath×∙→P)
(rUnit (cong S³→TotalPushoutPath× (snd f)) (~ j))) (~ j))))))))
-- We finally get the correct sequence
S³→S²→Pushout→Unit :
Exact4 (π'Gr 2 (S₊∙ 3)) (π'Gr 2 (S₊∙ 2)) (π'Gr 2 coFib-fold∘W∙) UnitGroup₀
(π'∘∙Hom 2 (fold∘W , refl))
(π'∘∙Hom 2 inr∙)
(→UnitHom (π'Gr 2 coFib-fold∘W∙))
S³→S²→Pushout→Unit =
subst
(λ F → Exact4 (π'Gr 2 (S₊∙ 3)) (π'Gr 2 (S₊∙ 2)) (π'Gr 2 coFib-fold∘W∙) UnitGroup₀
F (π'∘∙Hom 2 inr∙)
(→UnitHom (π'Gr 2 coFib-fold∘W∙)))
tripleComp≡
S³→S²→Pushout→Unit''
-- We need to throw around some pushouts
module _ where
Pushout-coFibW-fold⋁≃coFib-fold∘W :
Pushout {B = (Pushout W (λ _ → tt))} inl fold⋁ ≃ fst coFib-fold∘W∙
Pushout-coFibW-fold⋁≃coFib-fold∘W = compEquiv
(compEquiv pushoutSwitchEquiv
(isoToEquiv (PushoutDistr.PushoutDistrIso fold⋁ W λ _ → tt)))
pushoutSwitchEquiv
coFibW≅coFibW' : Pushout W (λ _ → tt) ≃ cofibW S¹ S¹ base base
coFibW≅coFibW' = pushoutEquiv W (λ _ → tt) joinTo⋁ (λ _ → tt)
(isoToEquiv (invIso (IsoSphereJoin 1 1)))
(idEquiv _)
(idEquiv _)
refl
refl
Pushout-coFibW-fold⋁≃Pushout⋁↪fold⋁ :
Pushout {B = (Pushout W (λ _ → tt))} inl fold⋁
≃ fst (Pushout⋁↪fold⋁∙ (S₊∙ 2))
Pushout-coFibW-fold⋁≃Pushout⋁↪fold⋁ = pushoutEquiv inl _ ⋁↪ fold⋁
(idEquiv _)
(compEquiv coFibW≅coFibW'
(isoToEquiv (invIso (Iso-Susp×Susp-cofibJoinTo⋁ S¹ S¹ base base))))
(idEquiv _)
(Susp×Susp→cofibW≡ S¹ S¹ base base)
refl
Pushout-coFibW-fold⋁≃Pushout⋁↪fold⋁∙ :
(Pushout {B = (Pushout W (λ _ → tt))} inl fold⋁ , inr north)
≃∙ (Pushout⋁↪fold⋁∙ (S₊∙ 2))
fst Pushout-coFibW-fold⋁≃Pushout⋁↪fold⋁∙ =
Pushout-coFibW-fold⋁≃Pushout⋁↪fold⋁
snd Pushout-coFibW-fold⋁≃Pushout⋁↪fold⋁∙ =
sym (push (inl north))
π₄S³≅π₃coFib-fold∘W∙ : GroupEquiv (π'Gr 3 (S₊∙ 3)) (π'Gr 2 coFib-fold∘W∙)
π₄S³≅π₃coFib-fold∘W∙ =
compGroupEquiv
(GroupIso→GroupEquiv
(compGroupIso
(π'Gr≅πGr 3 (S₊∙ 3))
(compGroupIso
π₄S³≅π₃PushS²
(invGroupIso (π'Gr≅πGr 2 (Pushout⋁↪fold⋁∙ (S₊∙ 2)))))))
(compGroupEquiv
(invGroupEquiv (π'Iso 2 Pushout-coFibW-fold⋁≃Pushout⋁↪fold⋁∙))
(π'Iso 2 (Pushout-coFibW-fold⋁≃coFib-fold∘W , sym (push north))))
-- We get the iso
-- For type checking reasons, let's first prove it for the abstract
-- definition of ℤ/_
-- To get everything on the same form as in Brunerie's thesis, we
-- first need the following:
fold∘W≡Whitehead :
fst (π'∘∙Hom 2 (fold∘W , refl)) ∣ idfun∙ (S₊∙ 3) ∣₂
≡ ∣ [ idfun∙ (S₊∙ 2) ∣ idfun∙ (S₊∙ 2) ] ∣₂
fold∘W≡Whitehead =
cong ∣_∣₂ (ΣPathP (funExt (main ∘ sphere→Join 1 1) , refl))
where
main : (x : _) → fold⋁ (joinTo⋁ {A = S₊∙ 1} {B = S₊∙ 1} x)
≡ fst [ idfun∙ (Susp S¹ , north)
∣ idfun∙ (Susp S¹ , north) ]-pre x
main (inl x) = refl
main (inr x) = refl
main (push a b i) j = help j i
where
help : cong (fold⋁ ∘ joinTo⋁ {A = S₊∙ 1} {B = S₊∙ 1}) (push a b)
≡ (σS b ∙ refl) ∙ σS a ∙ refl
help = cong-∙∙ fold⋁ _ _ _
∙ doubleCompPath≡compPath _ _ _
∙ cong₂ _∙_ (rUnit _) (sym (lUnit (σS a)) ∙ rUnit (σS a))
BrunerieIsoAbstract : GroupEquiv (π'Gr 3 (S₊∙ 3)) (abstractℤGroup/ Brunerie)
BrunerieIsoAbstract =
compGroupEquiv π₄S³≅π₃coFib-fold∘W∙
(invGroupEquiv
(GroupEquiv-abstractℤ/abs-gen
(π'Gr 2 (S₊∙ 3)) (π'Gr 2 (S₊∙ 2)) (π'Gr 2 coFib-fold∘W∙)
(GroupIso→GroupEquiv (invGroupIso (πₙ'Sⁿ≅ℤ 2)))
(invGroupEquiv hopfInvariantEquiv)
(π'∘∙Hom 2 (fold∘W , refl))
_
S³→S²→Pushout→Unit Brunerie main))
where
mainPath :
fst (π'∘∙Hom 2 (fold∘W , refl))
(Iso.inv (fst (πₙ'Sⁿ≅ℤ 2)) 1)
≡ [ ∣ idfun∙ (S₊∙ 2) ∣₂ ∣ ∣ idfun∙ (S₊∙ 2) ∣₂ ]π'
mainPath = cong (fst (π'∘∙Hom 2 (fold∘W , refl)))
(cong (Iso.inv (fst (πₙ'Sⁿ≅ℤ 2))) (sym (πₙ'Sⁿ≅ℤ-idfun∙ 2))
∙ (Iso.ret (fst (πₙ'Sⁿ≅ℤ 2)) ∣ idfun∙ (S₊∙ 3) ∣₂))
∙ fold∘W≡Whitehead
main : _ ≡ Brunerie
main i = abs (HopfInvariant-π' 0 (mainPath i))
-- And, finally, we get the actual iso
-- (as in Corollary 3.4.5 in Brunerie's thesis)
BrunerieIso : GroupEquiv (π'Gr 3 (S₊∙ 3)) (ℤGroup/ Brunerie)
BrunerieIso =
compGroupEquiv BrunerieIsoAbstract (abstractℤ/≅ℤ Brunerie)-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Papers.Pi4S3.html`
{-
Please do not move this file. Changes should only be made if
necessary.
This file contains pointers to the code examples and main results from
the paper:
Formalizing π₄(S³) ≅ ℤ/2ℤ and Computing a Brunerie Number in Cubical Agda
-}
-- The "--safe" flag ensures that there are no postulates or
-- unfinished goals
{-# OPTIONS --cubical #-}
module Cubical.Papers.Pi4S3 where
-- Misc.
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Univalence
open import Cubical.Foundations.Pointed
open import Cubical.Foundations.HLevels
open import Cubical.Data.Int hiding (_+_)
open import Cubical.Data.Nat
open import Cubical.Data.Nat.Order
open import Cubical.Data.Sum
open import Cubical.Data.Sigma
-- 2
open import Cubical.Data.Bool as Boolean
open import Cubical.HITs.S1 as Circle
open import Cubical.Foundations.Prelude as Prelude
open import Cubical.HITs.Susp as Suspensions
open import Cubical.HITs.Sn as Spheres
hiding (S) renaming (S₊ to S)
open import Cubical.HITs.Sn.Multiplication as SMult
open import Cubical.HITs.Pushout as Pushouts
open import Cubical.HITs.Wedge as Wedges
open import Cubical.HITs.Join as Joins
open import Cubical.HITs.Susp as Suspension
open import Cubical.HITs.PropositionalTruncation as PT
open import Cubical.HITs.Truncation as Trunc
open import Cubical.Homotopy.HSpace as H-Spaces
open import Cubical.Homotopy.Group.Base as HomotopyGroups
open import Cubical.Homotopy.Group.LES as LES
open import Cubical.Homotopy.HopfInvariant.HopfMap as HopfMap
open import Cubical.Homotopy.Hopf as HopfFibration
open import Cubical.Homotopy.Connected as Connectedness
open S¹Hopf
open import Cubical.Homotopy.Freudenthal as Freudenthal
open import Cubical.Homotopy.Group.PinSn as Stable
open import Cubical.Homotopy.Group.Pi3S2 as π₃S²
-- 3
open import Cubical.Homotopy.Group.Pi4S3.S3PushoutIso as James₁
open import Cubical.Homotopy.Group.Pi4S3.S3PushoutIso2 as James₂
open import Cubical.HITs.S2 as Sphere
open import Cubical.Homotopy.Whitehead as Whitehead
open import Cubical.Homotopy.BlakersMassey
module BM = BlakersMassey□
open BM
open import Cubical.Homotopy.Group.Pi4S3.BrunerieNumber as BNumber
hiding (W)
-- 5
open import Cubical.ZCohomology.Base as cohom
open import Cubical.ZCohomology.GroupStructure as cohomGr
open import Cubical.ZCohomology.Properties as cohomProps
open import Cubical.ZCohomology.RingStructure.CupProduct as cup
open import Cubical.ZCohomology.MayerVietorisUnreduced as MayerVietoris
open import Cubical.Homotopy.HopfInvariant.Base as HI
open import Cubical.Homotopy.HopfInvariant.Homomorphism as HI-hom
open import Cubical.Homotopy.HopfInvariant.Brunerie as HI-β
open import Cubical.ZCohomology.Gysin as GysinSeq
open import Cubical.Homotopy.Group.Pi4S3.Summary as π₄S³
hiding (π)
open import Cubical.ZCohomology.RingStructure.RingLaws as cupLaws
-- 6
open import Cubical.Homotopy.Group.Pi4S3.DirectProof as Direct
-- II. HOMOTOPY TYPE THEORY IN Cubical Agda
-- Booleans
open Boolean using (Bool)
-- S¹
open Circle using (S¹)
-- Non-dependent paths and refl
open Prelude using (_≡_ ; refl)
-- funExt, funExt⁻, cong
open Prelude using (funExt; funExt⁻; cong)
-- transport and dependent paths
open Prelude using (transport ; PathP)
-- cirlce-indution
open Circle using (elim)
-- suspension
open Suspensions using (Susp)
-- spheres
open Spheres using (S₊)
-- pushouts
open Pushouts using (Pushout)
-- wedge sums
open Wedges using (_⋁_)
-- joins
open Joins using (join)
-- cofibres
open Pushouts using (cofib)
-- ∇ and i∨
open Wedges using (fold⋁ ; ⋁↪)
∇ = fold⋁
i∨ = ⋁↪
-- propositional and general truncation
-- note that the indexing is off by 2!
open PT using (∥_∥₁)
open Trunc using (∥_∥_)
-- h-spaces
open H-Spaces using (HSpace)
-- homotopy groups (function and loop space definition, respectively)
-- Note that the indexing is off by 1.
open HomotopyGroups using (π'Gr ; πGr)
-- πLES (Proposition 1)
module ExactSeq = πLES
-- σ (definition 3)
open Suspensions using (toSusp)
σ = toSusp
-- Definition 4 and Proposition (Hopf map),
-- Phrased somewhat differently in the paper.
open HopfMap using (HopfMap)
open S¹Hopf using (IsoS³TotalHopf)
-- Lemma 1 (connectedness of spheres)
-- Note that the indexing is off by 2.
open Spheres using (sphereConnected)
-- Proposition 3 (πₙSᵐ vanishishing for n < m)
isContr-πₙSᵐ-low : (n m : ℕ) → n < m → isContr (π n (S₊∙ m))
isContr-πₙSᵐ-low n m l =
transport (cong isContr (sym (ua h)))
(∣ const∙ (S₊∙ n) _ ∣₂
, ST.elim (λ _ → isOfHLevelPath 2 squash₂ _ _)
λ f → refl)
where
open import Cubical.HITs.SetTruncation as ST
isContrUnit : isContr Unit
isContrUnit = tt , λ _ → refl
con-lem : isConnected (2 + n) (S₊ m)
con-lem = isConnectedSubtr (suc (suc n)) (fst l)
(subst (λ n → isConnected n (S₊ m))
(sym (+-suc (fst l) (suc n) ∙ cong suc (snd l)))
(sphereConnected m))
h : π n (S₊∙ m) ≃ π' n (Unit , tt)
h = compEquiv (isoToEquiv (πTruncIso n))
(compEquiv (pathToEquiv (cong (π n)
(ua∙ (isoToEquiv (isContr→Iso (con-lem) isContrUnit)) refl)))
(pathToEquiv (cong ∥_∥₂ (isoToPath (IsoΩSphereMap n)))))
-- Theorem 1 (Freudenthal Suspension Theorem)
open Freudenthal using (isConnectedσ) -- formalized by Evan Cavallo
-- Corollary 1 (πₙSⁿ≅ℤ with identity as generator)
open Stable using (πₙ'Sⁿ≅ℤ ; πₙ'Sⁿ≅ℤ-idfun∙)
-- Proposition 4 and Corollary 2 (πₙSⁿ≅ℤ with identity as generator)
open π₃S² using (π₃S²≅ℤ ; π₂S³-gen-by-HopfMap)
------ IV. THE BRUNERIE NUMBER ------
{- The formalization of this part does not
follow the paper exactly. For instance, Lemma 2 is baked into a more
specific elimination principle for J₂. For this reason, we only give
the crucial results here -}
---- A. The James construction ----
-- Lemma 3 (the family of automorphisms on ∥J₂S²∥₃
open James₁ using (∥Pushout⋁↪fold⋁S²∥₅≃∥Pushout⋁↪fold⋁S²∥₅)
---- B. Formalization of the James construction ----
-- S²-HIT
open Sphere using (S²)
-- Definition 5: J₂S²
open James₁ using (Pushout⋁↪fold⋁S₊2)
-- encode, decode
open James₁ using (encode ; decode)
-- Proposition 7: Ω ∥S³∥₄ ≃ ∥J₂S²∥₃
open James₁ using (IsoΩ∥SuspS²∥₅∥Pushout⋁↪fold⋁S²∥₅)
---- C. Formalization of the James construction ----
-- Proposition 8: Sⁿ * Sᵐ ≃ Sⁿ⁺ᵐ⁺¹
open SMult using (IsoSphereJoin)
-- Definition 6: W + whitehead product
W = joinTo⋁
open Whitehead using ([_∣_])
-- Theorem 3 is omitted as it is used implicitly in the proof of the main result
-- Blakers-Massey
open BM using (isConnected-toPullback) -- formalized primarily (in a different form) by Kang Rongji
-- Definition 7: The Brunerie number (note that, in the formalization
-- we have worked defined β as the image of the Hopf Invariant
-- directly)
open BNumber using (Brunerie)
-- Corollary 3: π₄S³ ≅ ℤ/βℤ
open BNumber using (BrunerieIso)
---
------ V. BRUNERIE'S PROOF PART 2 ------
---- A. Cohomology Theory / B. Formalization of Chapter 5----
-- All formalizations marked with (BLM22) are borrowed from Brunerie,
-- Ljungström, and Mörtberg, “Synthetic Integral Cohomology in Cubical
-- Agda"
-- Eilenberg-MacLane spaces and cohomology groups (BLM22)
open cohom using (coHomK)
open cohomGr using (coHomGr)
-- addition (BLM22)
open cohomGr using (_+ₖ_)
-- the cup product (BLM22)
open cup using (_⌣ₖ_ ; _⌣_)
-- Kₙ ≃ ΩKₙ₊₁ (BLM22)
open cohomProps using (Kn≃ΩKn+1)
-- Mayer Vietoris (BLM22)
open MV using ( Ker-i⊂Im-d ; Im-d⊂Ker-i
; Ker-Δ⊂Im-i ; Im-i⊂Ker-Δ
; Ker-d⊂Im-Δ ; Im-Δ⊂Ker-d)
-- Lemma 4 (cohomology of cofibers S³ → S²)
open HI using (Hopfβ-Iso)
-- Definition 8 (Hopf Invariant)
open HI using (HopfInvariant-π')
-- Proposition 9 (The Hopf invariant is a homomorphism)
open HI-hom using (GroupHom-HopfInvariant-π')
-- Proposition 10 (The Hopf invariant of the Brunerie element is ±2)
open HI-β using (Brunerie'≡2)
-- Lemma 5 -- only included for presentation, omitted from frmalization
---- C. The Gysin Sequence / B. Formalization of the Gysin Sequence
-- Proposition 11 (Gysin sequence)
open Gysin using (Im-⌣e⊂Ker-p ; Ker-p⊂Im-⌣e
; Im-Susp∘ϕ⊂Ker-⌣e ; Ker-⌣e⊂Im-Susp∘ϕ
; Im-ϕ∘j⊂Ker-p ; Ker-p⊂Im-ϕ∘j)
-- Proposition 12 : CP² fibration
-- Indirect, but see in particular
open HopfMap using (fibr)
-- Proposition 13 : Iterated Hopf Construction.
-- Indirect, but see in particular:
open Hopf using (joinIso₂)
-- Proposition 14 : ∣ HI hopf ∣ ≡ 1
open HopfMap using (HopfInvariant-HopfMap)
-- Theorem 5: π₄S³≅ℤ/2ℤ
open π₄S³ using (π₄S³≃ℤ/2ℤ)
-- Lemma 6: (BLM22)
open cupLaws using (assoc-helper)
-- proof that e₂ : H²(CP²) is a generator by computation
-- (the field with refl is where the computation happens)
open HopfMap using (isGenerator≃ℤ-e)
------ VI. SIMPLIFIED NEW PROOF AND COMPUTATION OF A BRUNERIE NUMBER ------
-- A relatively detailed accound of the proof is given in the formalization:
open Direct
-- Note that the numbering of the ηs is shifted, with
-- η₁ being ∣ ∇ ∘ W ∣, η₂ being η₁ and η₃ being η₂.
open Direct using (η₁ ; η₂ ; η₃)
-- computation of η₂: the alternative definition and the computation
open Direct using (η₃' ; computerIsoη₃)-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Papers.Synthetic.html`
module Cubical.Papers.Synthetic where
-- Cubical synthetic homotopy theory
-- Mörtberg and Pujet, „Cubical synthetic homotopy theory“.
-- https://dl.acm.org/doi/abs/10.1145/3372885.3373825
-- 2.1
import Agda.Builtin.Cubical.Path as Path
import Cubical.Foundations.Prelude as Prelude
-- 2.2
import Agda.Primitive.Cubical as PrimitiveCubical
import Cubical.Data.Bool as Bool
import Cubical.Core.Primitives as CorePrimitives
-- 2.3
import Cubical.HITs.S1 as S1
-- 2.4
import Cubical.Foundations.Equiv as Equiv
import Cubical.Core.Glue as CoreGlue
import Cubical.Foundations.Univalence as Univalence
-- 3.
import Cubical.HITs.Torus as T2
-- 3.1
import Cubical.Data.Int as Int
import Cubical.Data.Int.Properties as IntProp
import Cubical.Foundations.Isomorphism as Isomorphism
-- 4.1
import Cubical.HITs.Susp as Suspension
import Cubical.HITs.Sn as Sn
import Agda.Builtin.Nat as BNat
import Agda.Builtin.Bool as BBool
import Cubical.Foundations.GroupoidLaws as GroupoidLaws
import Cubical.HITs.S2 as S2
import Cubical.HITs.S3 as S3
-- 4.2
import Cubical.HITs.Pushout as Push
import Cubical.HITs.Pushout.Properties as PushProp
-- 4.3
import Cubical.HITs.Join as Join
import Cubical.HITs.Join.Properties as JoinProp
-- 5.
import Cubical.Homotopy.Hopf as Hopf
--------------------------------------------------------------------------------
-- 2. Cubical Agda
-- 2.1 The Interval and Path Types
-- 2.2 Transport and Composition
-- 2.3 Higher Inductive Types
-- 2.4 Glue Types and Univalence
--------------------------------------------------------------------------------
-- 2.1 The Interval and Path Types
open Path using (PathP) public
open Prelude using (_≡_ ; refl ; funExt) public
open Prelude renaming (sym to _⁻¹) public
-- 2.2 Transport and Composition
open Prelude using (transport ; subst ; J ; JRefl) public
open PrimitiveCubical using (Partial) public
open Bool using (Bool ; true ; false) public
partialBool : ∀ i → Partial (i ∨ ~ i) Bool
partialBool i = λ {(i = i1) → true
; (i = i0) → false}
open CorePrimitives using (inS ; outS ; hcomp) public
open Prelude using (_∙_) public
-- 2.3 Higher Inductive Types
open S1 using (S¹ ; base ; loop) public
double : S¹ → S¹
double base = base
double (loop i) = (loop ∙ loop) i
-- 2.4 Glue Types and Univalence
open Equiv using (idEquiv) public
open CoreGlue using (Glue) public
open Univalence using (ua) public
--------------------------------------------------------------------------------
-- 3. The Circle and Torus
-- 3.1 The Loop Spaces of the Circle and Torus
--------------------------------------------------------------------------------
open T2 using ( Torus ; point ; line1 ; line2 ; square
; t2c ; c2t ; c2t-t2c ; t2c-c2t ; Torus≡S¹×S¹)
-- 3.1 The Loop Spaces of the Circle and Torus
open S1 using (ΩS¹) public
open T2 using (ΩTorus) public
open Int using (pos ; negsuc) renaming (ℤ to Int) public
open IntProp using (sucPathℤ) public
open S1 using (helix ; winding) public
-- Examples computing the winding numbers of the circle
_ : winding (loop ∙ loop ∙ loop) ≡ pos 3
_ = refl
_ : winding ((loop ⁻¹) ∙ loop ∙ (loop ⁻¹)) ≡ negsuc 0
_ = refl
open S1 renaming (intLoop to loopn) public
open S1 renaming (windingℤLoop to winding-loopn) public
open S1 using (encode ; decode ; decodeEncode ; ΩS¹≡ℤ) public
open Isomorphism using (isoToPath ; iso) public
-- Notation of the paper, current notation under ΩS¹≡Int
ΩS¹≡Int' : ΩS¹ ≡ Int
ΩS¹≡Int' = isoToPath (iso winding loopn
winding-loopn (decodeEncode base))
open T2 using (ΩTorus≡ℤ×ℤ ; windingTorus) public
-- Examples at the end of section 3.
_ : windingTorus (line1 ∙ line2) ≡ (pos 1 , pos 1)
_ = refl
_ : windingTorus ((line1 ⁻¹) ∙ line2 ∙ line1) ≡ (pos 0 , pos 1)
_ = refl
--------------------------------------------------------------------------------
-- 4. Suspension, Spheres and Pushouts
-- 4.1 Suspension
-- 4.2 Pushouts and the 3 × 3 Lemma
-- 4.3 The Join and S³
--------------------------------------------------------------------------------
-- 4.1 Suspension
open Suspension using (Susp ; north ; south ; merid) public
open Sn using (S₊) public
open Suspension using ( SuspBool→S¹ ; S¹→SuspBool
; SuspBool→S¹→SuspBool
; S¹→SuspBool→S¹) public
-- Deprecated version of S₊
open BNat renaming (Nat to ℕ) hiding (_*_) public
open CorePrimitives renaming (Type to Set) public
open BBool using (Bool) public
-- At the time the paper was published, Set was used instead of Type
_-sphere : ℕ → Set
0 -sphere = Bool
(suc n) -sphere = Susp (n -sphere)
-- Lemma 4.1. The (1)-sphere is equal to the circle S1.
open BBool using (true ; false) public
-- Deprecated version of SuspBool→S¹
s2c : 1 -sphere → S¹
s2c north = base
s2c south = base
s2c (merid true i) = loop i
s2c (merid false i) = base -- (loop ⁻¹) i
-- Deprecated version of S¹→SuspBool
c2s : S¹ → 1 -sphere
c2s base = north
c2s (loop i) = (merid true ∙ (merid false ⁻¹)) i
open GroupoidLaws using (rUnit) public
-- Deprecated version of SuspBool→S¹→SuspBool
s2c-c2s : ∀ (p : S¹) → s2c (c2s p) ≡ p
s2c-c2s base = refl
s2c-c2s (loop i) j = rUnit loop (~ j) i
h1 : I → I → 1 -sphere
h1 i j = merid false (i ∧ j)
h2 : I → I → 1 -sphere
h2 i j = hcomp (λ k → λ { (i = i0) → north
; (i = i1) → merid false (j ∨ ~ k)
; (j = i1) → merid true i })
(merid true i)
-- Deprecated version of S¹→SuspBool→S¹
c2s-s2c : ∀ (t : 1 -sphere) → c2s (s2c t) ≡ t
c2s-s2c north j = north
c2s-s2c south j = merid false j
c2s-s2c (merid true i) j = h2 i j
c2s-s2c (merid false i) j = merid false (i ∧ j)
-- Notation of the paper, current notation under S¹≡SuspBool
-- Proof of Lemma 4.1
1-sphere≡S¹ : 1 -sphere ≡ S¹
1-sphere≡S¹ = isoToPath (iso s2c c2s s2c-c2s c2s-s2c)
-- Definitions of S2 and S3
open S2 using (S²) public
open S3 using (S³) public
-- 4.2 Pushouts and the 3 × 3 Lemma
open Push using (Pushout) public
-- 3x3-span is implemented as a record
open PushProp using (3x3-span) public
open 3x3-span using (f□1) public
-- The rest of the definitions inside the 3x3-lemma
-- A□0-A○□ , A□○-A○□ ...
open 3x3-span using (3x3-lemma) public
-- 4.3 The Join and S³
open Join renaming (join to Join) using (S³≡joinS¹S¹) public
open JoinProp using (join-assoc) public
--------------------------------------------------------------------------------
-- 5. The Hopf Fibration
--------------------------------------------------------------------------------
-- rot (denoted by _·_ here) in the paper is substituted by a rot and rotLoop in S1
open S1 using (_·_ ; rotLoop) public
open Hopf.S¹Hopf renaming ( HopfSuspS¹ to Hopf
; JoinS¹S¹→TotalHopf to j2h
; TotalHopf→JoinS¹S¹ to h2j)
using (HopfS²) public
open S1 renaming (rotInv-1 to lem-rot-inv) public-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Relation.Binary.Base.html`
module Cubical.Relation.Binary.Base where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.HLevels
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Equiv.Fiberwise
open import Cubical.Functions.Embedding
open import Cubical.Functions.Logic using (_⊔′_)
open import Cubical.Data.Empty as ⊥
open import Cubical.Data.Sigma
open import Cubical.Data.Sum.Base as ⊎
open import Cubical.HITs.SetQuotients.Base
open import Cubical.HITs.PropositionalTruncation as ∥₁
open import Cubical.Relation.Nullary.Base
open import Cubical.Induction.WellFounded
private
variable
ℓA ℓ≅A ℓA' ℓ≅A' : Level
Rel : ∀ {ℓa ℓb} (A : Type ℓa) (B : Type ℓb) (ℓ' : Level) → Type (ℓ-max (ℓ-max ℓa ℓb) (ℓ-suc ℓ'))
Rel A B ℓ' = A → B → Type ℓ'
PropRel : ∀ {ℓ} (A B : Type ℓ) (ℓ' : Level) → Type (ℓ-max ℓ (ℓ-suc ℓ'))
PropRel A B ℓ' = Σ[ R ∈ Rel A B ℓ' ] ∀ a b → isProp (R a b)
idPropRel : ∀ {ℓ} (A : Type ℓ) → PropRel A A ℓ
idPropRel A .fst a a' = ∥ a ≡ a' ∥₁
idPropRel A .snd _ _ = squash₁
invPropRel : ∀ {ℓ ℓ'} {A B : Type ℓ}
→ PropRel A B ℓ' → PropRel B A ℓ'
invPropRel R .fst b a = R .fst a b
invPropRel R .snd b a = R .snd a b
compPropRel : ∀ {ℓ ℓ' ℓ''} {A B C : Type ℓ}
→ PropRel A B ℓ' → PropRel B C ℓ'' → PropRel A C (ℓ-max ℓ (ℓ-max ℓ' ℓ''))
compPropRel R S .fst a c = ∥ Σ[ b ∈ _ ] (R .fst a b × S .fst b c) ∥₁
compPropRel R S .snd _ _ = squash₁
graphRel : ∀ {ℓ} {A B : Type ℓ} → (A → B) → Rel A B ℓ
graphRel f a b = f a ≡ b
module HeterogenousRelation {ℓ ℓ' : Level} {A B : Type ℓ} (R : Rel A B ℓ') where
isUniversalRel : Type (ℓ-max ℓ ℓ')
isUniversalRel = (a : A) (b : B) → R a b
module BinaryRelation {ℓ ℓ' : Level} {A : Type ℓ} (R : Rel A A ℓ') where
isRefl : Type (ℓ-max ℓ ℓ')
isRefl = (a : A) → R a a
isRefl' : Type (ℓ-max ℓ ℓ')
isRefl' = {a : A} → R a a
isIrrefl : Type (ℓ-max ℓ ℓ')
isIrrefl = (a : A) → ¬ R a a
isSym : Type (ℓ-max ℓ ℓ')
isSym = (a b : A) → R a b → R b a
isAsym : Type (ℓ-max ℓ ℓ')
isAsym = (a b : A) → R a b → ¬ R b a
isAntisym : Type (ℓ-max ℓ ℓ')
isAntisym = (a b : A) → R a b → R b a → a ≡ b
isTrans : Type (ℓ-max ℓ ℓ')
isTrans = (a b c : A) → R a b → R b c → R a c
isTrans' : Type (ℓ-max ℓ ℓ')
isTrans' = {a b c : A} → R a b → R b c → R a c
-- Sum types don't play nicely with props, so we truncate
isCotrans : Type (ℓ-max ℓ ℓ')
isCotrans = (a b c : A) → R a b → R a c ⊔′ R b c
isWeaklyLinear : Type (ℓ-max ℓ ℓ')
isWeaklyLinear = (a b c : A) → R a b → R a c ⊔′ R c b
isConnected : Type (ℓ-max ℓ ℓ')
isConnected = (a b : A) → (¬ R a b) × (¬ R b a) → a ≡ b
isTotal : Type (ℓ-max ℓ ℓ')
isTotal = (a b : A) → R a b ⊔′ R b a
isIrrefl×isTrans→isAsym : isIrrefl × isTrans → isAsym
isIrrefl×isTrans→isAsym (irrefl , trans) a₀ a₁ Ra₀a₁ Ra₁a₀
= irrefl a₀ (trans a₀ a₁ a₀ Ra₀a₁ Ra₁a₀)
WellFounded→isIrrefl : WellFounded R → isIrrefl
WellFounded→isIrrefl well = WFI.induction well λ a f Raa → f a Raa Raa
isAsym→isIrrefl : isAsym → isIrrefl
isAsym→isIrrefl asym a Raa = asym a a Raa Raa
IrreflKernel : Rel A A (ℓ-max ℓ ℓ')
IrreflKernel a b = R a b × (¬ a ≡ b)
ReflClosure : Rel A A (ℓ-max ℓ ℓ')
ReflClosure a b = R a b ⊎ (a ≡ b)
SymKernel : Rel A A ℓ'
SymKernel a b = R a b × R b a
SymClosure : Rel A A ℓ'
SymClosure a b = R a b ⊎ R b a
AsymKernel : Rel A A ℓ'
AsymKernel a b = R a b × (¬ R b a)
NegationRel : Rel A A ℓ'
NegationRel a b = ¬ (R a b)
Dual : Rel A A ℓ'
Dual a b = R b a
module _
{ℓ'' : Level}
(P : Embedding A ℓ'')
where
private
subtype : Type ℓ''
subtype = (fst P)
toA : subtype → A
toA = fst (snd P)
InducedRelation : Rel subtype subtype ℓ'
InducedRelation a b = R (toA a) (toA b)
record isEquivRel : Type (ℓ-max ℓ ℓ') where
constructor equivRel
field
reflexive : isRefl
symmetric : isSym
transitive : isTrans
isUniversalRel→isEquivRel : HeterogenousRelation.isUniversalRel R → isEquivRel
isUniversalRel→isEquivRel u .isEquivRel.reflexive a = u a a
isUniversalRel→isEquivRel u .isEquivRel.symmetric a b _ = u b a
isUniversalRel→isEquivRel u .isEquivRel.transitive a _ c _ _ = u a c
isPropValued : Type (ℓ-max ℓ ℓ')
isPropValued = (a b : A) → isProp (R a b)
isSetValued : Type (ℓ-max ℓ ℓ')
isSetValued = (a b : A) → isSet (R a b)
isEffective : Type (ℓ-max ℓ ℓ')
isEffective =
(a b : A) → isEquiv (eq/ {R = R} a b)
isDecidable : Type (ℓ-max ℓ ℓ')
isDecidable = (a b : A) → Dec (R a b)
impliesIdentity : Type _
impliesIdentity = {a a' : A} → (R a a') → (a ≡ a')
isTight : Type _
isTight = (a b : A) → ¬ R a b → a ≡ b
inequalityImplies : Type _
inequalityImplies = (a b : A) → ¬ a ≡ b → R a b
-- the total space corresponding to the binary relation w.r.t. a
relSinglAt : (a : A) → Type (ℓ-max ℓ ℓ')
relSinglAt a = Σ[ a' ∈ A ] (R a a')
-- the statement that the total space is contractible at any a
contrRelSingl : Type (ℓ-max ℓ ℓ')
contrRelSingl = (a : A) → isContr (relSinglAt a)
isUnivalent : Type (ℓ-max ℓ ℓ')
isUnivalent = (a a' : A) → (R a a') ≃ (a ≡ a')
contrRelSingl→isUnivalent : isRefl → contrRelSingl → isUnivalent
contrRelSingl→isUnivalent ρ c a a' = isoToEquiv i
where
h : isProp (relSinglAt a)
h = isContr→isProp (c a)
aρa : relSinglAt a
aρa = a , ρ a
Q : (y : A) → a ≡ y → _
Q y _ = R a y
i : Iso (R a a') (a ≡ a')
Iso.fun i r = cong fst (h aρa (a' , r))
Iso.inv i = J Q (ρ a)
Iso.sec i = J (λ y p → cong fst (h aρa (y , J Q (ρ a) p)) ≡ p)
(J (λ q _ → cong fst (h aρa (a , q)) ≡ refl)
(J (λ α _ → cong fst α ≡ refl) refl
(isProp→isSet h _ _ refl (h _ _)))
(sym (JRefl Q (ρ a))))
Iso.ret i r = J (λ w β → J Q (ρ a) (cong fst β) ≡ snd w)
(JRefl Q (ρ a)) (h aρa (a' , r))
isUnivalent→contrRelSingl : isUnivalent → contrRelSingl
isUnivalent→contrRelSingl u a = q
where
abstract
f : (x : A) → a ≡ x → R a x
f x p = invEq (u a x) p
t : singl a → relSinglAt a
t (x , p) = x , f x p
q : isContr (relSinglAt a)
q = isOfHLevelRespectEquiv 0 (t , totalEquiv _ _ f λ x → invEquiv (u a x) .snd)
(isContrSingl a)
EquivRel : ∀ {ℓ} (A : Type ℓ) (ℓ' : Level) → Type (ℓ-max ℓ (ℓ-suc ℓ'))
EquivRel A ℓ' = Σ[ R ∈ Rel A A ℓ' ] BinaryRelation.isEquivRel R
EquivPropRel : ∀ {ℓ} (A : Type ℓ) (ℓ' : Level) → Type (ℓ-max ℓ (ℓ-suc ℓ'))
EquivPropRel A ℓ' = Σ[ R ∈ PropRel A A ℓ' ] BinaryRelation.isEquivRel (R .fst)
record RelIso {A : Type ℓA} (_≅_ : Rel A A ℓ≅A)
{A' : Type ℓA'} (_≅'_ : Rel A' A' ℓ≅A') : Type (ℓ-max (ℓ-max ℓA ℓA') (ℓ-max ℓ≅A ℓ≅A')) where
constructor reliso
field
fun : A → A'
inv : A' → A
sec : (a' : A') → fun (inv a') ≅' a'
ret : (a : A) → inv (fun a) ≅ a
open BinaryRelation
RelIso→Iso : {A : Type ℓA} {A' : Type ℓA'}
(_≅_ : Rel A A ℓ≅A) (_≅'_ : Rel A' A' ℓ≅A')
(uni : impliesIdentity _≅_) (uni' : impliesIdentity _≅'_)
(f : RelIso _≅_ _≅'_)
→ Iso A A'
Iso.fun (RelIso→Iso _ _ _ _ f) = RelIso.fun f
Iso.inv (RelIso→Iso _ _ _ _ f) = RelIso.inv f
Iso.sec (RelIso→Iso _ _ uni uni' f) a'
= uni' (RelIso.sec f a')
Iso.ret (RelIso→Iso _ _ uni uni' f) a
= uni (RelIso.ret f a)
isIrreflIrreflKernel : ∀{ℓ ℓ'} {A : Type ℓ} (R : Rel A A ℓ') → isIrrefl (IrreflKernel R)
isIrreflIrreflKernel _ _ (_ , ¬a≡a) = ¬a≡a refl
isReflReflClosure : ∀{ℓ ℓ'} {A : Type ℓ} (R : Rel A A ℓ') → isRefl (ReflClosure R)
isReflReflClosure _ _ = inr refl
isSymSymKernel : ∀{ℓ ℓ'} {A : Type ℓ} (R : Rel A A ℓ') → isSym (SymKernel R)
isSymSymKernel _ _ _ (Rab , Rba) = Rba , Rab
isSymSymClosure : ∀{ℓ ℓ'} {A : Type ℓ} (R : Rel A A ℓ') → isSym (SymClosure R)
isSymSymClosure _ _ _ (inl Rab) = inr Rab
isSymSymClosure _ _ _ (inr Rba) = inl Rba
isAsymAsymKernel : ∀ {ℓ ℓ'} {A : Type ℓ} (R : Rel A A ℓ') → isAsym (AsymKernel R)
isAsymAsymKernel _ _ _ (Rab , _) (_ , ¬Rab) = ¬Rab Rab-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Structures.Maybe.html`
{-
Maybe structure: X ↦ Maybe (S X)
-}
{-# OPTIONS --no-exact-split #-}
module Cubical.Structures.Maybe where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Function
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.HLevels
open import Cubical.Foundations.SIP
open import Cubical.Functions.FunExtEquiv
open import Cubical.Data.Unit
open import Cubical.Data.Empty
open import Cubical.Data.Maybe
private
variable
ℓ ℓ₁ ℓ₁' : Level
MaybeRel : {A B : Type ℓ} (R : A → B → Type ℓ₁) → Maybe A → Maybe B → Type ℓ₁
MaybeRel R nothing nothing = Lift Unit
MaybeRel R nothing (just _) = Lift ⊥
MaybeRel R (just _) nothing = Lift ⊥
MaybeRel R (just x) (just y) = R x y
congMaybeRel : {A B : Type ℓ} {R : A → B → Type ℓ₁} {S : A → B → Type ℓ₁'}
→ (∀ x y → R x y ≃ S x y)
→ ∀ ox oy → MaybeRel R ox oy ≃ MaybeRel S ox oy
congMaybeRel e nothing nothing = Lift≃Lift (idEquiv _)
congMaybeRel e nothing (just _) = Lift≃Lift (idEquiv _)
congMaybeRel e (just _) nothing = Lift≃Lift (idEquiv _)
congMaybeRel e (just x) (just y) = e x y
module MaybePathP where
Code : (A : I → Type ℓ) → Maybe (A i0) → Maybe (A i1) → Type ℓ
Code A = MaybeRel (PathP A)
encodeRefl : {A : Type ℓ} → ∀ ox → Code (λ _ → A) ox ox
encodeRefl nothing = lift tt
encodeRefl (just _) = refl
encode : (A : I → Type ℓ) → ∀ ox oy → PathP (λ i → Maybe (A i)) ox oy → Code A ox oy
encode A ox oy p = transport (λ j → Code (λ i → A (i ∧ j)) ox (p j)) (encodeRefl ox)
decode : {A : I → Type ℓ} → ∀ ox oy → Code A ox oy → PathP (λ i → Maybe (A i)) ox oy
decode nothing nothing p i = nothing
decode (just _) (just _) p i = just (p i)
decodeEncodeRefl : {A : Type ℓ} (ox : Maybe A) → decode ox ox (encodeRefl ox) ≡ refl
decodeEncodeRefl nothing = refl
decodeEncodeRefl (just _) = refl
decodeEncode : {A : I → Type ℓ} → ∀ ox oy p → decode ox oy (encode A ox oy p) ≡ p
decodeEncode {A = A} ox oy p =
transport
(λ k →
decode _ _ (transp (λ j → Code (λ i → A (i ∧ j ∧ k)) ox (p (j ∧ k))) (~ k) (encodeRefl ox))
≡ (λ i → p (i ∧ k)))
(decodeEncodeRefl ox)
encodeDecode : (A : I → Type ℓ) → ∀ ox oy c → encode A ox oy (decode ox oy c) ≡ c
encodeDecode A nothing nothing c = refl
encodeDecode A (just x) (just y) c =
transport
(λ k →
encode (λ i → A (i ∧ k)) _ _ (decode (just x) (just (c k)) (λ i → c (i ∧ k)))
≡ (λ i → c (i ∧ k)))
(transportRefl _)
Code≃PathP : {A : I → Type ℓ} → ∀ ox oy → Code A ox oy ≃ PathP (λ i → Maybe (A i)) ox oy
Code≃PathP {A = A} ox oy = isoToEquiv isom
where
isom : Iso _ _
isom .Iso.fun = decode ox oy
isom .Iso.inv = encode _ ox oy
isom .Iso.sec = decodeEncode ox oy
isom .Iso.ret = encodeDecode A ox oy
-- Structured isomorphisms
MaybeStructure : (S : Type ℓ → Type ℓ₁) → Type ℓ → Type ℓ₁
MaybeStructure S X = Maybe (S X)
MaybeEquivStr : {S : Type ℓ → Type ℓ₁}
→ StrEquiv S ℓ₁' → StrEquiv (MaybeStructure S) ℓ₁'
MaybeEquivStr ι (X , ox) (Y , oy) e = MaybeRel (λ x y → ι (X , x) (Y , y) e) ox oy
maybeUnivalentStr : {S : Type ℓ → Type ℓ₁} (ι : StrEquiv S ℓ₁')
→ UnivalentStr S ι → UnivalentStr (MaybeStructure S) (MaybeEquivStr ι)
maybeUnivalentStr ι θ {X , ox} {Y , oy} e =
compEquiv
(congMaybeRel (λ x y → θ {X , x} {Y , y} e) ox oy)
(MaybePathP.Code≃PathP ox oy)
maybeEquivAction : {S : Type ℓ → Type ℓ₁}
→ EquivAction S → EquivAction (MaybeStructure S)
maybeEquivAction α e = congMaybeEquiv (α e)
maybeTransportStr : {S : Type ℓ → Type ℓ₁} (α : EquivAction S)
→ TransportStr α → TransportStr (maybeEquivAction α)
maybeTransportStr _ τ e nothing = refl
maybeTransportStr _ τ e (just x) = cong just (τ e x)-- SOURCE URL: `https://agda.github.io/cubical/Cubical.Structures.Record.html`
{-
Automatically generating proofs of UnivalentStr for records
-}
{-# OPTIONS --no-exact-split #-}
module Cubical.Structures.Record where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Function
open import Cubical.Foundations.HLevels
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.SIP
open import Cubical.Foundations.Structure
open import Cubical.Foundations.Univalence
open import Cubical.Data.Sigma
open import Cubical.Data.Nat
open import Cubical.Data.List as List
open import Cubical.Data.Vec as Vec
open import Cubical.Data.Bool
open import Cubical.Data.Maybe
open import Cubical.Data.Sum
open import Cubical.Structures.Auto
import Cubical.Structures.Macro as M
import Agda.Builtin.Reflection as R
open import Cubical.Reflection.Base
-- Magic number
private
FUEL = 10000
-- Types for specifying inputs to the tactics
data AutoFieldSpec : Typeω where
autoFieldSpec : ∀ {ℓ ℓ₁ ℓ₂} (R : Type ℓ → Type ℓ₁) {S : Type ℓ → Type ℓ₂}
→ ({X : Type ℓ} → R X → S X)
→ AutoFieldSpec
module _ {ℓ ℓ₁ ℓ₁'} where
mutual
data AutoFields (R : Type ℓ → Type ℓ₁) (ι : StrEquiv R ℓ₁') : Typeω
where
fields: : AutoFields R ι
_data[_∣_] : (fs : AutoFields R ι)
→ ∀ {ℓ₂ ℓ₂'} {S : Type ℓ → Type ℓ₂} {ι' : StrEquiv S ℓ₂'}
→ (f : {X : Type ℓ} → R X → S X)
→ ({A B : TypeWithStr ℓ R} {e : typ A ≃ typ B} → ι A B e → ι' (map-snd f A) (map-snd f B) e)
→ AutoFields R ι
_prop[_∣_] : (fs : AutoFields R ι)
→ ∀ {ℓ₂} {P : (X : Type ℓ) → GatherFields fs X → Type ℓ₂}
→ ({X : Type ℓ} (r : R X) → P X (projectFields fs r))
→ isPropProperty R ι fs P
→ AutoFields R ι
GatherFieldsLevel : {R : Type ℓ → Type ℓ₁} {ι : StrEquiv R ℓ₁'}
→ AutoFields R ι
→ Level
GatherFieldsLevel fields: = ℓ-zero
GatherFieldsLevel (_data[_∣_] fs {ℓ₂ = ℓ₂} _ _) = ℓ-max (GatherFieldsLevel fs) ℓ₂
GatherFieldsLevel (_prop[_∣_] fs {ℓ₂ = ℓ₂} _ _) = ℓ-max (GatherFieldsLevel fs) ℓ₂
GatherFields : {R : Type ℓ → Type ℓ₁} {ι : StrEquiv R ℓ₁'}
(dat : AutoFields R ι)
→ Type ℓ → Type (GatherFieldsLevel dat)
GatherFields fields: X = Unit
GatherFields (_data[_∣_] fs {S = S} _ _) X = GatherFields fs X × S X
GatherFields (_prop[_∣_] fs {P = P} _ _) X =
Σ[ s ∈ GatherFields fs X ] (P X s)
projectFields : {R : Type ℓ → Type ℓ₁} {ι : StrEquiv R ℓ₁'}
(fs : AutoFields R ι)
→ {X : Type ℓ} → R X → GatherFields fs X
projectFields fields: = _
projectFields (fs data[ f ∣ _ ]) r = projectFields fs r , f r
projectFields (fs prop[ f ∣ _ ]) r = projectFields fs r , f r
isPropProperty : ∀ {ℓ₂} (R : Type ℓ → Type ℓ₁)
(ι : StrEquiv R ℓ₁')
(fs : AutoFields R ι)
(P : (X : Type ℓ) → GatherFields fs X → Type ℓ₂)
→ Type (ℓ-max (ℓ-suc ℓ) (ℓ-max ℓ₁ ℓ₂))
isPropProperty R ι fs P =
{X : Type ℓ} (r : R X) → isProp (P X (projectFields fs r))
data AutoRecordSpec : Typeω where
autoRecordSpec : (R : Type ℓ → Type ℓ₁) (ι : StrEquiv R ℓ₁')
→ AutoFields R ι
→ AutoRecordSpec
-- Some reflection utilities
private
tApply : R.Term → List (R.Arg R.Term) → R.Term
tApply t l = R.def (quote idfun) (R.unknown v∷ t v∷ l)
tStrMap : R.Term → R.Term → R.Term
tStrMap A f = R.def (quote map-snd) (f v∷ A v∷ [])
tStrProj : R.Term → R.Name → R.Term
tStrProj A sfield = tStrMap A (R.def sfield [])
Fun : ∀ {ℓ ℓ'} → Type ℓ → Type ℓ' → Type (ℓ-max ℓ ℓ')
Fun A B = A → B
-- Helper functions used in the generated univalence proof
private
pathMap : ∀ {ℓ ℓ'} {S : I → Type ℓ} {T : I → Type ℓ'} (f : {i : I} → S i → T i)
{x : S i0} {y : S i1} → PathP S x y → PathP T (f x) (f y)
pathMap f p i = f (p i)
-- Property field helper functions
module _
{ℓ ℓ₁ ℓ₁' ℓ₂}
(R : Type ℓ → Type ℓ₁) -- Structure record
(ι : StrEquiv R ℓ₁') -- Equivalence record
(fs : AutoFields R ι) -- Prior fields
(P : (X : Type ℓ) → GatherFields fs X → Type ℓ₂) -- Property type
(f : {X : Type ℓ} (r : R X) → P X (projectFields fs r)) -- Property projection
where
prev = projectFields fs
Prev = GatherFields fs
PropHelperCenterType : Type _
PropHelperCenterType =
(A B : TypeWithStr ℓ R) (e : A .fst ≃ B .fst)
(p : PathP (λ i → Prev (ua e i)) (prev (A .snd)) (prev (B .snd)))
→ PathP (λ i → P (ua e i) (p i)) (f (A .snd)) (f (B .snd))
PropHelperContractType : PropHelperCenterType → Type _
PropHelperContractType c =
(A B : TypeWithStr ℓ R) (e : A .fst ≃ B .fst)
{p₀ : PathP (λ i → Prev (ua e i)) (prev (A .snd)) (prev (B .snd))}
(q : PathP (λ i → R (ua e i)) (A .snd) (B .snd))
(p : p₀ ≡ (λ i → prev (q i)))
→ PathP (λ k → PathP (λ i → P (ua e i) (p k i)) (f (A .snd)) (f (B .snd)))
(c A B e p₀)
(λ i → f (q i))
PropHelperType : Type _
PropHelperType =
Σ PropHelperCenterType PropHelperContractType
derivePropHelper : isPropProperty R ι fs P → PropHelperType
derivePropHelper propP .fst A B e p =
isOfHLevelPathP' 0 (propP _) (f (A .snd)) (f (B .snd)) .fst
derivePropHelper propP .snd A B e q p =
isOfHLevelPathP' 0 (isOfHLevelPathP 1 (propP _) _ _) _ _ .fst
-- Build proof of univalence from an isomorphism
module _ {ℓ ℓ₁ ℓ₁'} (S : Type ℓ → Type ℓ₁) (ι : StrEquiv S ℓ₁') where
fwdShape : Type _
fwdShape =
(A B : TypeWithStr ℓ S) (e : typ A ≃ typ B) → ι A B e → PathP (λ i → S (ua e i)) (str A) (str B)
bwdShape : Type _
bwdShape =
(A B : TypeWithStr ℓ S) (e : typ A ≃ typ B) → PathP (λ i → S (ua e i)) (str A) (str B) → ι A B e
fwdBwdShape : fwdShape → bwdShape → Type _
fwdBwdShape fwd bwd =
(A B : TypeWithStr ℓ S) (e : typ A ≃ typ B) → ∀ p → fwd A B e (bwd A B e p) ≡ p
bwdFwdShape : fwdShape → bwdShape → Type _
bwdFwdShape fwd bwd =
(A B : TypeWithStr ℓ S) (e : typ A ≃ typ B) → ∀ r → bwd A B e (fwd A B e r) ≡ r
-- The implicit arguments A,B in UnivalentStr make some things annoying so let's avoid them
ExplicitUnivalentStr : Type _
ExplicitUnivalentStr =
(A B : TypeWithStr _ S) (e : typ A ≃ typ B) → ι A B e ≃ PathP (λ i → S (ua e i)) (str A) (str B)
explicitUnivalentStr : (fwd : fwdShape) (bwd : bwdShape)
→ fwdBwdShape fwd bwd → bwdFwdShape fwd bwd
→ ExplicitUnivalentStr
explicitUnivalentStr fwd bwd fwdBwd bwdFwd A B e = isoToEquiv isom
where
open Iso
isom : Iso _ _
isom .fun = fwd A B e
isom .inv = bwd A B e
isom .sec = fwdBwd A B e
isom .ret = bwdFwd A B e
ExplicitUnivalentDesc : ∀ ℓ {ℓ₁ ℓ₁'} → (d : M.Desc ℓ ℓ₁ ℓ₁') → Type _
ExplicitUnivalentDesc _ d =
ExplicitUnivalentStr (M.MacroStructure d) (M.MacroEquivStr d)
explicitUnivalentDesc : ∀ ℓ {ℓ₁ ℓ₁'} → (d : M.Desc ℓ ℓ₁ ℓ₁') → ExplicitUnivalentDesc ℓ d
explicitUnivalentDesc _ d A B e = M.MacroUnivalentStr d e
-- Internal record specification type
private
record TypedTerm : Type where
field
type : R.Term
term : R.Term
record InternalDatumField : Type where
field
sfield : R.Name -- name of structure field
efield : R.Name -- name of equivalence field
record InternalPropField : Type where
field
sfield : R.Name -- name of structure field
InternalField : Type
InternalField = InternalDatumField ⊎ InternalPropField
record InternalSpec (A : Type) : Type where
field
srec : R.Term -- structure record type
erec : R.Term -- equivalence record type
fields : List (InternalField × A) -- in reverse order
open TypedTerm
open InternalDatumField
open InternalPropField
-- Parse a field and record specifications
private
findName : R.Term → R.TC R.Name
findName (R.def name _) = R.returnTC name
findName (R.lam R.hidden (R.abs _ t)) = findName t
findName t = R.typeError (R.strErr "Not a name + spine: " ∷ R.termErr t ∷ [])
parseFieldSpec : R.Term → R.TC (R.Term × R.Term × R.Term × R.Term)
parseFieldSpec (R.con (quote autoFieldSpec) (ℓ h∷ ℓ₁ h∷ ℓ₂ h∷ R v∷ S h∷ f v∷ [])) =
R.reduce ℓ >>= λ ℓ →
R.returnTC (ℓ , ℓ₂ , S , f)
parseFieldSpec t =
R.typeError (R.strErr "Malformed field specification: " ∷ R.termErr t ∷ [])
parseSpec : R.Term → R.TC (InternalSpec TypedTerm)
parseSpec (R.con (quote autoRecordSpec) (ℓ h∷ ℓ₁ h∷ ℓ₁' h∷ srecTerm v∷ erecTerm v∷ fs v∷ [])) =
parseFields fs >>= λ fs' →
R.returnTC λ { .srec → srecTerm ; .erec → erecTerm ; .fields → fs'}
where
open InternalSpec
parseFields : R.Term → R.TC (List (InternalField × TypedTerm))
parseFields (R.con (quote fields:) _) = R.returnTC []
parseFields (R.con (quote _data[_∣_])
(ℓ h∷ ℓ₁ h∷ ℓ₁' h∷ R h∷ ι h∷ fs v∷ ℓ₂ h∷ ℓ₂' h∷ S h∷ ι' h∷ sfieldTerm v∷ efieldTerm v∷ []))
=
R.reduce ℓ >>= λ ℓ →
findName sfieldTerm >>= λ sfieldName →
findName efieldTerm >>= λ efieldName →
buildDesc FUEL ℓ ℓ₂ S >>= λ d →
let
f : InternalField × TypedTerm
f = λ
{ .fst → inl λ { .sfield → sfieldName ; .efield → efieldName }
; .snd .type → R.def (quote ExplicitUnivalentDesc) (ℓ v∷ d v∷ [])
; .snd .term → R.def (quote explicitUnivalentDesc) (ℓ v∷ d v∷ [])
}
in
liftTC (f ∷_) (parseFields fs)
parseFields (R.con (quote _prop[_∣_])
(ℓ h∷ ℓ₁ h∷ ℓ₁' h∷ R h∷ ι h∷ fs v∷ ℓ₂ h∷ P h∷ fieldTerm v∷ prop v∷ []))
=
findName fieldTerm >>= λ fieldName →
let
p : InternalField × TypedTerm
p = λ
{ .fst → inr λ { .sfield → fieldName }
; .snd .type →
R.def (quote PropHelperType) (srecTerm v∷ erecTerm v∷ fs v∷ P v∷ fieldTerm v∷ [])
; .snd .term →
R.def (quote derivePropHelper) (srecTerm v∷ erecTerm v∷ fs v∷ P v∷ fieldTerm v∷ prop v∷ [])
}
in
liftTC (p ∷_) (parseFields fs)
parseFields t = R.typeError (R.strErr "Malformed autoRecord specification (1): " ∷ R.termErr t ∷ [])
parseSpec t = R.typeError (R.strErr "Malformed autoRecord specification (2): " ∷ R.termErr t ∷ [])
-- Build a proof of univalence from an InternalSpec
module _ (spec : InternalSpec ℕ) where
open InternalSpec spec
private
fwdDatum : Vec R.Term 4 → R.Term → InternalDatumField × ℕ → R.Term
fwdDatum (A ∷ B ∷ e ∷ streq ∷ _) i (dat , n) =
R.def (quote equivFun)
(tApply (v n) (tStrProj A (dat .sfield) v∷ tStrProj B (dat .sfield) v∷ e v∷ [])
v∷ R.def (dat .efield) (streq v∷ [])
v∷ i
v∷ [])
fwdProperty : Vec R.Term 4 → R.Term → R.Term → InternalPropField × ℕ → R.Term
fwdProperty (A ∷ B ∷ e ∷ streq ∷ _) i prevPath prop =
R.def (quote fst) (v (prop .snd) v∷ A v∷ B v∷ e v∷ prevPath v∷ i v∷ [])
bwdClause : Vec R.Term 4 → InternalDatumField × ℕ → R.Clause
bwdClause (A ∷ B ∷ e ∷ q ∷ _) (dat , n) =
R.clause [] (R.proj (dat .efield) v∷ [])
(R.def (quote invEq)
(tApply
(v n)
(tStrProj A (dat .sfield) v∷ tStrProj B (dat .sfield) v∷ e v∷ [])
v∷ R.def (quote pathMap) (R.def (dat .sfield) [] v∷ q v∷ [])
v∷ []))
fwdBwdDatum : Vec R.Term 4 → R.Term → R.Term → InternalDatumField × ℕ → R.Term
fwdBwdDatum (A ∷ B ∷ e ∷ q ∷ _) j i (dat , n) =
R.def (quote secEq)
(tApply
(v n)
(tStrProj A (dat .sfield) v∷ tStrProj B (dat .sfield) v∷ e v∷ [])
v∷ R.def (quote pathMap) (R.def (dat .sfield) [] v∷ q v∷ [])
v∷ j v∷ i
v∷ [])
fwdBwdProperty : Vec R.Term 4 → (j i prevPath : R.Term) → InternalPropField × ℕ → R.Term
fwdBwdProperty (A ∷ B ∷ e ∷ q ∷ _) j i prevPath prop =
R.def (quote snd) (v (prop .snd) v∷ A v∷ B v∷ e v∷ q v∷ prevPath v∷ j v∷ i v∷ [])
bwdFwdClause : Vec R.Term 4 → R.Term → InternalDatumField × ℕ → R.Clause
bwdFwdClause (A ∷ B ∷ e ∷ streq ∷ _) j (dat , n) =
R.clause [] (R.proj (dat .efield) v∷ [])
(R.def (quote retEq)
(tApply
(v n)
(tStrProj A (dat .sfield) v∷ tStrProj B (dat .sfield) v∷ e v∷ [])
v∷ R.def (dat .efield) (streq v∷ [])
v∷ j
v∷ []))
makeVarsFrom : {n : ℕ} → ℕ → Vec R.Term n
makeVarsFrom {zero} k = []
makeVarsFrom {suc n} k = v (n + k) ∷ (makeVarsFrom k)
fwd : R.Term
fwd =
vlam "A" (vlam "B" (vlam "e" (vlam "streq" (vlam "i" (R.pat-lam body [])))))
where
-- input list is in reverse order
fwdClauses : ℕ → List (InternalField × ℕ) → List (R.Name × R.Term)
fwdClauses k [] = []
fwdClauses k ((inl f , n) ∷ fs) =
fwdClauses k fs
∷ʳ (f .sfield , fwdDatum (makeVarsFrom k) (v 0) (map-snd (4 + k +_) (f , n)))
fwdClauses k ((inr p , n) ∷ fs) =
fwdClauses k fs
∷ʳ (p .sfield , fwdProperty (makeVarsFrom k) (v 0) prevPath (map-snd (4 + k +_) (p , n)))
where
prevPath =
vlam "i"
(List.foldl
(λ t (_ , t') → R.con (quote _,_) (t v∷ t' v∷ []))
(R.con (quote tt) [])
(fwdClauses (suc k) fs))
body =
List.map (λ (n , t) → R.clause [] [ varg (R.proj n) ] t) (fwdClauses 1 fields)
bwd : R.Term
bwd =
vlam "A" (vlam "B" (vlam "e" (vlam "q" (R.pat-lam (bwdClauses fields) []))))
where
-- input is in reverse order
bwdClauses : List (InternalField × ℕ) → List R.Clause
bwdClauses [] = []
bwdClauses ((inl f , n) ∷ fs) =
bwdClauses fs
∷ʳ bwdClause (makeVarsFrom 0) (map-snd (4 +_) (f , n))
bwdClauses ((inr p , n) ∷ fs) = bwdClauses fs
fwdBwd : R.Term
fwdBwd =
vlam "A" (vlam "B" (vlam "e" (vlam "q" (vlam "j" (vlam "i" (R.pat-lam body []))))))
where
-- input is in reverse order
fwdBwdClauses : ℕ → List (InternalField × ℕ) → List (R.Name × R.Term)
fwdBwdClauses k [] = []
fwdBwdClauses k ((inl f , n) ∷ fs) =
fwdBwdClauses k fs
∷ʳ (f .sfield , fwdBwdDatum (makeVarsFrom k) (v 1) (v 0) (map-snd (4 + k +_) (f , n)))
fwdBwdClauses k ((inr p , n) ∷ fs) =
fwdBwdClauses k fs
∷ʳ ((p .sfield , fwdBwdProperty (makeVarsFrom k) (v 1) (v 0) prevPath (map-snd (4 + k +_) (p , n))))
where
prevPath =
vlam "j"
(vlam "i"
(List.foldl
(λ t (_ , t') → R.con (quote _,_) (t v∷ t' v∷ []))
(R.con (quote tt) [])
(fwdBwdClauses (2 + k) fs)))
body = List.map (λ (n , t) → R.clause [] [ varg (R.proj n) ] t) (fwdBwdClauses 2 fields)
bwdFwd : R.Term
bwdFwd =
vlam "A" (vlam "B" (vlam "e" (vlam "streq" (vlam "j" (R.pat-lam (bwdFwdClauses fields) [])))))
where
bwdFwdClauses : List (InternalField × ℕ) → List R.Clause
bwdFwdClauses [] = []
bwdFwdClauses ((inl f , n) ∷ fs) =
bwdFwdClauses fs
∷ʳ bwdFwdClause (makeVarsFrom 1) (v 0) (map-snd (5 +_) (f , n))
bwdFwdClauses ((inr _ , n) ∷ fs) = bwdFwdClauses fs
univalentRecord : R.Term
univalentRecord =
R.def (quote explicitUnivalentStr)
(R.unknown v∷ R.unknown v∷ fwd v∷ bwd v∷ fwdBwd v∷ bwdFwd v∷ [])
macro
autoFieldEquiv : R.Term → R.Term → R.Term → R.Term → R.TC Unit
autoFieldEquiv spec A B hole =
(R.reduce spec >>= parseFieldSpec) >>= λ (ℓ , ℓ₂ , S , f) →
buildDesc FUEL ℓ ℓ₂ S >>= λ d →
R.unify hole (R.def (quote M.MacroEquivStr) (d v∷ tStrMap A f v∷ tStrMap B f v∷ []))
autoUnivalentRecord : R.Term → R.Term → R.TC Unit
autoUnivalentRecord t hole =
(R.reduce t >>= parseSpec) >>= λ spec →
-- R.typeError (R.strErr "WOW: " ∷ R.termErr (main spec) ∷ [])
R.unify (main spec) hole
where
module _ (spec : InternalSpec TypedTerm) where
open InternalSpec spec
mapUp : ∀ {ℓ ℓ'} {A : Type ℓ} {B : Type ℓ'} → (ℕ → A → B) → ℕ → List A → List B
mapUp f _ [] = []
mapUp f n (x ∷ xs) = f n x ∷ mapUp f (suc n) xs
closureSpec : InternalSpec ℕ
closureSpec .InternalSpec.srec = srec
closureSpec .InternalSpec.erec = erec
closureSpec .InternalSpec.fields = mapUp (λ n → map-snd (λ _ → n)) 0 fields
closure : R.Term
closure =
iter (List.length fields) (vlam "") (univalentRecord closureSpec)
env : List (R.Arg R.Term)
env = List.map (varg ∘ term ∘ snd) (List.rev fields)
closureTy : R.Term
closureTy =
List.foldr
(λ ty cod → R.def (quote Fun) (ty v∷ cod v∷ []))
(R.def (quote ExplicitUnivalentStr) (srec v∷ erec v∷ []))
(List.map (type ∘ snd) (List.rev fields))
main : R.Term
main = R.def (quote idfun) (closureTy v∷ closure v∷ env)