\import Equiv
\import Equiv.Fiber
\import Function
\import Homotopy.HLevel
\import Homotopy.Fibration
\import Homotopy.Localization.Accessible
\import Homotopy.Localization.Connected
\import Homotopy.Localization.Universe
\import Logic
\import Logic.Unique
\import Paths
\import Paths.Meta
\func IsLocalEquiv.{u} {U : Universe.{u}} {A B : \Type u} (f : A -> B) => \Pi (Z : Local.{u}) -> IsEquiv {B -> Z} {A -> Z} (-o f)
\module Extension \where {
-- | The type of extensions of {g} along {f}
\func ext {A B C : \Type} (f : A -> B) (g : A -> C) => Fib (-o f) g
\func ext-equiv {A B C : \Type} (f : A -> B) (g : A -> C) : QEquiv {ext f g} {\Pi (b : B) -> \Sigma (c : C) (\Pi (a : A) -> f a = b -> g a = c)} \cowith
| f p b => (p.1 b, \lam a fa=b => inv (path ((p.2 @ __) a)) *> pmap p.1 fa=b)
| ret K => ((K __).1, path (\lam i a => inv ((K (f a)).2 a idp) @ i))
| ret_f b => path (\lam j => (b.1, path (\lam i a => inv_inv (path ((b.2 @ __) a)) @ j @ i)))
| f_sec K =>
\have p (b : B) (a : A) (q : f a = b) =>
Jl (\lam b' q' => inv (inv ((K (f a)).2 a idp)) *> pmap (K __).1 q' = (K b').2 a q') (inv_inv ((K (f a)).2 a idp)) q
\in path (\lam i b => ((K b).1, p b __ __ @ i))
\lemma contr-equiv.{u} {A B C : \Type u} (f : A -> B) (p : \Pi (g : A -> C) (b : B) -> Contr (\Sigma (c : C) (\Pi (a : A) -> f a = b -> g a = c)))
: IsEquiv {B -> C} {A -> C} (-o f)
=> contrFibers=>IsEquiv (\lam g => rewrite (path (QEquiv_= (ext-equiv f g))) (HLevels_-2-pi (\lam b => \Sigma (c : C) (\Pi (a : A) -> f a = b -> g a = c)) {0} (p g)))
}
\lemma connected_isLocalEquiv.{u} {U : Universe.{u}} {A B : \Type u} (f : A -> B) (conn : isConnectedMap f) : IsLocalEquiv f
=> \lam C => Extension.contr-equiv f (\lam g b =>
\let | G (x : Fib f b) => g x.1
| p c => \new QEquiv {(\lam _ => c) = G} {\Pi (a : A) -> f a = b -> g a = c} {
| f q a r => path ((inv q @ __) (a,r))
| ret h => inv (path (\lam i (x : Fib f b) => h x.1 x.2 @ i))
| ret_f q => inv_inv q
| f_sec h => path (\lam k a r => path (\lam i => (inv_inv (path (\lam j (x : Fib f b) => h x.1 x.2 @ j)) @ k @ i) (a,r)))
}
\in rewriteI (path (\lam i => \Sigma (c : C) (QEquiv_= (p c) i)))
(IsEquiv=>contrFibers (propExt.dir (nullTypeUniverse.localDesc (Fib f b) C) (conn b C)) G))
-- | A map between local types is a local equivalence if and only if it is an equivalence
\lemma localTypesEquiv.{u} {U : Universe.{u}} {A B : Local.{u}} (f : A -> B) : IsLocalEquiv f = IsEquiv f
=> propExt (dir f) (\lam e C => -o_IsEquiv e)
\where {
-- | A local equivalence between local types is an equivalence
\lemma dir.{u} {U : Universe.{u}} {A B : Local.{u}} (f : A -> B) (p : IsLocalEquiv f) : IsEquiv f
=> \let | g => IsEquiv.ret (p A) id
| g_f => IsEquiv.f_ret (p A)
| H => IsEquiv.ret (p B)
\in inP \new QEquiv {
| ret => g
| ret_f a => path (g_f __ a)
| f_sec b => path \lam i => (
f `o` g ==< inv (IsEquiv.ret_f (p B)) >==
H (f `o` g `o` f) ==< pmap (\lam t => H (f `o` t)) g_f >==
H f ==< IsEquiv.ret_f (p B) >==
id `qed) i b
}
}
\lemma localEquivMap.{u} {U : ReflUniverse.{u}} {A B : \Type u} (f : A -> B) : IsLocalEquiv f = IsEquiv (lmap f)
=> \have p (C : Local) : IsEquiv {LType B -> C} {LType A -> C} (-o (lmap f)) = IsEquiv {B -> C} {A -> C} (-o f)
=> IsEquiv.parallelEquiv ((localization B).local-univ C)
((localization A).local-univ C)
(\lam h => path (\lam i a => h (Localization.lift-prop (inL `o` f) a @ i)))
\in path (\lam i => \Pi (C : Local) -> inv (p C) i) *> localTypesEquiv (lmap f)