l3lab/ntp-mathlib huggingface dataset:
/-- Transport the property of being cartesian closed across an equivalence of categories.

Note we didn't require any coherence between the choice of finite products here, since we transport
along the `prodComparison` isomorphism.
-/
def cartesianClosedOfEquiv (e : C ≌ D) [h : CartesianClosed C] : CartesianClosed D where
  closed X :=
    { isAdj := by
        haveI q : Exponentiable (e.inverse.obj X) := inferInstance
        have : IsLeftAdjoint (prod.functor.obj (e.inverse.obj X)) := q.isAdj
        have : e.functor ⋙ prod.functor.obj X ⋙ e.inverse ≅
            prod.functor.obj (e.inverse.obj X) := by
          apply NatIso.ofComponents _ _
          · intro Y
            apply asIso (prodComparison e.inverse X (e.functor.obj Y)) ≪≫ _
            

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
A B X✝ X' Y✝ Y' Z : C
inst✝³ : HasFiniteProducts C
inst✝² : Exponentiable A
D : Type u₂
inst✝¹ : Category.{v, u₂} D
inst✝ : HasFiniteProducts D
e : C ≌ D
h : CartesianClosed C
X : D
q : Exponentiable (e.inverse.obj X)
this : IsLeftAdjoint (prod.functor.obj (e.inverse.obj X))
Y : C
⊢ e.inverse.obj X ⨯ e.inverse.obj (e.functor.obj Y) ≅ (prod.functor.obj (e.inverse.obj X)).obj Y

Next tactic:
apply prod.mapIso (Iso.refl _) (e.unitIso.app Y).symm
/-- Transport the property of being cartesian closed across an equivalence of categories.

Note we didn't require any coherence between the choice of finite products here, since we transport
along the `prodComparison` isomorphism.
-/
def cartesianClosedOfEquiv (e : C ≌ D) [h : CartesianClosed C] : CartesianClosed D where
  closed X :=
    { isAdj := by
        haveI q : Exponentiable (e.inverse.obj X) := inferInstance
        have : IsLeftAdjoint (prod.functor.obj (e.inverse.obj X)) := q.isAdj
        have : e.functor ⋙ prod.functor.obj X ⋙ e.inverse ≅
            prod.functor.obj (e.inverse.obj X) := by
          apply NatIso.ofComponents _ _
          · intro Y
            apply asIso (prodComparison e.inverse X (e.functor.obj Y)) ≪≫ _
            apply prod.mapIso (Iso.refl _) (e.unitIso.app Y).symm
          · 

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
A B X✝ X' Y Y' Z : C
inst✝³ : HasFiniteProducts C
inst✝² : Exponentiable A
D : Type u₂
inst✝¹ : Category.{v, u₂} D
inst✝ : HasFiniteProducts D
e : C ≌ D
h : CartesianClosed C
X : D
q : Exponentiable (e.inverse.obj X)
this : IsLeftAdjoint (prod.functor.obj (e.inverse.obj X))
⊢ ∀ {X_1 Y : C} (f : X_1 ⟶ Y),
    (e.functor ⋙ prod.functor.obj X ⋙ e.inverse).map f ≫
        (asIso (prodComparison e.inverse X (e.functor.obj Y)) ≪≫
            prod.mapIso (Iso.refl (e.inverse.obj X)) (e.unitIso.app Y).symm).hom =
      (asIso (prodComparison e.inverse X (e.functor.obj X_1)) ≪≫
            prod.mapIso (Iso.refl (e.inverse.obj X)) (e.unitIso.app X_1).symm).hom ≫
        (prod.functor.obj (e.inverse.obj X)).map f

Next tactic:
intro Y Z g
/-- Transport the property of being cartesian closed across an equivalence of categories.

Note we didn't require any coherence between the choice of finite products here, since we transport
along the `prodComparison` isomorphism.
-/
def cartesianClosedOfEquiv (e : C ≌ D) [h : CartesianClosed C] : CartesianClosed D where
  closed X :=
    { isAdj := by
        haveI q : Exponentiable (e.inverse.obj X) := inferInstance
        have : IsLeftAdjoint (prod.functor.obj (e.inverse.obj X)) := q.isAdj
        have : e.functor ⋙ prod.functor.obj X ⋙ e.inverse ≅
            prod.functor.obj (e.inverse.obj X) := by
          apply NatIso.ofComponents _ _
          · intro Y
            apply asIso (prodComparison e.inverse X (e.functor.obj Y)) ≪≫ _
            apply prod.mapIso (Iso.refl _) (e.unitIso.app Y).symm
          · intro Y Z g
            

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
A B X✝ X' Y✝ Y' Z✝ : C
inst✝³ : HasFiniteProducts C
inst✝² : Exponentiable A
D : Type u₂
inst✝¹ : Category.{v, u₂} D
inst✝ : HasFiniteProducts D
e : C ≌ D
h : CartesianClosed C
X : D
q : Exponentiable (e.inverse.obj X)
this : IsLeftAdjoint (prod.functor.obj (e.inverse.obj X))
Y Z : C
g : Y ⟶ Z
⊢ (e.functor ⋙ prod.functor.obj X ⋙ e.inverse).map g ≫
      (asIso (prodComparison e.inverse X (e.functor.obj Z)) ≪≫
          prod.mapIso (Iso.refl (e.inverse.obj X)) (e.unitIso.app Z).symm).hom =
    (asIso (prodComparison e.inverse X (e.functor.obj Y)) ≪≫
          prod.mapIso (Iso.refl (e.inverse.obj X)) (e.unitIso.app Y).symm).hom ≫
      (prod.functor.obj (e.inverse.obj X)).map g

Next tactic:
dsimp
/-- Transport the property of being cartesian closed across an equivalence of categories.

Note we didn't require any coherence between the choice of finite products here, since we transport
along the `prodComparison` isomorphism.
-/
def cartesianClosedOfEquiv (e : C ≌ D) [h : CartesianClosed C] : CartesianClosed D where
  closed X :=
    { isAdj := by
        haveI q : Exponentiable (e.inverse.obj X) := inferInstance
        have : IsLeftAdjoint (prod.functor.obj (e.inverse.obj X)) := q.isAdj
        have : e.functor ⋙ prod.functor.obj X ⋙ e.inverse ≅
            prod.functor.obj (e.inverse.obj X) := by
          apply NatIso.ofComponents _ _
          · intro Y
            apply asIso (prodComparison e.inverse X (e.functor.obj Y)) ≪≫ _
            apply prod.mapIso (Iso.refl _) (e.unitIso.app Y).symm
          · intro Y Z g
            dsimp
            

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
A B X✝ X' Y✝ Y' Z✝ : C
inst✝³ : HasFiniteProducts C
inst✝² : Exponentiable A
D : Type u₂
inst✝¹ : Category.{v, u₂} D
inst✝ : HasFiniteProducts D
e : C ≌ D
h : CartesianClosed C
X : D
q : Exponentiable (e.inverse.obj X)
this : IsLeftAdjoint (prod.functor.obj (e.inverse.obj X))
Y Z : C
g : Y ⟶ Z
⊢ e.inverse.map (prod.map (𝟙 X) (e.functor.map g)) ≫
      prodComparison e.inverse X (e.functor.obj Z) ≫ prod.map (𝟙 (e.inverse.obj X)) (e.unitIso.inv.app Z) =
    (prodComparison e.inverse X (e.functor.obj Y) ≫ prod.map (𝟙 (e.inverse.obj X)) (e.unitIso.inv.app Y)) ≫
      prod.map (𝟙 (e.inverse.obj X)) g

Next tactic:
simp [prodComparison, prod.comp_lift, ← e.inverse.map_comp, ← e.inverse.map_comp_assoc]
/-- Transport the property of being cartesian closed across an equivalence of categories.

Note we didn't require any coherence between the choice of finite products here, since we transport
along the `prodComparison` isomorphism.
-/
def cartesianClosedOfEquiv (e : C ≌ D) [h : CartesianClosed C] : CartesianClosed D where
  closed X :=
    { isAdj := by
        haveI q : Exponentiable (e.inverse.obj X) := inferInstance
        have : IsLeftAdjoint (prod.functor.obj (e.inverse.obj X)) := q.isAdj
        have : e.functor ⋙ prod.functor.obj X ⋙ e.inverse ≅
            prod.functor.obj (e.inverse.obj X) := by
          apply NatIso.ofComponents _ _
          · intro Y
            apply asIso (prodComparison e.inverse X (e.functor.obj Y)) ≪≫ _
            apply prod.mapIso (Iso.refl _) (e.unitIso.app Y).symm
          · intro Y Z g
            dsimp
            simp [prodComparison, prod.comp_lift, ← e.inverse.map_comp, ← e.inverse.map_comp_assoc]
            -- I wonder if it would be a good idea to
            -- make `map_comp` a simp lemma the other way round
        · 

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
A B X✝ X' Y Y' Z : C
inst✝³ : HasFiniteProducts C
inst✝² : Exponentiable A
D : Type u₂
inst✝¹ : Category.{v, u₂} D
inst✝ : HasFiniteProducts D
e : C ≌ D
h : CartesianClosed C
X : D
q : Exponentiable (e.inverse.obj X)
this✝ : IsLeftAdjoint (prod.functor.obj (e.inverse.obj X))
this : e.functor ⋙ prod.functor.obj X ⋙ e.inverse ≅ prod.functor.obj (e.inverse.obj X)
⊢ IsLeftAdjoint (MonoidalCategory.tensorLeft X)

Next tactic:
have : IsLeftAdjoint (e.functor ⋙ prod.functor.obj X ⋙ e.inverse) :=
            Adjunction.leftAdjointOfNatIso this.symm
/-- Transport the property of being cartesian closed across an equivalence of categories.

Note we didn't require any coherence between the choice of finite products here, since we transport
along the `prodComparison` isomorphism.
-/
def cartesianClosedOfEquiv (e : C ≌ D) [h : CartesianClosed C] : CartesianClosed D where
  closed X :=
    { isAdj := by
        haveI q : Exponentiable (e.inverse.obj X) := inferInstance
        have : IsLeftAdjoint (prod.functor.obj (e.inverse.obj X)) := q.isAdj
        have : e.functor ⋙ prod.functor.obj X ⋙ e.inverse ≅
            prod.functor.obj (e.inverse.obj X) := by
          apply NatIso.ofComponents _ _
          · intro Y
            apply asIso (prodComparison e.inverse X (e.functor.obj Y)) ≪≫ _
            apply prod.mapIso (Iso.refl _) (e.unitIso.app Y).symm
          · intro Y Z g
            dsimp
            simp [prodComparison, prod.comp_lift, ← e.inverse.map_comp, ← e.inverse.map_comp_assoc]
            -- I wonder if it would be a good idea to
            -- make `map_comp` a simp lemma the other way round
        · have : IsLeftAdjoint (e.functor ⋙ prod.functor.obj X ⋙ e.inverse) :=
            Adjunction.leftAdjointOfNatIso this.symm
          

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
A B X✝ X' Y Y' Z : C
inst✝³ : HasFiniteProducts C
inst✝² : Exponentiable A
D : Type u₂
inst✝¹ : Category.{v, u₂} D
inst✝ : HasFiniteProducts D
e : C ≌ D
h : CartesianClosed C
X : D
q : Exponentiable (e.inverse.obj X)
this✝¹ : IsLeftAdjoint (prod.functor.obj (e.inverse.obj X))
this✝ : e.functor ⋙ prod.functor.obj X ⋙ e.inverse ≅ prod.functor.obj (e.inverse.obj X)
this : IsLeftAdjoint (e.functor ⋙ prod.functor.obj X ⋙ e.inverse)
⊢ IsLeftAdjoint (MonoidalCategory.tensorLeft X)

Next tactic:
have : IsLeftAdjoint (e.inverse ⋙ e.functor ⋙ prod.functor.obj X ⋙ e.inverse) :=
            Adjunction.leftAdjointOfComp e.inverse _
/-- Transport the property of being cartesian closed across an equivalence of categories.

Note we didn't require any coherence between the choice of finite products here, since we transport
along the `prodComparison` isomorphism.
-/
def cartesianClosedOfEquiv (e : C ≌ D) [h : CartesianClosed C] : CartesianClosed D where
  closed X :=
    { isAdj := by
        haveI q : Exponentiable (e.inverse.obj X) := inferInstance
        have : IsLeftAdjoint (prod.functor.obj (e.inverse.obj X)) := q.isAdj
        have : e.functor ⋙ prod.functor.obj X ⋙ e.inverse ≅
            prod.functor.obj (e.inverse.obj X) := by
          apply NatIso.ofComponents _ _
          · intro Y
            apply asIso (prodComparison e.inverse X (e.functor.obj Y)) ≪≫ _
            apply prod.mapIso (Iso.refl _) (e.unitIso.app Y).symm
          · intro Y Z g
            dsimp
            simp [prodComparison, prod.comp_lift, ← e.inverse.map_comp, ← e.inverse.map_comp_assoc]
            -- I wonder if it would be a good idea to
            -- make `map_comp` a simp lemma the other way round
        · have : IsLeftAdjoint (e.functor ⋙ prod.functor.obj X ⋙ e.inverse) :=
            Adjunction.leftAdjointOfNatIso this.symm
          have : IsLeftAdjoint (e.inverse ⋙ e.functor ⋙ prod.functor.obj X ⋙ e.inverse) :=
            Adjunction.leftAdjointOfComp e.inverse _
          

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
A B X✝ X' Y Y' Z : C
inst✝³ : HasFiniteProducts C
inst✝² : Exponentiable A
D : Type u₂
inst✝¹ : Category.{v, u₂} D
inst✝ : HasFiniteProducts D
e : C ≌ D
h : CartesianClosed C
X : D
q : Exponentiable (e.inverse.obj X)
this✝² : IsLeftAdjoint (prod.functor.obj (e.inverse.obj X))
this✝¹ : e.functor ⋙ prod.functor.obj X ⋙ e.inverse ≅ prod.functor.obj (e.inverse.obj X)
this✝ : IsLeftAdjoint (e.functor ⋙ prod.functor.obj X ⋙ e.inverse)
this : IsLeftAdjoint (e.inverse ⋙ e.functor ⋙ prod.functor.obj X ⋙ e.inverse)
⊢ IsLeftAdjoint (MonoidalCategory.tensorLeft X)

Next tactic:
have :
            (e.inverse ⋙ e.functor ⋙ prod.functor.obj X ⋙ e.inverse) ⋙ e.functor ≅
              prod.functor.obj X := by
            apply isoWhiskerRight e.counitIso (prod.functor.obj X ⋙ e.inverse ⋙ e.functor) ≪≫ _
            change prod.functor.obj X ⋙ e.inverse ⋙ e.functor ≅ prod.functor.obj X
            apply isoWhiskerLeft (prod.functor.obj X) e.counitIso
/-- Transport the property of being cartesian closed across an equivalence of categories.

Note we didn't require any coherence between the choice of finite products here, since we transport
along the `prodComparison` isomorphism.
-/
def cartesianClosedOfEquiv (e : C ≌ D) [h : CartesianClosed C] : CartesianClosed D where
  closed X :=
    { isAdj := by
        haveI q : Exponentiable (e.inverse.obj X) := inferInstance
        have : IsLeftAdjoint (prod.functor.obj (e.inverse.obj X)) := q.isAdj
        have : e.functor ⋙ prod.functor.obj X ⋙ e.inverse ≅
            prod.functor.obj (e.inverse.obj X) := by
          apply NatIso.ofComponents _ _
          · intro Y
            apply asIso (prodComparison e.inverse X (e.functor.obj Y)) ≪≫ _
            apply prod.mapIso (Iso.refl _) (e.unitIso.app Y).symm
          · intro Y Z g
            dsimp
            simp [prodComparison, prod.comp_lift, ← e.inverse.map_comp, ← e.inverse.map_comp_assoc]
            -- I wonder if it would be a good idea to
            -- make `map_comp` a simp lemma the other way round
        · have : IsLeftAdjoint (e.functor ⋙ prod.functor.obj X ⋙ e.inverse) :=
            Adjunction.leftAdjointOfNatIso this.symm
          have : IsLeftAdjoint (e.inverse ⋙ e.functor ⋙ prod.functor.obj X ⋙ e.inverse) :=
            Adjunction.leftAdjointOfComp e.inverse _
          have :
            (e.inverse ⋙ e.functor ⋙ prod.functor.obj X ⋙ e.inverse) ⋙ e.functor ≅
              prod.functor.obj X := by
            

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
A B X✝ X' Y Y' Z : C
inst✝³ : HasFiniteProducts C
inst✝² : Exponentiable A
D : Type u₂
inst✝¹ : Category.{v, u₂} D
inst✝ : HasFiniteProducts D
e : C ≌ D
h : CartesianClosed C
X : D
q : Exponentiable (e.inverse.obj X)
this✝² : IsLeftAdjoint (prod.functor.obj (e.inverse.obj X))
this✝¹ : e.functor ⋙ prod.functor.obj X ⋙ e.inverse ≅ prod.functor.obj (e.inverse.obj X)
this✝ : IsLeftAdjoint (e.functor ⋙ prod.functor.obj X ⋙ e.inverse)
this : IsLeftAdjoint (e.inverse ⋙ e.functor ⋙ prod.functor.obj X ⋙ e.inverse)
⊢ (e.inverse ⋙ e.functor ⋙ prod.functor.obj X ⋙ e.inverse) ⋙ e.functor ≅ prod.functor.obj X

Next tactic:
apply isoWhiskerRight e.counitIso (prod.functor.obj X ⋙ e.inverse ⋙ e.functor) ≪≫ _
/-- Transport the property of being cartesian closed across an equivalence of categories.

Note we didn't require any coherence between the choice of finite products here, since we transport
along the `prodComparison` isomorphism.
-/
def cartesianClosedOfEquiv (e : C ≌ D) [h : CartesianClosed C] : CartesianClosed D where
  closed X :=
    { isAdj := by
        haveI q : Exponentiable (e.inverse.obj X) := inferInstance
        have : IsLeftAdjoint (prod.functor.obj (e.inverse.obj X)) := q.isAdj
        have : e.functor ⋙ prod.functor.obj X ⋙ e.inverse ≅
            prod.functor.obj (e.inverse.obj X) := by
          apply NatIso.ofComponents _ _
          · intro Y
            apply asIso (prodComparison e.inverse X (e.functor.obj Y)) ≪≫ _
            apply prod.mapIso (Iso.refl _) (e.unitIso.app Y).symm
          · intro Y Z g
            dsimp
            simp [prodComparison, prod.comp_lift, ← e.inverse.map_comp, ← e.inverse.map_comp_assoc]
            -- I wonder if it would be a good idea to
            -- make `map_comp` a simp lemma the other way round
        · have : IsLeftAdjoint (e.functor ⋙ prod.functor.obj X ⋙ e.inverse) :=
            Adjunction.leftAdjointOfNatIso this.symm
          have : IsLeftAdjoint (e.inverse ⋙ e.functor ⋙ prod.functor.obj X ⋙ e.inverse) :=
            Adjunction.leftAdjointOfComp e.inverse _
          have :
            (e.inverse ⋙ e.functor ⋙ prod.functor.obj X ⋙ e.inverse) ⋙ e.functor ≅
              prod.functor.obj X := by
            apply isoWhiskerRight e.counitIso (prod.functor.obj X ⋙ e.inverse ⋙ e.functor) ≪≫ _
            

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
A B X✝ X' Y Y' Z : C
inst✝³ : HasFiniteProducts C
inst✝² : Exponentiable A
D : Type u₂
inst✝¹ : Category.{v, u₂} D
inst✝ : HasFiniteProducts D
e : C ≌ D
h : CartesianClosed C
X : D
q : Exponentiable (e.inverse.obj X)
this✝² : IsLeftAdjoint (prod.functor.obj (e.inverse.obj X))
this✝¹ : e.functor ⋙ prod.functor.obj X ⋙ e.inverse ≅ prod.functor.obj (e.inverse.obj X)
this✝ : IsLeftAdjoint (e.functor ⋙ prod.functor.obj X ⋙ e.inverse)
this : IsLeftAdjoint (e.inverse ⋙ e.functor ⋙ prod.functor.obj X ⋙ e.inverse)
⊢ 𝟭 D ⋙ prod.functor.obj X ⋙ e.inverse ⋙ e.functor ≅ prod.functor.obj X

Next tactic:
change prod.functor.obj X ⋙ e.inverse ⋙ e.functor ≅ prod.functor.obj X
/-- Transport the property of being cartesian closed across an equivalence of categories.

Note we didn't require any coherence between the choice of finite products here, since we transport
along the `prodComparison` isomorphism.
-/
def cartesianClosedOfEquiv (e : C ≌ D) [h : CartesianClosed C] : CartesianClosed D where
  closed X :=
    { isAdj := by
        haveI q : Exponentiable (e.inverse.obj X) := inferInstance
        have : IsLeftAdjoint (prod.functor.obj (e.inverse.obj X)) := q.isAdj
        have : e.functor ⋙ prod.functor.obj X ⋙ e.inverse ≅
            prod.functor.obj (e.inverse.obj X) := by
          apply NatIso.ofComponents _ _
          · intro Y
            apply asIso (prodComparison e.inverse X (e.functor.obj Y)) ≪≫ _
            apply prod.mapIso (Iso.refl _) (e.unitIso.app Y).symm
          · intro Y Z g
            dsimp
            simp [prodComparison, prod.comp_lift, ← e.inverse.map_comp, ← e.inverse.map_comp_assoc]
            -- I wonder if it would be a good idea to
            -- make `map_comp` a simp lemma the other way round
        · have : IsLeftAdjoint (e.functor ⋙ prod.functor.obj X ⋙ e.inverse) :=
            Adjunction.leftAdjointOfNatIso this.symm
          have : IsLeftAdjoint (e.inverse ⋙ e.functor ⋙ prod.functor.obj X ⋙ e.inverse) :=
            Adjunction.leftAdjointOfComp e.inverse _
          have :
            (e.inverse ⋙ e.functor ⋙ prod.functor.obj X ⋙ e.inverse) ⋙ e.functor ≅
              prod.functor.obj X := by
            apply isoWhiskerRight e.counitIso (prod.functor.obj X ⋙ e.inverse ⋙ e.functor) ≪≫ _
            change prod.functor.obj X ⋙ e.inverse ⋙ e.functor ≅ prod.functor.obj X
            

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
A B X✝ X' Y Y' Z : C
inst✝³ : HasFiniteProducts C
inst✝² : Exponentiable A
D : Type u₂
inst✝¹ : Category.{v, u₂} D
inst✝ : HasFiniteProducts D
e : C ≌ D
h : CartesianClosed C
X : D
q : Exponentiable (e.inverse.obj X)
this✝² : IsLeftAdjoint (prod.functor.obj (e.inverse.obj X))
this✝¹ : e.functor ⋙ prod.functor.obj X ⋙ e.inverse ≅ prod.functor.obj (e.inverse.obj X)
this✝ : IsLeftAdjoint (e.functor ⋙ prod.functor.obj X ⋙ e.inverse)
this : IsLeftAdjoint (e.inverse ⋙ e.functor ⋙ prod.functor.obj X ⋙ e.inverse)
⊢ prod.functor.obj X ⋙ e.inverse ⋙ e.functor ≅ prod.functor.obj X

Next tactic:
apply isoWhiskerLeft (prod.functor.obj X) e.counitIso
/-- Transport the property of being cartesian closed across an equivalence of categories.

Note we didn't require any coherence between the choice of finite products here, since we transport
along the `prodComparison` isomorphism.
-/
def cartesianClosedOfEquiv (e : C ≌ D) [h : CartesianClosed C] : CartesianClosed D where
  closed X :=
    { isAdj := by
        haveI q : Exponentiable (e.inverse.obj X) := inferInstance
        have : IsLeftAdjoint (prod.functor.obj (e.inverse.obj X)) := q.isAdj
        have : e.functor ⋙ prod.functor.obj X ⋙ e.inverse ≅
            prod.functor.obj (e.inverse.obj X) := by
          apply NatIso.ofComponents _ _
          · intro Y
            apply asIso (prodComparison e.inverse X (e.functor.obj Y)) ≪≫ _
            apply prod.mapIso (Iso.refl _) (e.unitIso.app Y).symm
          · intro Y Z g
            dsimp
            simp [prodComparison, prod.comp_lift, ← e.inverse.map_comp, ← e.inverse.map_comp_assoc]
            -- I wonder if it would be a good idea to
            -- make `map_comp` a simp lemma the other way round
        · have : IsLeftAdjoint (e.functor ⋙ prod.functor.obj X ⋙ e.inverse) :=
            Adjunction.leftAdjointOfNatIso this.symm
          have : IsLeftAdjoint (e.inverse ⋙ e.functor ⋙ prod.functor.obj X ⋙ e.inverse) :=
            Adjunction.leftAdjointOfComp e.inverse _
          have :
            (e.inverse ⋙ e.functor ⋙ prod.functor.obj X ⋙ e.inverse) ⋙ e.functor ≅
              prod.functor.obj X := by
            apply isoWhiskerRight e.counitIso (prod.functor.obj X ⋙ e.inverse ⋙ e.functor) ≪≫ _
            change prod.functor.obj X ⋙ e.inverse ⋙ e.functor ≅ prod.functor.obj X
            apply isoWhiskerLeft (prod.functor.obj X) e.counitIso
          

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
A B X✝ X' Y Y' Z : C
inst✝³ : HasFiniteProducts C
inst✝² : Exponentiable A
D : Type u₂
inst✝¹ : Category.{v, u₂} D
inst✝ : HasFiniteProducts D
e : C ≌ D
h : CartesianClosed C
X : D
q : Exponentiable (e.inverse.obj X)
this✝³ : IsLeftAdjoint (prod.functor.obj (e.inverse.obj X))
this✝² : e.functor ⋙ prod.functor.obj X ⋙ e.inverse ≅ prod.functor.obj (e.inverse.obj X)
this✝¹ : IsLeftAdjoint (e.functor ⋙ prod.functor.obj X ⋙ e.inverse)
this✝ : IsLeftAdjoint (e.inverse ⋙ e.functor ⋙ prod.functor.obj X ⋙ e.inverse)
this : (e.inverse ⋙ e.functor ⋙ prod.functor.obj X ⋙ e.inverse) ⋙ e.functor ≅ prod.functor.obj X
⊢ IsLeftAdjoint (MonoidalCategory.tensorLeft X)

Next tactic:
skip
/-- Transport the property of being cartesian closed across an equivalence of categories.

Note we didn't require any coherence between the choice of finite products here, since we transport
along the `prodComparison` isomorphism.
-/
def cartesianClosedOfEquiv (e : C ≌ D) [h : CartesianClosed C] : CartesianClosed D where
  closed X :=
    { isAdj := by
        haveI q : Exponentiable (e.inverse.obj X) := inferInstance
        have : IsLeftAdjoint (prod.functor.obj (e.inverse.obj X)) := q.isAdj
        have : e.functor ⋙ prod.functor.obj X ⋙ e.inverse ≅
            prod.functor.obj (e.inverse.obj X) := by
          apply NatIso.ofComponents _ _
          · intro Y
            apply asIso (prodComparison e.inverse X (e.functor.obj Y)) ≪≫ _
            apply prod.mapIso (Iso.refl _) (e.unitIso.app Y).symm
          · intro Y Z g
            dsimp
            simp [prodComparison, prod.comp_lift, ← e.inverse.map_comp, ← e.inverse.map_comp_assoc]
            -- I wonder if it would be a good idea to
            -- make `map_comp` a simp lemma the other way round
        · have : IsLeftAdjoint (e.functor ⋙ prod.functor.obj X ⋙ e.inverse) :=
            Adjunction.leftAdjointOfNatIso this.symm
          have : IsLeftAdjoint (e.inverse ⋙ e.functor ⋙ prod.functor.obj X ⋙ e.inverse) :=
            Adjunction.leftAdjointOfComp e.inverse _
          have :
            (e.inverse ⋙ e.functor ⋙ prod.functor.obj X ⋙ e.inverse) ⋙ e.functor ≅
              prod.functor.obj X := by
            apply isoWhiskerRight e.counitIso (prod.functor.obj X ⋙ e.inverse ⋙ e.functor) ≪≫ _
            change prod.functor.obj X ⋙ e.inverse ⋙ e.functor ≅ prod.functor.obj X
            apply isoWhiskerLeft (prod.functor.obj X) e.counitIso
          skip
          

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
A B X✝ X' Y Y' Z : C
inst✝³ : HasFiniteProducts C
inst✝² : Exponentiable A
D : Type u₂
inst✝¹ : Category.{v, u₂} D
inst✝ : HasFiniteProducts D
e : C ≌ D
h : CartesianClosed C
X : D
q : Exponentiable (e.inverse.obj X)
this✝³ : IsLeftAdjoint (prod.functor.obj (e.inverse.obj X))
this✝² : e.functor ⋙ prod.functor.obj X ⋙ e.inverse ≅ prod.functor.obj (e.inverse.obj X)
this✝¹ : IsLeftAdjoint (e.functor ⋙ prod.functor.obj X ⋙ e.inverse)
this✝ : IsLeftAdjoint (e.inverse ⋙ e.functor ⋙ prod.functor.obj X ⋙ e.inverse)
this : (e.inverse ⋙ e.functor ⋙ prod.functor.obj X ⋙ e.inverse) ⋙ e.functor ≅ prod.functor.obj X
⊢ IsLeftAdjoint (MonoidalCategory.tensorLeft X)

Next tactic:
apply Adjunction.leftAdjointOfNatIso this
instance [SMul R ℝ] [SMul S ℝ] [SMulCommClass R S ℝ] : SMulCommClass R S ℂ where
  smul_comm r s x := by 

Proof state:
R : Type u_1
S : Type u_2
inst✝² : SMul R ℝ
inst✝¹ : SMul S ℝ
inst✝ : SMulCommClass R S ℝ
r : R
s : S
x : ℂ
⊢ r • s • x = s • r • x

Next tactic:
ext