l3lab/ntp-mathlib huggingface dataset:
@[reassoc (attr := simp)]
theorem tensor_inv_hom_id' {V W X Y Z : C} (f : V ⟶ W) [IsIso f] (g : X ⟶ Y) (h : Y ⟶ Z) :
    (g ⊗ inv f) ≫ (h ⊗ f) = (g ⊗ 𝟙 W) ≫ (h ⊗ 𝟙 W) := by
  

Proof state:
C✝ : Type u
𝒞 : Category.{v, u} C✝
inst✝³ : MonoidalCategory C✝
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : MonoidalCategory C
U V✝ W✝ X✝ Y✝ Z✝ V W X Y Z : C
f : V ⟶ W
inst✝ : IsIso f
g : X ⟶ Y
h : Y ⟶ Z
⊢ (g ⊗ inv f) ≫ (h ⊗ f) = (g ⊗ 𝟙 W) ≫ (h ⊗ 𝟙 W)

Next tactic:
rw [← tensor_comp, IsIso.inv_hom_id, comp_tensor_id]
/-- The associator as a natural isomorphism. -/
@[simps!]
def associatorNatIso : leftAssocTensor C ≅ rightAssocTensor C :=
  NatIso.ofComponents
    (by
      

Proof state:
C✝ : Type u
𝒞 : Category.{v, u} C✝
inst✝² : MonoidalCategory C✝
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : MonoidalCategory C
⊢ (X : C × C × C) → (leftAssocTensor C).obj X ≅ (rightAssocTensor C).obj X

Next tactic:
intros
/-- The associator as a natural isomorphism. -/
@[simps!]
def associatorNatIso : leftAssocTensor C ≅ rightAssocTensor C :=
  NatIso.ofComponents
    (by
      intros
      

Proof state:
C✝ : Type u
𝒞 : Category.{v, u} C✝
inst✝² : MonoidalCategory C✝
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : MonoidalCategory C
X✝ : C × C × C
⊢ (leftAssocTensor C).obj X✝ ≅ (rightAssocTensor C).obj X✝

Next tactic:
apply MonoidalCategory.associator
/-- The associator as a natural isomorphism. -/
@[simps!]
def associatorNatIso : leftAssocTensor C ≅ rightAssocTensor C :=
  NatIso.ofComponents
    (by
      intros
      apply MonoidalCategory.associator)
    (by
      

Proof state:
C✝ : Type u
𝒞 : Category.{v, u} C✝
inst✝² : MonoidalCategory C✝
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : MonoidalCategory C
⊢ ∀ {X Y : C × C × C} (f : X ⟶ Y),
    (leftAssocTensor C).map f ≫ (α_ Y.1 Y.2.1 Y.2.2).hom = (α_ X.1 X.2.1 X.2.2).hom ≫ (rightAssocTensor C).map f

Next tactic:
intros
/-- The associator as a natural isomorphism. -/
@[simps!]
def associatorNatIso : leftAssocTensor C ≅ rightAssocTensor C :=
  NatIso.ofComponents
    (by
      intros
      apply MonoidalCategory.associator)
    (by
      intros
      

Proof state:
C✝ : Type u
𝒞 : Category.{v, u} C✝
inst✝² : MonoidalCategory C✝
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : MonoidalCategory C
X✝ Y✝ : C × C × C
f✝ : X✝ ⟶ Y✝
⊢ (leftAssocTensor C).map f✝ ≫ (α_ Y✝.1 Y✝.2.1 Y✝.2.2).hom = (α_ X✝.1 X✝.2.1 X✝.2.2).hom ≫ (rightAssocTensor C).map f✝

Next tactic:
apply MonoidalCategory.associator_naturality
/-- The left unitor as a natural isomorphism. -/
@[simps!]
def leftUnitorNatIso : tensorUnitLeft C ≅ 𝟭 C :=
  NatIso.ofComponents
    (by
      

Proof state:
C✝ : Type u
𝒞 : Category.{v, u} C✝
inst✝² : MonoidalCategory C✝
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : MonoidalCategory C
⊢ (X : C) → (tensorUnitLeft C).obj X ≅ (𝟭 C).obj X

Next tactic:
intros
/-- The left unitor as a natural isomorphism. -/
@[simps!]
def leftUnitorNatIso : tensorUnitLeft C ≅ 𝟭 C :=
  NatIso.ofComponents
    (by
      intros
      

Proof state:
C✝ : Type u
𝒞 : Category.{v, u} C✝
inst✝² : MonoidalCategory C✝
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : MonoidalCategory C
X✝ : C
⊢ (tensorUnitLeft C).obj X✝ ≅ (𝟭 C).obj X✝

Next tactic:
apply MonoidalCategory.leftUnitor
/-- The left unitor as a natural isomorphism. -/
@[simps!]
def leftUnitorNatIso : tensorUnitLeft C ≅ 𝟭 C :=
  NatIso.ofComponents
    (by
      intros
      apply MonoidalCategory.leftUnitor)
    (by
      

Proof state:
C✝ : Type u
𝒞 : Category.{v, u} C✝
inst✝² : MonoidalCategory C✝
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : MonoidalCategory C
⊢ ∀ {X Y : C} (f : X ⟶ Y), (tensorUnitLeft C).map f ≫ (λ_ Y).hom = (λ_ X).hom ≫ (𝟭 C).map f

Next tactic:
intros
/-- The left unitor as a natural isomorphism. -/
@[simps!]
def leftUnitorNatIso : tensorUnitLeft C ≅ 𝟭 C :=
  NatIso.ofComponents
    (by
      intros
      apply MonoidalCategory.leftUnitor)
    (by
      intros
      

Proof state:
C✝ : Type u
𝒞 : Category.{v, u} C✝
inst✝² : MonoidalCategory C✝
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : MonoidalCategory C
X✝ Y✝ : C
f✝ : X✝ ⟶ Y✝
⊢ (tensorUnitLeft C).map f✝ ≫ (λ_ Y✝).hom = (λ_ X✝).hom ≫ (𝟭 C).map f✝

Next tactic:
apply MonoidalCategory.leftUnitor_naturality
/-- The right unitor as a natural isomorphism. -/
@[simps!]
def rightUnitorNatIso : tensorUnitRight C ≅ 𝟭 C :=
  NatIso.ofComponents
    (by
      

Proof state:
C✝ : Type u
𝒞 : Category.{v, u} C✝
inst✝² : MonoidalCategory C✝
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : MonoidalCategory C
⊢ (X : C) → (tensorUnitRight C).obj X ≅ (𝟭 C).obj X

Next tactic:
intros
/-- The right unitor as a natural isomorphism. -/
@[simps!]
def rightUnitorNatIso : tensorUnitRight C ≅ 𝟭 C :=
  NatIso.ofComponents
    (by
      intros
      

Proof state:
C✝ : Type u
𝒞 : Category.{v, u} C✝
inst✝² : MonoidalCategory C✝
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : MonoidalCategory C
X✝ : C
⊢ (tensorUnitRight C).obj X✝ ≅ (𝟭 C).obj X✝

Next tactic:
apply MonoidalCategory.rightUnitor
/-- The right unitor as a natural isomorphism. -/
@[simps!]
def rightUnitorNatIso : tensorUnitRight C ≅ 𝟭 C :=
  NatIso.ofComponents
    (by
      intros
      apply MonoidalCategory.rightUnitor)
    (by
      

Proof state:
C✝ : Type u
𝒞 : Category.{v, u} C✝
inst✝² : MonoidalCategory C✝
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : MonoidalCategory C
⊢ ∀ {X Y : C} (f : X ⟶ Y), (tensorUnitRight C).map f ≫ (ρ_ Y).hom = (ρ_ X).hom ≫ (𝟭 C).map f

Next tactic:
intros
/-- The right unitor as a natural isomorphism. -/
@[simps!]
def rightUnitorNatIso : tensorUnitRight C ≅ 𝟭 C :=
  NatIso.ofComponents
    (by
      intros
      apply MonoidalCategory.rightUnitor)
    (by
      intros
      

Proof state:
C✝ : Type u
𝒞 : Category.{v, u} C✝
inst✝² : MonoidalCategory C✝
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : MonoidalCategory C
X✝ Y✝ : C
f✝ : X✝ ⟶ Y✝
⊢ (tensorUnitRight C).map f✝ ≫ (ρ_ Y✝).hom = (ρ_ X✝).hom ≫ (𝟭 C).map f✝

Next tactic:
apply MonoidalCategory.rightUnitor_naturality
/-- Tensoring on the left with `X ⊗ Y` is naturally isomorphic to
tensoring on the left with `Y`, and then again with `X`.
-/
def tensorLeftTensor (X Y : C) : tensorLeft (X ⊗ Y) ≅ tensorLeft Y ⋙ tensorLeft X :=
  NatIso.ofComponents (associator _ _) fun {Z} {Z'} f => by
    

Proof state:
C✝¹ : Type u
𝒞 : Category.{v, u} C✝¹
inst✝⁴ : MonoidalCategory C✝¹
C✝ : Type u
inst✝³ : Category.{v, u} C✝
inst✝² : MonoidalCategory C✝
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : MonoidalCategory C
X Y Z Z' : C
f : Z ⟶ Z'
⊢ (tensorLeft (X ⊗ Y)).map f ≫ (α_ X Y Z').hom = (α_ X Y Z).hom ≫ (tensorLeft Y ⋙ tensorLeft X).map f

Next tactic:
dsimp
/-- Tensoring on the left with `X ⊗ Y` is naturally isomorphic to
tensoring on the left with `Y`, and then again with `X`.
-/
def tensorLeftTensor (X Y : C) : tensorLeft (X ⊗ Y) ≅ tensorLeft Y ⋙ tensorLeft X :=
  NatIso.ofComponents (associator _ _) fun {Z} {Z'} f => by
    dsimp
    

Proof state:
C✝¹ : Type u
𝒞 : Category.{v, u} C✝¹
inst✝⁴ : MonoidalCategory C✝¹
C✝ : Type u
inst✝³ : Category.{v, u} C✝
inst✝² : MonoidalCategory C✝
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : MonoidalCategory C
X Y Z Z' : C
f : Z ⟶ Z'
⊢ (𝟙 (X ⊗ Y) ⊗ f) ≫ (α_ X Y Z').hom = (α_ X Y Z).hom ≫ (𝟙 X ⊗ 𝟙 Y ⊗ f)

Next tactic:
rw [← tensor_id]
/-- Tensoring on the left with `X ⊗ Y` is naturally isomorphic to
tensoring on the left with `Y`, and then again with `X`.
-/
def tensorLeftTensor (X Y : C) : tensorLeft (X ⊗ Y) ≅ tensorLeft Y ⋙ tensorLeft X :=
  NatIso.ofComponents (associator _ _) fun {Z} {Z'} f => by
    dsimp
    rw [← tensor_id]
    

Proof state:
C✝¹ : Type u
𝒞 : Category.{v, u} C✝¹
inst✝⁴ : MonoidalCategory C✝¹
C✝ : Type u
inst✝³ : Category.{v, u} C✝
inst✝² : MonoidalCategory C✝
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : MonoidalCategory C
X Y Z Z' : C
f : Z ⟶ Z'
⊢ ((𝟙 X ⊗ 𝟙 Y) ⊗ f) ≫ (α_ X Y Z').hom = (α_ X Y Z).hom ≫ (𝟙 X ⊗ 𝟙 Y ⊗ f)

Next tactic:
apply associator_naturality
@[simp]
theorem tensorLeftTensor_inv_app (X Y Z : C) :
    (tensorLeftTensor X Y).inv.app Z = (associator X Y Z).inv := by 

Proof state:
C✝¹ : Type u
𝒞 : Category.{v, u} C✝¹
inst✝⁴ : MonoidalCategory C✝¹
C✝ : Type u
inst✝³ : Category.{v, u} C✝
inst✝² : MonoidalCategory C✝
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : MonoidalCategory C
X Y Z : C
⊢ (tensorLeftTensor X Y).inv.app Z = (α_ X Y Z).inv

Next tactic:
simp [tensorLeftTensor]
instance : Faithful (tensoringLeft C) where
  map_injective {X} {Y} f g h := by
    

Proof state:
C✝² : Type u
𝒞 : Category.{v, u} C✝²
inst✝⁶ : MonoidalCategory C✝²
C✝¹ : Type u
inst✝⁵ : Category.{v, u} C✝¹
inst✝⁴ : MonoidalCategory C✝¹
C✝ : Type u
inst✝³ : Category.{v, u} C✝
inst✝² : MonoidalCategory C✝
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : MonoidalCategory C
X Y : C
f g : X ⟶ Y
h : (tensoringLeft C).map f = (tensoringLeft C).map g
⊢ f = g

Next tactic:
injections h
instance : Faithful (tensoringLeft C) where
  map_injective {X} {Y} f g h := by
    injections h
    

Proof state:
C✝² : Type u
𝒞 : Category.{v, u} C✝²
inst✝⁶ : MonoidalCategory C✝²
C✝¹ : Type u
inst✝⁵ : Category.{v, u} C✝¹
inst✝⁴ : MonoidalCategory C✝¹
C✝ : Type u
inst✝³ : Category.{v, u} C✝
inst✝² : MonoidalCategory C✝
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : MonoidalCategory C
X Y : C
f g : X ⟶ Y
h : (fun Z => f ⊗ 𝟙 Z) = fun Z => g ⊗ 𝟙 Z
⊢ f = g

Next tactic:
replace h := congr_fun h (𝟙_ C)
instance : Faithful (tensoringLeft C) where
  map_injective {X} {Y} f g h := by
    injections h
    replace h := congr_fun h (𝟙_ C)
    

Proof state:
C✝² : Type u
𝒞 : Category.{v, u} C✝²
inst✝⁶ : MonoidalCategory C✝²
C✝¹ : Type u
inst✝⁵ : Category.{v, u} C✝¹
inst✝⁴ : MonoidalCategory C✝¹
C✝ : Type u
inst✝³ : Category.{v, u} C✝
inst✝² : MonoidalCategory C✝
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : MonoidalCategory C
X Y : C
f g : X ⟶ Y
h : f ⊗ 𝟙 (𝟙_ C) = g ⊗ 𝟙 (𝟙_ C)
⊢ f = g

Next tactic:
simpa using h
instance : Faithful (tensoringRight C) where
  map_injective {X} {Y} f g h := by
    

Proof state:
C✝² : Type u
𝒞 : Category.{v, u} C✝²
inst✝⁶ : MonoidalCategory C✝²
C✝¹ : Type u
inst✝⁵ : Category.{v, u} C✝¹
inst✝⁴ : MonoidalCategory C✝¹
C✝ : Type u
inst✝³ : Category.{v, u} C✝
inst✝² : MonoidalCategory C✝
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : MonoidalCategory C
X Y : C
f g : X ⟶ Y
h : (tensoringRight C).map f = (tensoringRight C).map g
⊢ f = g

Next tactic:
injections h
instance : Faithful (tensoringRight C) where
  map_injective {X} {Y} f g h := by
    injections h
    

Proof state:
C✝² : Type u
𝒞 : Category.{v, u} C✝²
inst✝⁶ : MonoidalCategory C✝²
C✝¹ : Type u
inst✝⁵ : Category.{v, u} C✝¹
inst✝⁴ : MonoidalCategory C✝¹
C✝ : Type u
inst✝³ : Category.{v, u} C✝
inst✝² : MonoidalCategory C✝
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : MonoidalCategory C
X Y : C
f g : X ⟶ Y
h : (fun Z => 𝟙 Z ⊗ f) = fun Z => 𝟙 Z ⊗ g
⊢ f = g

Next tactic:
replace h := congr_fun h (𝟙_ C)
instance : Faithful (tensoringRight C) where
  map_injective {X} {Y} f g h := by
    injections h
    replace h := congr_fun h (𝟙_ C)
    

Proof state:
C✝² : Type u
𝒞 : Category.{v, u} C✝²
inst✝⁶ : MonoidalCategory C✝²
C✝¹ : Type u
inst✝⁵ : Category.{v, u} C✝¹
inst✝⁴ : MonoidalCategory C✝¹
C✝ : Type u
inst✝³ : Category.{v, u} C✝
inst✝² : MonoidalCategory C✝
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : MonoidalCategory C
X Y : C
f g : X ⟶ Y
h : 𝟙 (𝟙_ C) ⊗ f = 𝟙 (𝟙_ C) ⊗ g
⊢ f = g

Next tactic:
simpa using h
/-- Tensoring on the right with `X ⊗ Y` is naturally isomorphic to
tensoring on the right with `X`, and then again with `Y`.
-/
def tensorRightTensor (X Y : C) : tensorRight (X ⊗ Y) ≅ tensorRight X ⋙ tensorRight Y :=
  NatIso.ofComponents (fun Z => (associator Z X Y).symm) fun {Z} {Z'} f => by
    

Proof state:
C✝³ : Type u
𝒞 : Category.{v, u} C✝³
inst✝⁸ : MonoidalCategory C✝³
C✝² : Type u
inst✝⁷ : Category.{v, u} C✝²
inst✝⁶ : MonoidalCategory C✝²
C✝¹ : Type u
inst✝⁵ : Category.{v, u} C✝¹
inst✝⁴ : MonoidalCategory C✝¹
C✝ : Type u
inst✝³ : Category.{v, u} C✝
inst✝² : MonoidalCategory C✝
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : MonoidalCategory C
X Y Z Z' : C
f : Z ⟶ Z'
⊢ (tensorRight (X ⊗ Y)).map f ≫ ((fun Z => (α_ Z X Y).symm) Z').hom =
    ((fun Z => (α_ Z X Y).symm) Z).hom ≫ (tensorRight X ⋙ tensorRight Y).map f

Next tactic:
dsimp
/-- Tensoring on the right with `X ⊗ Y` is naturally isomorphic to
tensoring on the right with `X`, and then again with `Y`.
-/
def tensorRightTensor (X Y : C) : tensorRight (X ⊗ Y) ≅ tensorRight X ⋙ tensorRight Y :=
  NatIso.ofComponents (fun Z => (associator Z X Y).symm) fun {Z} {Z'} f => by
    dsimp
    

Proof state:
C✝³ : Type u
𝒞 : Category.{v, u} C✝³
inst✝⁸ : MonoidalCategory C✝³
C✝² : Type u
inst✝⁷ : Category.{v, u} C✝²
inst✝⁶ : MonoidalCategory C✝²
C✝¹ : Type u
inst✝⁵ : Category.{v, u} C✝¹
inst✝⁴ : MonoidalCategory C✝¹
C✝ : Type u
inst✝³ : Category.{v, u} C✝
inst✝² : MonoidalCategory C✝
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : MonoidalCategory C
X Y Z Z' : C
f : Z ⟶ Z'
⊢ (f ⊗ 𝟙 (X ⊗ Y)) ≫ (α_ Z' X Y).inv = (α_ Z X Y).inv ≫ ((f ⊗ 𝟙 X) ⊗ 𝟙 Y)

Next tactic:
rw [← tensor_id]
/-- Tensoring on the right with `X ⊗ Y` is naturally isomorphic to
tensoring on the right with `X`, and then again with `Y`.
-/
def tensorRightTensor (X Y : C) : tensorRight (X ⊗ Y) ≅ tensorRight X ⋙ tensorRight Y :=
  NatIso.ofComponents (fun Z => (associator Z X Y).symm) fun {Z} {Z'} f => by
    dsimp
    rw [← tensor_id]
    

Proof state:
C✝³ : Type u
𝒞 : Category.{v, u} C✝³
inst✝⁸ : MonoidalCategory C✝³
C✝² : Type u
inst✝⁷ : Category.{v, u} C✝²
inst✝⁶ : MonoidalCategory C✝²
C✝¹ : Type u
inst✝⁵ : Category.{v, u} C✝¹
inst✝⁴ : MonoidalCategory C✝¹
C✝ : Type u
inst✝³ : Category.{v, u} C✝
inst✝² : MonoidalCategory C✝
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : MonoidalCategory C
X Y Z Z' : C
f : Z ⟶ Z'
⊢ (f ⊗ 𝟙 X ⊗ 𝟙 Y) ≫ (α_ Z' X Y).inv = (α_ Z X Y).inv ≫ ((f ⊗ 𝟙 X) ⊗ 𝟙 Y)

Next tactic:
apply associator_inv_naturality
@[simp]
theorem tensorRightTensor_inv_app (X Y Z : C) :
    (tensorRightTensor X Y).inv.app Z = (associator Z X Y).hom := by 

Proof state:
C✝³ : Type u
𝒞 : Category.{v, u} C✝³
inst✝⁸ : MonoidalCategory C✝³
C✝² : Type u
inst✝⁷ : Category.{v, u} C✝²
inst✝⁶ : MonoidalCategory C✝²
C✝¹ : Type u
inst✝⁵ : Category.{v, u} C✝¹
inst✝⁴ : MonoidalCategory C✝¹
C✝ : Type u
inst✝³ : Category.{v, u} C✝
inst✝² : MonoidalCategory C✝
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : MonoidalCategory C
X Y Z : C
⊢ (tensorRightTensor X Y).inv.app Z = (α_ Z X Y).hom

Next tactic:
simp [tensorRightTensor]
@[simps! tensorObj tensorHom tensorUnit associator]
instance prodMonoidal : MonoidalCategory (C₁ × C₂) where
  tensorObj X Y := (X.1 ⊗ Y.1, X.2 ⊗ Y.2)
  tensorHom f g := (f.1 ⊗ g.1, f.2 ⊗ g.2)
  whiskerLeft X _ _ f := (whiskerLeft X.1 f.1, whiskerLeft X.2 f.2)
  whiskerRight f X := (whiskerRight f.1 X.1, whiskerRight f.2 X.2)
  tensorHom_def := by 

Proof state:
C : Type u
𝒞 : Category.{v, u} C
inst✝⁴ : MonoidalCategory C
C₁ : Type u₁
inst✝³ : Category.{v₁, u₁} C₁
inst✝² : MonoidalCategory C₁
C₂ : Type u₂
inst✝¹ : Category.{v₂, u₂} C₂
inst✝ : MonoidalCategory C₂
⊢ ∀ {X₁ Y₁ X₂ Y₂ : C₁ × C₂} (f : X₁ ⟶ Y₁) (g : X₂ ⟶ Y₂), f ⊗ g = f ▷ X₂ ≫ Y₁ ◁ g

Next tactic:
simp [tensorHom_def]
@[simp]
theorem prodMonoidal_leftUnitor_hom_fst (X : C₁ × C₂) :
    ((λ_ X).hom : 𝟙_ _ ⊗ X ⟶ X).1 = (λ_ X.1).hom := by
  

Proof state:
C : Type u
𝒞 : Category.{v, u} C
inst✝⁴ : MonoidalCategory C
C₁ : Type u₁
inst✝³ : Category.{v₁, u₁} C₁
inst✝² : MonoidalCategory C₁
C₂ : Type u₂
inst✝¹ : Category.{v₂, u₂} C₂
inst✝ : MonoidalCategory C₂
X : C₁ × C₂
⊢ (λ_ X).hom.1 = (λ_ X.1).hom

Next tactic:
cases X
@[simp]
theorem prodMonoidal_leftUnitor_hom_fst (X : C₁ × C₂) :
    ((λ_ X).hom : 𝟙_ _ ⊗ X ⟶ X).1 = (λ_ X.1).hom := by
  cases X
  

Proof state:
case mk
C : Type u
𝒞 : Category.{v, u} C
inst✝⁴ : MonoidalCategory C
C₁ : Type u₁
inst✝³ : Category.{v₁, u₁} C₁
inst✝² : MonoidalCategory C₁
C₂ : Type u₂
inst✝¹ : Category.{v₂, u₂} C₂
inst✝ : MonoidalCategory C₂
fst✝ : C₁
snd✝ : C₂
⊢ (λ_ (fst✝, snd✝)).hom.1 = (λ_ (fst✝, snd✝).1).hom

Next tactic:
rfl
@[simp]
theorem prodMonoidal_leftUnitor_hom_snd (X : C₁ × C₂) :
    ((λ_ X).hom : 𝟙_ _ ⊗ X ⟶ X).2 = (λ_ X.2).hom := by
  

Proof state:
C : Type u
𝒞 : Category.{v, u} C
inst✝⁴ : MonoidalCategory C
C₁ : Type u₁
inst✝³ : Category.{v₁, u₁} C₁
inst✝² : MonoidalCategory C₁
C₂ : Type u₂
inst✝¹ : Category.{v₂, u₂} C₂
inst✝ : MonoidalCategory C₂
X : C₁ × C₂
⊢ (λ_ X).hom.2 = (λ_ X.2).hom

Next tactic:
cases X
@[simp]
theorem prodMonoidal_leftUnitor_hom_snd (X : C₁ × C₂) :
    ((λ_ X).hom : 𝟙_ _ ⊗ X ⟶ X).2 = (λ_ X.2).hom := by
  cases X
  

Proof state:
case mk
C : Type u
𝒞 : Category.{v, u} C
inst✝⁴ : MonoidalCategory C
C₁ : Type u₁
inst✝³ : Category.{v₁, u₁} C₁
inst✝² : MonoidalCategory C₁
C₂ : Type u₂
inst✝¹ : Category.{v₂, u₂} C₂
inst✝ : MonoidalCategory C₂
fst✝ : C₁
snd✝ : C₂
⊢ (λ_ (fst✝, snd✝)).hom.2 = (λ_ (fst✝, snd✝).2).hom

Next tactic:
rfl
@[simp]
theorem prodMonoidal_leftUnitor_inv_fst (X : C₁ × C₂) :
    ((λ_ X).inv : X ⟶ 𝟙_ _ ⊗ X).1 = (λ_ X.1).inv := by
  

Proof state:
C : Type u
𝒞 : Category.{v, u} C
inst✝⁴ : MonoidalCategory C
C₁ : Type u₁
inst✝³ : Category.{v₁, u₁} C₁
inst✝² : MonoidalCategory C₁
C₂ : Type u₂
inst✝¹ : Category.{v₂, u₂} C₂
inst✝ : MonoidalCategory C₂
X : C₁ × C₂
⊢ (λ_ X).inv.1 = (λ_ X.1).inv

Next tactic:
cases X
@[simp]
theorem prodMonoidal_leftUnitor_inv_fst (X : C₁ × C₂) :
    ((λ_ X).inv : X ⟶ 𝟙_ _ ⊗ X).1 = (λ_ X.1).inv := by
  cases X
  

Proof state:
case mk
C : Type u
𝒞 : Category.{v, u} C
inst✝⁴ : MonoidalCategory C
C₁ : Type u₁
inst✝³ : Category.{v₁, u₁} C₁
inst✝² : MonoidalCategory C₁
C₂ : Type u₂
inst✝¹ : Category.{v₂, u₂} C₂
inst✝ : MonoidalCategory C₂
fst✝ : C₁
snd✝ : C₂
⊢ (λ_ (fst✝, snd✝)).inv.1 = (λ_ (fst✝, snd✝).1).inv

Next tactic:
rfl
@[simp]
theorem prodMonoidal_leftUnitor_inv_snd (X : C₁ × C₂) :
    ((λ_ X).inv : X ⟶ 𝟙_ _ ⊗ X).2 = (λ_ X.2).inv := by
  

Proof state:
C : Type u
𝒞 : Category.{v, u} C
inst✝⁴ : MonoidalCategory C
C₁ : Type u₁
inst✝³ : Category.{v₁, u₁} C₁
inst✝² : MonoidalCategory C₁
C₂ : Type u₂
inst✝¹ : Category.{v₂, u₂} C₂
inst✝ : MonoidalCategory C₂
X : C₁ × C₂
⊢ (λ_ X).inv.2 = (λ_ X.2).inv

Next tactic:
cases X
@[simp]
theorem prodMonoidal_leftUnitor_inv_snd (X : C₁ × C₂) :
    ((λ_ X).inv : X ⟶ 𝟙_ _ ⊗ X).2 = (λ_ X.2).inv := by
  cases X
  

Proof state:
case mk
C : Type u
𝒞 : Category.{v, u} C
inst✝⁴ : MonoidalCategory C
C₁ : Type u₁
inst✝³ : Category.{v₁, u₁} C₁
inst✝² : MonoidalCategory C₁
C₂ : Type u₂
inst✝¹ : Category.{v₂, u₂} C₂
inst✝ : MonoidalCategory C₂
fst✝ : C₁
snd✝ : C₂
⊢ (λ_ (fst✝, snd✝)).inv.2 = (λ_ (fst✝, snd✝).2).inv

Next tactic:
rfl
@[simp]
theorem prodMonoidal_rightUnitor_hom_fst (X : C₁ × C₂) :
    ((ρ_ X).hom : X ⊗ 𝟙_ _ ⟶ X).1 = (ρ_ X.1).hom := by
  

Proof state:
C : Type u
𝒞 : Category.{v, u} C
inst✝⁴ : MonoidalCategory C
C₁ : Type u₁
inst✝³ : Category.{v₁, u₁} C₁
inst✝² : MonoidalCategory C₁
C₂ : Type u₂
inst✝¹ : Category.{v₂, u₂} C₂
inst✝ : MonoidalCategory C₂
X : C₁ × C₂
⊢ (ρ_ X).hom.1 = (ρ_ X.1).hom

Next tactic:
cases X
@[simp]
theorem prodMonoidal_rightUnitor_hom_fst (X : C₁ × C₂) :
    ((ρ_ X).hom : X ⊗ 𝟙_ _ ⟶ X).1 = (ρ_ X.1).hom := by
  cases X
  

Proof state:
case mk
C : Type u
𝒞 : Category.{v, u} C
inst✝⁴ : MonoidalCategory C
C₁ : Type u₁
inst✝³ : Category.{v₁, u₁} C₁
inst✝² : MonoidalCategory C₁
C₂ : Type u₂
inst✝¹ : Category.{v₂, u₂} C₂
inst✝ : MonoidalCategory C₂
fst✝ : C₁
snd✝ : C₂
⊢ (ρ_ (fst✝, snd✝)).hom.1 = (ρ_ (fst✝, snd✝).1).hom

Next tactic:
rfl
@[simp]
theorem prodMonoidal_rightUnitor_hom_snd (X : C₁ × C₂) :
    ((ρ_ X).hom : X ⊗ 𝟙_ _ ⟶ X).2 = (ρ_ X.2).hom := by
  

Proof state:
C : Type u
𝒞 : Category.{v, u} C
inst✝⁴ : MonoidalCategory C
C₁ : Type u₁
inst✝³ : Category.{v₁, u₁} C₁
inst✝² : MonoidalCategory C₁
C₂ : Type u₂
inst✝¹ : Category.{v₂, u₂} C₂
inst✝ : MonoidalCategory C₂
X : C₁ × C₂
⊢ (ρ_ X).hom.2 = (ρ_ X.2).hom

Next tactic:
cases X
@[simp]
theorem prodMonoidal_rightUnitor_hom_snd (X : C₁ × C₂) :
    ((ρ_ X).hom : X ⊗ 𝟙_ _ ⟶ X).2 = (ρ_ X.2).hom := by
  cases X
  

Proof state:
case mk
C : Type u
𝒞 : Category.{v, u} C
inst✝⁴ : MonoidalCategory C
C₁ : Type u₁
inst✝³ : Category.{v₁, u₁} C₁
inst✝² : MonoidalCategory C₁
C₂ : Type u₂
inst✝¹ : Category.{v₂, u₂} C₂
inst✝ : MonoidalCategory C₂
fst✝ : C₁
snd✝ : C₂
⊢ (ρ_ (fst✝, snd✝)).hom.2 = (ρ_ (fst✝, snd✝).2).hom

Next tactic:
rfl
@[simp]
theorem prodMonoidal_rightUnitor_inv_fst (X : C₁ × C₂) :
    ((ρ_ X).inv : X ⟶ X ⊗ 𝟙_ _).1 = (ρ_ X.1).inv := by
  

Proof state:
C : Type u
𝒞 : Category.{v, u} C
inst✝⁴ : MonoidalCategory C
C₁ : Type u₁
inst✝³ : Category.{v₁, u₁} C₁
inst✝² : MonoidalCategory C₁
C₂ : Type u₂
inst✝¹ : Category.{v₂, u₂} C₂
inst✝ : MonoidalCategory C₂
X : C₁ × C₂
⊢ (ρ_ X).inv.1 = (ρ_ X.1).inv

Next tactic:
cases X
@[simp]
theorem prodMonoidal_rightUnitor_inv_fst (X : C₁ × C₂) :
    ((ρ_ X).inv : X ⟶ X ⊗ 𝟙_ _).1 = (ρ_ X.1).inv := by
  cases X
  

Proof state:
case mk
C : Type u
𝒞 : Category.{v, u} C
inst✝⁴ : MonoidalCategory C
C₁ : Type u₁
inst✝³ : Category.{v₁, u₁} C₁
inst✝² : MonoidalCategory C₁
C₂ : Type u₂
inst✝¹ : Category.{v₂, u₂} C₂
inst✝ : MonoidalCategory C₂
fst✝ : C₁
snd✝ : C₂
⊢ (ρ_ (fst✝, snd✝)).inv.1 = (ρ_ (fst✝, snd✝).1).inv

Next tactic:
rfl
@[simp]
theorem prodMonoidal_rightUnitor_inv_snd (X : C₁ × C₂) :
    ((ρ_ X).inv : X ⟶ X ⊗ 𝟙_ _).2 = (ρ_ X.2).inv := by
  

Proof state:
C : Type u
𝒞 : Category.{v, u} C
inst✝⁴ : MonoidalCategory C
C₁ : Type u₁
inst✝³ : Category.{v₁, u₁} C₁
inst✝² : MonoidalCategory C₁
C₂ : Type u₂
inst✝¹ : Category.{v₂, u₂} C₂
inst✝ : MonoidalCategory C₂
X : C₁ × C₂
⊢ (ρ_ X).inv.2 = (ρ_ X.2).inv

Next tactic:
cases X
@[simp]
theorem prodMonoidal_rightUnitor_inv_snd (X : C₁ × C₂) :
    ((ρ_ X).inv : X ⟶ X ⊗ 𝟙_ _).2 = (ρ_ X.2).inv := by
  cases X
  

Proof state:
case mk
C : Type u
𝒞 : Category.{v, u} C
inst✝⁴ : MonoidalCategory C
C₁ : Type u₁
inst✝³ : Category.{v₁, u₁} C₁
inst✝² : MonoidalCategory C₁
C₂ : Type u₂
inst✝¹ : Category.{v₂, u₂} C₂
inst✝ : MonoidalCategory C₂
fst✝ : C₁
snd✝ : C₂
⊢ (ρ_ (fst✝, snd✝)).inv.2 = (ρ_ (fst✝, snd✝).2).inv

Next tactic:
rfl
/-- A pair (i, j) is contained in the antidiagonal of `n` if and only if `i + j = n`. -/
@[simp]
theorem mem_antidiagonal {n : ℕ} {x : ℕ × ℕ} : x ∈ antidiagonal n ↔ x.1 + x.2 = n := by
  

Proof state:
n : ℕ
x : ℕ × ℕ
⊢ x ∈ antidiagonal n ↔ x.1 + x.2 = n

Next tactic:
rw [antidiagonal, mem_map]
/-- A pair (i, j) is contained in the antidiagonal of `n` if and only if `i + j = n`. -/
@[simp]
theorem mem_antidiagonal {n : ℕ} {x : ℕ × ℕ} : x ∈ antidiagonal n ↔ x.1 + x.2 = n := by
  rw [antidiagonal, mem_map]; 

Proof state:
n : ℕ
x : ℕ × ℕ
⊢ (∃ a ∈ range (n + 1), (a, n - a) = x) ↔ x.1 + x.2 = n

Next tactic:
constructor
/-- A pair (i, j) is contained in the antidiagonal of `n` if and only if `i + j = n`. -/
@[simp]
theorem mem_antidiagonal {n : ℕ} {x : ℕ × ℕ} : x ∈ antidiagonal n ↔ x.1 + x.2 = n := by
  rw [antidiagonal, mem_map]; constructor
  · 

Proof state:
case mp
n : ℕ
x : ℕ × ℕ
⊢ (∃ a ∈ range (n + 1), (a, n - a) = x) → x.1 + x.2 = n

Next tactic:
rintro ⟨i, hi, rfl⟩
/-- A pair (i, j) is contained in the antidiagonal of `n` if and only if `i + j = n`. -/
@[simp]
theorem mem_antidiagonal {n : ℕ} {x : ℕ × ℕ} : x ∈ antidiagonal n ↔ x.1 + x.2 = n := by
  rw [antidiagonal, mem_map]; constructor
  · rintro ⟨i, hi, rfl⟩
    

Proof state:
case mp.intro.intro
n i : ℕ
hi : i ∈ range (n + 1)
⊢ (i, n - i).1 + (i, n - i).2 = n

Next tactic:
rw [mem_range, lt_succ_iff] at hi
/-- A pair (i, j) is contained in the antidiagonal of `n` if and only if `i + j = n`. -/
@[simp]
theorem mem_antidiagonal {n : ℕ} {x : ℕ × ℕ} : x ∈ antidiagonal n ↔ x.1 + x.2 = n := by
  rw [antidiagonal, mem_map]; constructor
  · rintro ⟨i, hi, rfl⟩
    rw [mem_range, lt_succ_iff] at hi
    

Proof state:
case mp.intro.intro
n i : ℕ
hi : i ≤ n
⊢ (i, n - i).1 + (i, n - i).2 = n

Next tactic:
exact add_tsub_cancel_of_le hi
/-- A pair (i, j) is contained in the antidiagonal of `n` if and only if `i + j = n`. -/
@[simp]
theorem mem_antidiagonal {n : ℕ} {x : ℕ × ℕ} : x ∈ antidiagonal n ↔ x.1 + x.2 = n := by
  rw [antidiagonal, mem_map]; constructor
  · rintro ⟨i, hi, rfl⟩
    rw [mem_range, lt_succ_iff] at hi
    exact add_tsub_cancel_of_le hi
  · 

Proof state:
case mpr
n : ℕ
x : ℕ × ℕ
⊢ x.1 + x.2 = n → ∃ a ∈ range (n + 1), (a, n - a) = x

Next tactic:
rintro rfl