\import Equiv
\import Equiv.Fiber
\import Equiv.Univalence
\import Function.Meta
\import Logic.Unique
\import Homotopy.Fibration
\import Paths
\import Paths.Meta
\record HAEquiv \extends QEquiv
| f_ret_f=f_sec_f : \Pi (x : A) -> pmap f (ret_f x) = f_sec (f x)
\where {
\protected \func coh_f_sec (s : Section) (r : \Pi (y : s.B) -> s (s.ret y) = y) (y : s.B) : s (s.ret y) = y
=> inv (r (s (s.ret y))) *> pmap s (s.ret_f (s.ret y)) *> r y
\protected \func coh_f_ret_f=f_sec_f (s : Section) (r : \Pi (y : s.B) -> s (s.ret y) = y) (x : s.A) : pmap s (s.ret_f x) = coh_f_sec s r (s x)
=> inv $ rotatePathLeft $
pmap s (s.ret_f (s.ret (s x))) *> r (s x) ==< pmap (pmap s __ *> r (s x)) (homotopy_app-comm (\lam x => s.ret (s x)) s.ret_f x) >==
pmap (\lam x => s (s.ret (s x))) (s.ret_f x) *> r (s x) ==< homotopy-isNatural (\lam y => s (s.ret y)) (\lam y => y) r (pmap s (s.ret_f x)) >==
r (s (s.ret (s x))) *> pmap s (s.ret_f x) `qed
\use \coerce fromQEquiv (e : QEquiv) : HAEquiv \cowith
| Section => e
| f_sec => coh_f_sec e e.f_sec
| f_ret_f=f_sec_f => coh_f_ret_f=f_sec_f e e.f_sec
\lemma levelProp {A B : \Type} {f : A -> B} : isProp (HAEquiv f)
=> \lam e e' =>
\let
| T1' (r : Retraction f) (x : A) =>
(r.sec (f x), r.f_sec (f x)) = {Fib f (f x)} (x,idp)
| T1 (r : Retraction f) (x : A) =>
\Sigma (p : r.sec (f x) = x) (pmap f p = r.f_sec (f x))
| T1'=T1 (r : Retraction f) (x : A) : T1' r x = T1 r x =>
Equiv-to-= (Fib.equiv (f x) (r.sec (f x), r.f_sec (f x)) (x,idp))
| T1'-isContr (r : Retraction f) (x : A) : Contr (T1' r x) =>
isProp=>PathContr (Fib f (f x)) (isContr=>isProp (Equiv=>contrFibers e (f x))) _ _
| T1-isContr (r : Retraction f) (x : A) : Contr (T1 r x) =>
rewriteI (T1'=T1 r x) (T1'-isContr r x)
| T2 => \Sigma (r : Retraction f) (\Pi (x : A) -> T1 r x)
| T2-isContr : Contr T2 => sigma-Contr (\Pi (x : A) -> T1 __ x)
(Retraction.isContr e)
(\lam r => pi-Contr (T1 r) (T1-isContr r))
| E : T2 = HAEquiv f => path (iso (\lam (t : T2) => \new HAEquiv f {
| ret => sec {t.1}
| f_sec => f_sec {t.1}
| ret_f x => (t.2 x).1
| f_ret_f=f_sec_f x => (t.2 x).2
}) (\lam (r : HAEquiv f) => (\new Retraction f r.sec r.f_sec, \lam x => (r.ret_f x, r.f_ret_f=f_sec_f x)))
(\lam t2 => idp) (\lam (hae : HAEquiv f) => idp {HAEquiv f hae.ret hae.ret_f hae.f_sec hae.f_ret_f=f_sec_f}))
\in isContr=>isProp (rewriteI E T2-isContr) e e'
}