{- 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 -} {-# OPTIONS --cubical --no-import-sorts --safe #-} module Cubical.Foundations.Equiv where open import Cubical.Foundations.Function open import Cubical.Foundations.Prelude open import Cubical.Foundations.Isomorphism open import Cubical.Foundations.GroupoidLaws open import Cubical.Foundations.Equiv.Base public open import Cubical.Data.Sigma.Base private variable ℓ' ℓ'' : Level A B C D : Type 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)) equivEq : {e f : A B} (h : e .fst f .fst) e f equivEq {e = e} {f = f} h = λ i (h i) , isProp→PathP i isPropIsEquiv (h i)) (e .snd) (f .snd) i 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 module _ (w : A B) where invEq : B A invEq = invIsEq (snd w) secEq : section invEq (w .fst) secEq = retIsEq (snd w) retEq : retract invEq (w .fst) retEq = 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 rightInv (equivToIso e) = retEq e leftInv (equivToIso e) = secEq 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 -- TODO: there should be a direct proof of this that doesn't use equivToIso compEquiv : A B B C A C compEquiv f g = isoToEquiv (compIso (equivToIso f) (equivToIso g)) 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 (secEq e)) invEquiv-is-linv : (e : A B) compEquiv (invEquiv e) e idEquiv B invEquiv-is-linv e = equivEq (funExt (retEq 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 a+ .fst .fst = a+ .lower LiftEquiv .snd .equiv-proof _ .fst .snd = refl LiftEquiv .snd .equiv-proof _ .snd (_ , p) i .fst = p (~ i) .lower LiftEquiv .snd .equiv-proof _ .snd (_ , p) i .snd j = p (~ i j) 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 .rightInv e = equivEq refl isom .leftInv _ = 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.rightInv g = funExt λ b retEq k _ cong g (retEq h b) equiv→Iso h k .Iso.leftInv f = funExt λ a secEq k _ cong f (secEq h a) equiv→ : (A B) (C D) (A C) (B D) equiv→ h k = isoToEquiv (equiv→Iso h k) 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.rightInv g = equivEq (equiv→Iso h k .Iso.rightInv (equivFun g)) equivCompIso h k .Iso.leftInv f = equivEq (equiv→Iso h k .Iso.leftInv (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)