Spectral/homotopy/smash_adjoint.hlean
Floris van Doorn 013ca8d5f2 make progress on naturality of smash-pmap adjunction
The only fact left to be proven is a property (which is an equality of phomotopies) of the functorial action of the smash product
2017-03-03 17:43:03 -05:00

485 lines
20 KiB
Text

-- Authors: Floris van Doorn
-- in collaboration with Egbert, Stefano, Robin, Ulrik
import .smash
open bool pointed eq equiv is_equiv sum bool prod unit circle cofiber prod.ops wedge is_trunc
function red_susp unit sigma
namespace smash
variables {A B C : Type*}
definition pinl [constructor] (A : Type*) {B : Type*} (b : B) : A →* A ∧ B :=
begin
fapply pmap.mk,
{ intro a, exact smash.mk a b },
{ exact gluer' b pt }
end
definition pinl_phomotopy {A B : Type*} {b b' : B} (p : b = b') : pinl A b ~* pinl A b' :=
begin
fapply phomotopy.mk,
{ exact ap010 (pmap.to_fun ∘ pinl A) p },
{ induction p, apply idp_con }
end
definition pinr [constructor] {A : Type*} (B : Type*) (a : A) : B →* A ∧ B :=
begin
fapply pmap.mk,
{ intro b, exact smash.mk a b },
{ exact gluel' a pt }
end
definition smash_pmap_unit_pt [constructor] (A B : Type*)
: pinl A pt ~* pconst A (A ∧ B) :=
begin
fconstructor,
{ intro a, exact gluel' a pt },
{ rexact con.right_inv (gluel pt) ⬝ (con.right_inv (gluer pt))⁻¹ }
end
definition smash_pmap_unit [constructor] (A B : Type*) : B →* ppmap A (A ∧ B) :=
begin
fapply pmap.mk,
{ exact pinl A },
{ apply eq_of_phomotopy, exact smash_pmap_unit_pt A B }
end
definition smash_functor_pid_gluer' (A : Type*) {B C : Type*} (b : B) (f : B →* C) :
ap (smash_functor (pid A) f) (gluer' b pt) = gluer' (f b) (f pt) :=
begin
rexact functor_gluer'2 (@id A) f b pt
end
definition smash_functor_pid_pinl' [constructor] {A B C : Type*} (b : B) (f : B →* C) :
pinl A (f b) ~* smash_functor (pid A) f ∘* pinl A b :=
begin
fapply phomotopy.mk,
{ intro a, reflexivity },
{ refine !idp_con ⬝ _,
induction C with C c₀, induction f with f f₀, esimp at *,
induction f₀, rexact smash_functor_pid_gluer' A b (pmap_of_map f pt) }
end
definition smash_pmap_unit_pt_natural [constructor] (f : B →* C) :
smash_functor_pid_pinl' pt f ⬝*
pwhisker_left (smash_functor (pid A) f) (smash_pmap_unit_pt A B) ⬝*
pcompose_pconst (smash_functor (pid A) f) =
pinl_phomotopy (respect_pt f) ⬝* smash_pmap_unit_pt A C :=
begin
induction f with f f₀, induction C with C c₀, esimp at *,
induction f₀, refine _ ⬝ !refl_trans⁻¹,
refine !trans_refl ⬝ _,
fapply phomotopy_eq',
{ intro a, refine !idp_con ⬝ _,
rexact functor_gluel'2 (pid A) f a pt },
{ refine whisker_right_idp _ ⬝ph _,
refine ap (λx, _ ⬝ x) _ ⬝ph _,
rotate 1, rexact (functor_gluel'2_same (pid A) f pt),
-- refine whisker_left _ (!con.assoc ⬝ whisker_left _ !con.left_inv ⬝ !con_idp) ⬝ph _,
refine whisker_right _ !idp_con ⬝pv _,
refine !con.assoc⁻¹ ⬝ph _, apply whisker_bl,
refine !con.assoc⁻¹ ⬝ whisker_right _ _ ⬝pv _,
rotate 1, esimp, apply whisker_left_idp_con,
refine !con.assoc ⬝pv _, apply whisker_tl,
refine whisker_right _ !idp_con ⬝pv _,
refine whisker_right _ !whisker_right_idp ⬝pv _,
refine whisker_right _ (!idp_con ⬝ !ap02_con) ⬝ !con.assoc ⬝pv _,
apply whisker_tl,
apply vdeg_square,
refine whisker_right _ !ap_inv ⬝ _, apply inv_con_eq_of_eq_con,
unfold [smash_functor_pid_gluer'],
rexact functor_gluer'2_same (pmap_of_map id (Point A)) (pmap_of_map f pt) pt }
end
definition smash_pmap_unit_natural {A B C : Type*} (f : B →* C) :
smash_pmap_unit A C ∘* f ~*
ppcompose_left (smash_functor (pid A) f) ∘* smash_pmap_unit A B :=
begin
induction A with A a₀, induction B with B b₀, induction C with C c₀,
induction f with f f₀, esimp at *, induction f₀, fapply phomotopy_mk_ppmap,
{ esimp [pcompose], intro b, exact smash_functor_pid_pinl' b (pmap_of_map f b₀) },
{ refine ap (λx, _ ⬝* phomotopy_of_eq x) !respect_pt_pcompose ⬝ _
⬝ ap phomotopy_of_eq !respect_pt_pcompose⁻¹,
esimp, refine _ ⬝ ap phomotopy_of_eq !idp_con⁻¹,
refine _ ⬝ !phomotopy_of_eq_of_phomotopy⁻¹,
refine ap (λx, _ ⬝* phomotopy_of_eq (x ⬝ _)) !pcompose_eq_of_phomotopy ⬝ _,
refine ap (λx, _ ⬝* x) (!phomotopy_of_eq_con ⬝
ap011 phomotopy.trans !phomotopy_of_eq_of_phomotopy
!phomotopy_of_eq_of_phomotopy ⬝ !trans_refl) ⬝ _,
refine _ ⬝ smash_pmap_unit_pt_natural (pmap_of_map f b₀) ⬝ _,
{ exact !trans_refl⁻¹ },
{ exact !refl_trans }}
end
definition smash_pmap_counit_map [unfold 3] {A B : Type*} (af : A ∧ (ppmap A B)) : B :=
begin
induction af with a f a f,
{ exact f a },
{ exact pt },
{ exact pt },
{ reflexivity },
{ exact respect_pt f }
end
definition smash_pmap_counit [constructor] (A B : Type*) : A ∧ (ppmap A B) →* B :=
begin
fapply pmap.mk,
{ exact smash_pmap_counit_map },
{ reflexivity }
end
definition smash_pmap_counit_natural {A B C : Type*} (g : B →* C) :
g ∘* smash_pmap_counit A B ~* smash_pmap_counit A C ∘* smash_functor (pid A) (ppcompose_left g) :=
begin
symmetry,
fapply phomotopy.mk,
{ intro af, induction af with a f a f,
{ reflexivity },
{ exact (respect_pt g)⁻¹ },
{ exact (respect_pt g)⁻¹ },
{ apply eq_pathover,
refine ap_compose (smash_pmap_counit A C) _ _ ⬝ph _ ⬝hp (ap_compose g _ _)⁻¹,
refine ap02 _ !functor_gluel ⬝ph _ ⬝hp ap02 _ !elim_gluel⁻¹,
refine !ap_con ⬝ !ap_compose'⁻¹ ◾ !elim_gluel ⬝ph _⁻¹ʰ,
apply square_of_eq_bot, refine !idp_con ⬝ _,
induction C with C c₀, induction g with g g₀, esimp at *,
induction g₀, refine ap02 _ !eq_of_phomotopy_refl },
{ apply eq_pathover,
refine ap_compose (smash_pmap_counit A C) _ _ ⬝ph _ ⬝hp (ap_compose g _ _)⁻¹,
refine ap02 _ !functor_gluer ⬝ph _ ⬝hp ap02 _ !elim_gluer⁻¹,
refine !ap_con ⬝ !ap_compose'⁻¹ ◾ !elim_gluer ⬝ph _,
refine !idp_con ⬝ph _, apply square_of_eq,
refine !idp_con ⬝ !con_inv_cancel_right⁻¹ }},
{ refine !idp_con ⬝ !idp_con ⬝ _, refine _ ⬝ !ap_compose',
refine _ ⬝ !ap_prod_elim⁻¹, esimp,
refine _ ⬝ (ap_is_constant respect_pt _)⁻¹, refine !idp_con⁻¹ }
end
definition smash_pmap_unit_counit (A B : Type*) :
smash_pmap_counit A (A ∧ B) ∘* smash_functor (pid A) (smash_pmap_unit A B) ~* pid (A ∧ B) :=
begin
fconstructor,
{ intro x,
induction x with a b a b,
{ reflexivity },
{ exact gluel pt },
{ exact gluer pt },
{ apply eq_pathover_id_right,
refine ap_compose smash_pmap_counit_map _ _ ⬝ ap02 _ !functor_gluel ⬝ph _,
refine !ap_con ⬝ !ap_compose'⁻¹ ◾ !elim_gluel ⬝ph _,
refine !ap_eq_of_phomotopy ⬝ph _,
apply square_of_eq, refine !idp_con ⬝ !inv_con_cancel_right⁻¹ },
{ apply eq_pathover_id_right,
refine ap_compose smash_pmap_counit_map _ _ ⬝ ap02 _ !functor_gluer ⬝ph _,
refine !ap_con ⬝ !ap_compose'⁻¹ ◾ !elim_gluer ⬝ph _,
refine !idp_con ⬝ph _,
apply square_of_eq, refine !idp_con ⬝ !inv_con_cancel_right⁻¹ }},
{ refine _ ⬝ !ap_compose',
refine _ ⬝ !ap_prod_elim⁻¹, refine _ ⬝ (ap_is_constant respect_pt _)⁻¹,
rexact (con.right_inv (gluer pt))⁻¹ }
end
definition smash_pmap_counit_unit_pt [constructor] {A B : Type*} (f : A →* B) :
smash_pmap_counit A B ∘* pinl A f ~* f :=
begin
fconstructor,
{ intro a, reflexivity },
{ refine !idp_con ⬝ !elim_gluer'⁻¹ }
end
definition smash_pmap_counit_unit (A B : Type*) :
ppcompose_left (smash_pmap_counit A B) ∘* smash_pmap_unit A (ppmap A B) ~* pid (ppmap A B) :=
begin
fapply phomotopy_mk_ppmap,
{ intro f, exact smash_pmap_counit_unit_pt f },
{ refine !trans_refl ⬝ _,
refine _ ⬝ ap (λx, phomotopy_of_eq (x ⬝ _)) !pcompose_eq_of_phomotopy⁻¹,
refine _ ⬝ !phomotopy_of_eq_con⁻¹,
refine _ ⬝ ap011 phomotopy.trans !phomotopy_of_eq_of_phomotopy⁻¹
!phomotopy_of_eq_of_phomotopy⁻¹,
refine _ ⬝ !trans_refl⁻¹,
fapply phomotopy_eq,
{ intro a, refine !elim_gluel'⁻¹ },
{ esimp, refine whisker_right _ !whisker_right_idp ⬝ _ ⬝ !idp_con⁻¹,
refine whisker_right _ !elim_gluel'_same⁻² ⬝ _ ⬝ !elim_gluer'_same⁻¹⁻²,
apply inv_con_eq_of_eq_con, refine !idp_con ⬝ _, esimp,
refine _ ⬝ !ap02_con ⬝ whisker_left _ !ap_inv,
refine !whisker_right_idp ⬝ _,
exact !idp_con }}
end
definition smash_elim [constructor] {A B C : Type*} (f : A →* ppmap B C) : B ∧ A →* C :=
smash_pmap_counit B C ∘* smash_functor (pid B) f
definition smash_elim_inv [constructor] {A B C : Type*} (g : A ∧ B →* C) : B →* ppmap A C :=
ppcompose_left g ∘* smash_pmap_unit A B
definition smash_elim_left_inv {A B C : Type*} (f : A →* ppmap B C) : smash_elim_inv (smash_elim f) ~* f :=
begin
refine !pwhisker_right !ppcompose_left_pcompose ⬝* _,
refine !passoc ⬝* _,
refine !pwhisker_left !smash_pmap_unit_natural⁻¹* ⬝* _,
refine !passoc⁻¹* ⬝* _,
refine !pwhisker_right !smash_pmap_counit_unit ⬝* _,
apply pid_pcompose
end
definition smash_elim_right_inv {A B C : Type*} (g : A ∧ B →* C) : smash_elim (smash_elim_inv g) ~* g :=
begin
refine !pwhisker_left !smash_functor_pid_pcompose ⬝* _,
refine !passoc⁻¹* ⬝* _,
refine !pwhisker_right !smash_pmap_counit_natural⁻¹* ⬝* _,
refine !passoc ⬝* _,
refine !pwhisker_left !smash_pmap_unit_counit ⬝* _,
apply pcompose_pid
end
definition smash_elim_pconst (A B C : Type*) :
smash_elim (pconst B (ppmap A C)) ~* pconst (A ∧ B) C :=
begin
refine pwhisker_left _ (smash_functor_pconst_right (pid A)) ⬝* !pcompose_pconst
-- fconstructor,
-- { intro x, induction x with a b a b,
-- { reflexivity },
-- { reflexivity },
-- { reflexivity },
-- { apply eq_pathover_constant_right, apply hdeg_square,
-- refine ap_compose smash_pmap_counit_map _ _ ⬝ ap02 _ !functor_gluel ⬝ !ap_con ⬝
-- !ap_compose'⁻¹ ◾ !elim_gluel},
-- { apply eq_pathover_constant_right, apply hdeg_square,
-- refine ap_compose smash_pmap_counit_map _ _ ⬝ ap02 _ !functor_gluer ⬝ !ap_con ⬝
-- !ap_compose'⁻¹ ◾ !elim_gluer }},
-- { reflexivity }
end
definition pconst_pcompose_pconst (A B C : Type*) :
pconst_pcompose (pconst A B) = pcompose_pconst (pconst B C) :=
idp
definition symm_symm {A B : Type*} {f g : A →* B} (p : f ~* g) : p⁻¹*⁻¹* = p :=
phomotopy_eq (λa, !inv_inv)
begin
induction p using phomotopy_rec_on_idp, induction f with f f₀, induction B with B b₀, esimp at *,
induction f₀, esimp,
end
definition pconst_pcompose_phomotopy_pconst {A B C : Type*} {f : A →* B} (p : f ~* pconst A B) :
pconst_pcompose f = pwhisker_left (pconst B C) p ⬝* pcompose_pconst (pconst B C) :=
begin
assert H : Π(p : pconst A B ~* f),
pconst_pcompose f = pwhisker_left (pconst B C) p⁻¹* ⬝* pcompose_pconst (pconst B C),
{ intro p, induction p using phomotopy_rec_on_idp, reflexivity },
refine H p⁻¹* ⬝ ap (pwhisker_left _) !symm_symm ◾** idp,
end
definition smash_elim_inv_pconst (A B C : Type*) :
smash_elim_inv (pconst (A ∧ B) C) ~* pconst B (ppmap A C) :=
begin
fapply phomotopy_mk_ppmap,
{ intro f, apply pconst_pcompose },
{ esimp, refine !trans_refl ⬝ _,
refine _ ⬝ (!phomotopy_of_eq_con ⬝ (ap phomotopy_of_eq !pcompose_eq_of_phomotopy ⬝
!phomotopy_of_eq_of_phomotopy) ◾** !phomotopy_of_eq_of_phomotopy)⁻¹,
apply pconst_pcompose_phomotopy_pconst }
end
definition smash_elim_natural {A B C C' : Type*} (f : C →* C')
(g : B →* ppmap A C) : f ∘* smash_elim g ~* smash_elim (ppcompose_left f ∘* g) :=
begin
refine _ ⬝* pwhisker_left _ !smash_functor_pid_pcompose⁻¹*,
refine !passoc⁻¹* ⬝* pwhisker_right _ _ ⬝* !passoc,
apply smash_pmap_counit_natural
end
definition smash_elim_inv_natural {A B C C' : Type*} (f : C →* C')
(g : A ∧ B →* C) : ppcompose_left f ∘* smash_elim_inv g ~* smash_elim_inv (f ∘* g) :=
begin
refine !passoc⁻¹* ⬝* pwhisker_right _ _,
exact !ppcompose_left_pcompose⁻¹*
end
definition smash_elim_phomotopy {A B C : Type*} {f f' : A →* ppmap B C}
(p : f ~* f') : smash_elim f ~* smash_elim f' :=
begin
apply pwhisker_left,
exact smash_functor_phomotopy phomotopy.rfl p
end
definition smash_elim_inv_phomotopy {A B C : Type*} {f f' : A ∧ B →* C}
(p : f ~* f') : smash_elim_inv f ~* smash_elim_inv f' :=
pwhisker_right _ (ppcompose_left_phomotopy p)
definition smash_elim_eq_of_phomotopy {A B C : Type*} {f f' : A →* ppmap B C}
(p : f ~* f') : ap smash_elim (eq_of_phomotopy p) = eq_of_phomotopy (smash_elim_phomotopy p) :=
begin
induction p using phomotopy_rec_on_idp,
refine ap02 _ !eq_of_phomotopy_refl ⬝ _,
refine !eq_of_phomotopy_refl⁻¹ ⬝ _,
apply ap eq_of_phomotopy,
refine _ ⬝ ap (pwhisker_left _) !smash_functor_phomotopy_refl⁻¹,
refine !pwhisker_left_refl⁻¹
end
definition smash_elim_inv_eq_of_phomotopy {A B C : Type*} {f f' : A ∧ B →* C} (p : f ~* f') :
ap smash_elim_inv (eq_of_phomotopy p) = eq_of_phomotopy (smash_elim_inv_phomotopy p) :=
begin
induction p using phomotopy_rec_on_idp,
refine ap02 _ !eq_of_phomotopy_refl ⬝ _,
refine !eq_of_phomotopy_refl⁻¹ ⬝ _,
apply ap eq_of_phomotopy,
refine _ ⬝ ap (pwhisker_right _) !ppcompose_left_phomotopy_refl⁻¹,
refine !pwhisker_right_refl⁻¹
end
definition smash_pelim [constructor] (A B C : Type*) : ppmap A (ppmap B C) →* ppmap (B ∧ A) C :=
pmap.mk smash_elim (eq_of_phomotopy !smash_elim_pconst)
definition smash_pelim_inv [constructor] (A B C : Type*) :
ppmap (B ∧ A) C →* ppmap A (ppmap B C) :=
pmap.mk smash_elim_inv (eq_of_phomotopy !smash_elim_inv_pconst)
theorem smash_elim_natural_pconst {A B C C' : Type*} (f : C →* C') :
smash_elim_natural f (pconst A (ppmap B C)) ⬝*
(smash_elim_phomotopy (pcompose_pconst (ppcompose_left f)) ⬝*
smash_elim_pconst B A C') =
pwhisker_left f (smash_elim_pconst B A C) ⬝*
pcompose_pconst f :=
begin
refine idp ◾** (!trans_assoc⁻¹ ⬝ (!pwhisker_left_trans⁻¹ ◾** idp)) ⬝ _,
refine !trans_assoc⁻¹ ⬝ _,
refine (!trans_assoc ⬝ (idp ◾** (!pwhisker_left_trans⁻¹ ⬝
ap (pwhisker_left _) (smash_functor_pconst_right_pid_pcompose' (ppcompose_left f))⁻¹ ⬝
!pwhisker_left_trans))) ◾** idp ⬝ _,
refine (!trans_assoc⁻¹ ⬝ (!passoc_phomotopy_right⁻¹ʰ** ⬝h**
!pwhisker_right_pwhisker_left ⬝h** !passoc_phomotopy_right) ◾** idp) ◾** idp ⬝ _,
refine !trans_assoc ⬝ !trans_assoc ⬝ idp ◾**_ ⬝ !trans_assoc⁻¹ ⬝ !pwhisker_left_trans⁻¹ ◾** idp,
refine !trans_assoc ⬝ !trans_assoc ⬝ (eq_symm_trans_of_trans_eq _)⁻¹,
refine !pcompose_pconst_pcompose⁻¹ ⬝ _,
refine _ ⬝ idp ◾** (!pcompose_pconst_pcompose),
refine !pcompose_pconst_phomotopy⁻¹
end
definition smash_pelim_natural {A B C C' : Type*} (f : C →* C') :
ppcompose_left f ∘* smash_pelim A B C ~*
smash_pelim A B C' ∘* ppcompose_left (ppcompose_left f) :=
begin
fapply phomotopy_mk_ppmap,
{ exact smash_elim_natural f },
{ esimp,
refine idp ◾** (!phomotopy_of_eq_con ⬝ (ap phomotopy_of_eq !smash_elim_eq_of_phomotopy ⬝
!phomotopy_of_eq_of_phomotopy) ◾** !phomotopy_of_eq_of_phomotopy) ⬝ _ ,
refine _ ⬝ (!phomotopy_of_eq_con ⬝ (ap phomotopy_of_eq !pcompose_eq_of_phomotopy ⬝
!phomotopy_of_eq_of_phomotopy) ◾** !phomotopy_of_eq_of_phomotopy)⁻¹,
exact smash_elim_natural_pconst f }
end
definition smash_adjoint_pmap' [constructor] (A B C : Type*) : B →* ppmap A C ≃ A ∧ B →* C :=
begin
fapply equiv.MK,
{ exact smash_elim },
{ exact smash_elim_inv },
{ intro g, apply eq_of_phomotopy, exact smash_elim_right_inv g },
{ intro f, apply eq_of_phomotopy, exact smash_elim_left_inv f }
end
definition smash_adjoint_pmap_inv [constructor] (A B C : Type*) :
ppmap B (ppmap A C) ≃* ppmap (A ∧ B) C :=
pequiv_of_equiv (smash_adjoint_pmap' A B C) (eq_of_phomotopy (smash_elim_pconst A B C))
definition smash_adjoint_pmap [constructor] (A B C : Type*) :
ppmap (A ∧ B) C ≃* ppmap B (ppmap A C) :=
(smash_adjoint_pmap_inv A B C)⁻¹ᵉ*
definition smash_adjoint_pmap_natural_pt {A B C C' : Type*} (f : C →* C') (g : A ∧ B →* C) :
ppcompose_left f ∘* smash_adjoint_pmap A B C g ~* smash_adjoint_pmap A B C' (f ∘* g) :=
begin
refine !passoc⁻¹* ⬝* pwhisker_right _ _,
exact !ppcompose_left_pcompose⁻¹*
end
definition smash_adjoint_pmap_inv_natural_pt {A B C C' : Type*} (f : C →* C')
(g : B →* ppmap A C) : f ∘* (smash_adjoint_pmap A B C)⁻¹ᵉ* g ~*
(smash_adjoint_pmap A B C')⁻¹ᵉ* (ppcompose_left f ∘* g) :=
begin
refine _ ⬝* pwhisker_left _ !smash_functor_pid_pcompose⁻¹*,
refine !passoc⁻¹* ⬝* pwhisker_right _ _ ⬝* !passoc,
apply smash_pmap_counit_natural
end
definition smash_adjoint_pmap_inv_natural [constructor] {A B C C' : Type*} (f : C →* C') :
ppcompose_left f ∘* smash_adjoint_pmap_inv A B C ~*
smash_adjoint_pmap_inv A B C' ∘* ppcompose_left (ppcompose_left f) :=
smash_pelim_natural f
definition smash_adjoint_pmap_natural [constructor] {A B C C' : Type*} (f : C →* C') :
ppcompose_left (ppcompose_left f) ∘* smash_adjoint_pmap A B C ~*
smash_adjoint_pmap A B C' ∘* ppcompose_left f :=
(smash_adjoint_pmap_inv_natural f)⁻¹ʰ*
/- associativity of smash -/
definition smash_assoc_elim_equiv (A B C X : Type*) :
ppmap (A ∧ (B ∧ C)) X ≃* ppmap ((A ∧ B) ∧ C) X :=
calc
ppmap (A ∧ (B ∧ C)) X ≃* ppmap (B ∧ C) (ppmap A X) : smash_adjoint_pmap A (B ∧ C) X
... ≃* ppmap C (ppmap B (ppmap A X)) : smash_adjoint_pmap B C (ppmap A X)
... ≃* ppmap C (ppmap (A ∧ B) X) : pequiv_ppcompose_left (smash_adjoint_pmap_inv A B X)
... ≃* ppmap ((A ∧ B) ∧ C) X : smash_adjoint_pmap_inv (A ∧ B) C X
definition smash_assoc_elim_equiv_fn (A B C X : Type*) (f : A ∧ (B ∧ C) →* X) :
(A ∧ B) ∧ C →* X :=
smash_elim (ppcompose_left (smash_adjoint_pmap A B X)⁻¹ᵉ* (smash_elim_inv (smash_elim_inv f)))
definition smash_assoc_elim_natural_pt {A B C X X' : Type*} (f : X →* X') (g : A ∧ (B ∧ C) →* X) :
f ∘* smash_assoc_elim_equiv A B C X g ~* smash_assoc_elim_equiv A B C X' (f ∘* g) :=
begin
refine !smash_adjoint_pmap_inv_natural_pt ⬝* _,
apply smash_elim_phomotopy,
refine !passoc⁻¹* ⬝* _,
refine pwhisker_right _ !smash_adjoint_pmap_inv_natural ⬝* _,
refine !passoc ⬝* _,
apply pwhisker_left,
refine !smash_adjoint_pmap_natural_pt ⬝* _,
apply smash_elim_inv_phomotopy,
refine !smash_adjoint_pmap_natural_pt
end
definition smash_assoc_elim_inv_natural_pt {A B C X X' : Type*} (f : X →* X')
(g : (A ∧ B) ∧ C →* X) :
f ∘* (smash_assoc_elim_equiv A B C X)⁻¹ᵉ* g ~* (smash_assoc_elim_equiv A B C X')⁻¹ᵉ* (f ∘* g) :=
begin
refine !smash_adjoint_pmap_inv_natural_pt ⬝* _,
apply smash_elim_phomotopy,
refine !passoc⁻¹* ⬝* _,
refine pwhisker_right _ !smash_pmap_counit_natural ⬝* _,
refine !passoc ⬝* _,
apply pwhisker_left,
refine !smash_functor_pid_pcompose⁻¹* ⬝* _,
apply smash_functor_phomotopy phomotopy.rfl,
refine !passoc⁻¹* ⬝* _,
refine pwhisker_right _ !smash_adjoint_pmap_natural ⬝* _,
refine !passoc ⬝* _,
apply pwhisker_left,
apply smash_elim_inv_natural
end
-- TODO: maybe do it without pap / phomotopy_of_eq
definition smash_assoc (A B C : Type*) : A ∧ (B ∧ C) ≃* (A ∧ B) ∧ C :=
begin
fapply pequiv.MK2,
{ exact !smash_assoc_elim_equiv⁻¹ᵉ* !pid },
{ exact !smash_assoc_elim_equiv !pid },
{ refine !smash_assoc_elim_inv_natural_pt ⬝* _,
refine pap !smash_assoc_elim_equiv⁻¹ᵉ* !pcompose_pid ⬝* _,
apply phomotopy_of_eq, apply to_left_inv !smash_assoc_elim_equiv },
{ refine !smash_assoc_elim_natural_pt ⬝* _,
refine pap !smash_assoc_elim_equiv !pcompose_pid ⬝* _,
apply phomotopy_of_eq, apply to_right_inv !smash_assoc_elim_equiv }
end
print axioms smash_assoc
end smash