\import Equiv
\import Equiv.HalfAdjoint
\import Homotopy.Connected
\import Homotopy.Cube
\import Homotopy.Join
\import Homotopy.Pointed
\import Homotopy.Pushout
\import Homotopy.Sphere
\import Homotopy.Sphere.Circle
\import Homotopy.Suspension
\import Logic
\import Paths
\import Paths.Meta
\class HSpace \extends Pointed
| \infixl 7 * : E -> E -> E
| base-left (x : E) : base * x = x
| base-right (x : E) : x * base = x
\class HSpaceConn \extends HSpace, Connected0
-- | For every point {x} in a connected H-space, ``(x *)`` is an equivalence.
\lemma HSpaceConn-left {A : HSpaceConn} (x : A) => lem (isConn0 base x)
\where {
-- | If a point {x} in an H-space belongs to the same connected component as {base}, then ``(x *)`` is an equivalence.
\lemma lem {A : HSpace} {x : A} (c : TruncP (base = x)) : IsEquiv (x *) \elim c
| inP base=x => rewriteI (path (\lam i y => (inv (base-left y) *> pmap (* y) base=x) @ i)) (inP idEquiv)
}
-- | For every point {x} in a connected H-space, ``(* x)`` is an equivalence.
\lemma HSpaceConn-right {A : HSpaceConn} (x : A) => lem (isConn0 base x)
\where {
-- | If a point {x} in an H-space belongs to the same connected component as {base}, then ``(* x)`` is an equivalence.
\lemma lem {A : HSpace} {x : A} (c : TruncP (base = x)) : IsEquiv (__ * x) \elim c
| inP base=x => rewriteI (path (\lam i y => (inv (base-right y) *> pmap (y *) base=x) @ i)) (inP idEquiv)
}
\instance Circle_HSpace : HSpaceConn Sphere1
| base => base1
| * => mult
| base-left _ => idp
| base-right => mult-right
| isConn0 (base1) (base1) => inP idp
\where {
\open Sphere1(ploop)
\func circle-loop (y : Sphere1) : y = y
| base1 => path loop
| loop => Cube2.map ploop ploop ploop ploop (inv (<*_idp ploop) *> pmap (ploop <*) (inv (*>_inv ploop)))
\func mult (x y : Sphere1) : Sphere1 \elim x
| base1 => y
| loop => circle-loop y
\func mult-right (x : Sphere1) : mult x base1 = x
| base1 => idp
| loop i => idp
}
\instance Sphere1_HSpace : HSpaceConn (Sphere 1) => rewriteI (path (QEquiv_= Sphere1-equiv)) Circle_HSpace
\func hopf.{u} {A : HSpaceConn.{u}} (x : Susp A) : \Type u \elim x
| north => A
| south => A
| pglue a => QEquiv_= (IsEquiv.toQEquiv (HSpaceConn-left a))
\where
\func total-equiv.{u} {A : HSpaceConn.{u}} : (\Sigma (x : Susp A) (hopf x)) = Join A A
=> inv (PushoutData.flattening hopf) *> QEquiv_= {total A} total_join-equiv
\where {
\open PushoutData(ppglue)
\func total (A : HSpace) => PushoutData {\Sigma A A} {\Sigma (\Sigma) A} {\Sigma (\Sigma) A} (\lam p => ((),p.2)) (\lam p => ((), p.1 * p.2))
\func total_join-equiv {A : HSpaceConn} : QEquiv {total A} {Join A A} \cowith
| f => totalJoin
| ret => joinTotal
| ret_f => totalJoinTotal
| f_sec => joinTotalJoin
\func totalJoin {A : HSpace} (x : total A) : Join A A
| pinl (_,a) => jinl a
| pinr (_,a) => jinr a
| pglue (a,a') i => pglue (a', a * a') i
\func joinTotal {A : HSpaceConn} (x : Join A A) : total A
| jinl a => pinl ((),a)
| jinr a => pinr ((),a)
| pglue (a,a') =>
\let e : HAEquiv (* a) => IsEquiv.toQEquiv (HSpaceConn-right a)
\in ppglue (e.sec a', a) *> pmap (\lam x => pinr ((),x)) (e.f_sec a')
\func joinTotalJoin {A : HSpaceConn} (x : Join A A) : totalJoin (joinTotal x) = x
| jinl a => idp
| jinr a => idp
| pglue (a,a') i =>
\have | e : HAEquiv (* a) => IsEquiv.toQEquiv (HSpaceConn-right a)
| p =>
pmap totalJoin (ppglue (e.sec a', a) *> pmap (\lam y => pinr ((),y)) (e.f_sec a')) ==< pmap_*>-comm totalJoin (ppglue (e.sec a', a)) (pmap (\lam y => pinr ((),y)) (e.f_sec a')) >==
jglue a (e.sec a' * a) *> pmap jinr (e.f_sec a') ==< Jl (\lam x p => jglue a (e.sec a' * a) *> pmap jinr p = jglue a x) idp (e.f_sec a') >==
jglue a a' `qed
\in path (p @ __ @ i)
\func totalJoinTotal {A : HSpaceConn} (x : total A) : joinTotal (totalJoin x) = x \elim x
| pinl (_,a) => idp
| pinr (_,a) => idp
| pglue (a,a') i =>
\let | e : HAEquiv (* a') => IsEquiv.toQEquiv (HSpaceConn-right a')
| s => ppglue (e.ret (a * a'), a')
| p =>
s *> pmap (\lam y => pinr ((),y)) (e.f_sec (a * a')) ==< pmap (\lam p => s *> pmap (\lam y => pinr ((),y)) p) (inv (e.f_ret_f=f_sec_f a)) >==
s *> pmap (\lam y => pinr ((), y * a')) (e.ret_f a) ==< Jl (\lam x p => s *> pmap (\lam y => pinr ((), y * a')) p = ppglue (x,a')) idp (e.ret_f a) >==
ppglue (a,a') `qed
\in path (p @ __ @ i)
}
\func hopfS2 (x : Sphere 2) => hopf x
\where
\func total-equiv =>
(\Sigma (x : Sphere 2) (hopfS2 x)) ==< hopf.total-equiv >==
Join (Sphere 1) (Sphere 1) ==< Join_Sphere (Sphere 1) 1 >==
Sphere 3 `qed