l3lab/ntp-mathlib huggingface dataset:
instance {α} [AddMonoid α] : LawfulApplicative (AddConst α) := by
  refine' { .. } <;> intros <;> 

Proof state:
case refine'_1
α : Type ?u.38625
inst✝ : AddMonoid α
α✝ β✝ : Type ?u.38630
⊢ mapConst = map ∘ Function.const β✝

Next tactic:
simp [add_assoc, (· <$> ·), Seq.seq, pure]
instance {α} [AddMonoid α] : LawfulApplicative (AddConst α) := by
  refine' { .. } <;> intros <;> 

Proof state:
case refine'_2
α : Type ?u.38625
inst✝ : AddMonoid α
α✝ : Type ?u.38630
x✝ : AddConst α α✝
⊢ id <$> x✝ = x✝

Next tactic:
simp [add_assoc, (· <$> ·), Seq.seq, pure]
instance {α} [AddMonoid α] : LawfulApplicative (AddConst α) := by
  refine' { .. } <;> intros <;> 

Proof state:
case refine'_3
α : Type ?u.38625
inst✝ : AddMonoid α
α✝ β✝ γ✝ : Type ?u.38630
g✝ : α✝ → β✝
h✝ : β✝ → γ✝
x✝ : AddConst α α✝
⊢ (h✝ ∘ g✝) <$> x✝ = h✝ <$> g✝ <$> x✝

Next tactic:
simp [add_assoc, (· <$> ·), Seq.seq, pure]
instance {α} [AddMonoid α] : LawfulApplicative (AddConst α) := by
  refine' { .. } <;> intros <;> 

Proof state:
case refine'_4
α : Type ?u.38625
inst✝ : AddMonoid α
α✝ β✝ : Type ?u.38630
x✝ : AddConst α α✝
y✝ : AddConst α β✝
⊢ (SeqLeft.seqLeft x✝ fun x => y✝) = Seq.seq (Function.const β✝ <$> x✝) fun x => y✝

Next tactic:
simp [add_assoc, (· <$> ·), Seq.seq, pure]
instance {α} [AddMonoid α] : LawfulApplicative (AddConst α) := by
  refine' { .. } <;> intros <;> 

Proof state:
case refine'_5
α : Type ?u.38625
inst✝ : AddMonoid α
α✝ β✝ : Type ?u.38630
x✝ : AddConst α α✝
y✝ : AddConst α β✝
⊢ (SeqRight.seqRight x✝ fun x => y✝) = Seq.seq (Function.const α✝ id <$> x✝) fun x => y✝

Next tactic:
simp [add_assoc, (· <$> ·), Seq.seq, pure]
instance {α} [AddMonoid α] : LawfulApplicative (AddConst α) := by
  refine' { .. } <;> intros <;> 

Proof state:
case refine'_6
α : Type ?u.38625
inst✝ : AddMonoid α
α✝ β✝ : Type ?u.38630
g✝ : α✝ → β✝
x✝ : AddConst α α✝
⊢ (Seq.seq (pure g✝) fun x => x✝) = g✝ <$> x✝

Next tactic:
simp [add_assoc, (· <$> ·), Seq.seq, pure]
instance {α} [AddMonoid α] : LawfulApplicative (AddConst α) := by
  refine' { .. } <;> intros <;> 

Proof state:
case refine'_7
α : Type ?u.38625
inst✝ : AddMonoid α
α✝ β✝ : Type ?u.38630
g✝ : α✝ → β✝
x✝ : α✝
⊢ g✝ <$> pure x✝ = pure (g✝ x✝)

Next tactic:
simp [add_assoc, (· <$> ·), Seq.seq, pure]
instance {α} [AddMonoid α] : LawfulApplicative (AddConst α) := by
  refine' { .. } <;> intros <;> 

Proof state:
case refine'_8
α : Type ?u.38625
inst✝ : AddMonoid α
α✝ β✝ : Type ?u.38630
g✝ : AddConst α (α✝ → β✝)
x✝ : α✝
⊢ (Seq.seq g✝ fun x => pure x✝) = (fun h => h x✝) <$> g✝

Next tactic:
simp [add_assoc, (· <$> ·), Seq.seq, pure]
instance {α} [AddMonoid α] : LawfulApplicative (AddConst α) := by
  refine' { .. } <;> intros <;> 

Proof state:
case refine'_9
α : Type ?u.38625
inst✝ : AddMonoid α
α✝ β✝ γ✝ : Type ?u.38630
x✝ : AddConst α α✝
g✝ : AddConst α (α✝ → β✝)
h✝ : AddConst α (β✝ → γ✝)
⊢ (Seq.seq h✝ fun x => Seq.seq g✝ fun x => x✝) = Seq.seq (Seq.seq (Function.comp <$> h✝) fun x => g✝) fun x => x✝

Next tactic:
simp [add_assoc, (· <$> ·), Seq.seq, pure]
instance {α} [AddMonoid α] : LawfulApplicative (AddConst α) := by
  refine' { .. } <;> intros <;> simp [add_assoc, (· <$> ·), Seq.seq, pure] <;> 

Proof state:
case refine'_1
α : Type ?u.38625
inst✝ : AddMonoid α
α✝ β✝ : Type ?u.38630
⊢ mapConst = Const.map ∘ Function.const β✝

Next tactic:
rfl
instance {α} [AddMonoid α] : LawfulApplicative (AddConst α) := by
  refine' { .. } <;> intros <;> simp [add_assoc, (· <$> ·), Seq.seq, pure] <;> 

Proof state:
case refine'_2
α : Type ?u.38625
inst✝ : AddMonoid α
α✝ : Type ?u.38630
x✝ : AddConst α α✝
⊢ Const.map id x✝ = x✝

Next tactic:
rfl
instance {α} [AddMonoid α] : LawfulApplicative (AddConst α) := by
  refine' { .. } <;> intros <;> simp [add_assoc, (· <$> ·), Seq.seq, pure] <;> 

Proof state:
case refine'_3
α : Type ?u.38625
inst✝ : AddMonoid α
α✝ β✝ γ✝ : Type ?u.38630
g✝ : α✝ → β✝
h✝ : β✝ → γ✝
x✝ : AddConst α α✝
⊢ Const.map (h✝ ∘ g✝) x✝ = Const.map h✝ (Const.map g✝ x✝)

Next tactic:
rfl
instance {α} [AddMonoid α] : LawfulApplicative (AddConst α) := by
  refine' { .. } <;> intros <;> simp [add_assoc, (· <$> ·), Seq.seq, pure] <;> 

Proof state:
case refine'_4
α : Type ?u.38625
inst✝ : AddMonoid α
α✝ β✝ : Type ?u.38630
x✝ : AddConst α α✝
y✝ : AddConst α β✝
⊢ (SeqLeft.seqLeft x✝ fun x => y✝) = Const.map (Function.const β✝) x✝ + y✝

Next tactic:
rfl
instance {α} [AddMonoid α] : LawfulApplicative (AddConst α) := by
  refine' { .. } <;> intros <;> simp [add_assoc, (· <$> ·), Seq.seq, pure] <;> 

Proof state:
case refine'_5
α : Type ?u.38625
inst✝ : AddMonoid α
α✝ β✝ : Type ?u.38630
x✝ : AddConst α α✝
y✝ : AddConst α β✝
⊢ (SeqRight.seqRight x✝ fun x => y✝) = Const.map (Function.const α✝ id) x✝ + y✝

Next tactic:
rfl
instance {α} [AddMonoid α] : LawfulApplicative (AddConst α) := by
  refine' { .. } <;> intros <;> simp [add_assoc, (· <$> ·), Seq.seq, pure] <;> 

Proof state:
case refine'_6
α : Type ?u.38625
inst✝ : AddMonoid α
α✝ β✝ : Type ?u.38630
g✝ : α✝ → β✝
x✝ : AddConst α α✝
⊢ x✝ = Const.map g✝ x✝

Next tactic:
rfl
instance {α} [AddMonoid α] : LawfulApplicative (AddConst α) := by
  refine' { .. } <;> intros <;> simp [add_assoc, (· <$> ·), Seq.seq, pure] <;> 

Proof state:
case refine'_7
α : Type ?u.38625
inst✝ : AddMonoid α
α✝ β✝ : Type ?u.38630
g✝ : α✝ → β✝
x✝ : α✝
⊢ Const.map g✝ 0 = 0

Next tactic:
rfl
instance {α} [AddMonoid α] : LawfulApplicative (AddConst α) := by
  refine' { .. } <;> intros <;> simp [add_assoc, (· <$> ·), Seq.seq, pure] <;> 

Proof state:
case refine'_8
α : Type ?u.38625
inst✝ : AddMonoid α
α✝ β✝ : Type ?u.38630
g✝ : AddConst α (α✝ → β✝)
x✝ : α✝
⊢ g✝ = Const.map (fun h => h x✝) g✝

Next tactic:
rfl
instance {α} [AddMonoid α] : LawfulApplicative (AddConst α) := by
  refine' { .. } <;> intros <;> simp [add_assoc, (· <$> ·), Seq.seq, pure] <;> 

Proof state:
case refine'_9
α : Type ?u.38625
inst✝ : AddMonoid α
α✝ β✝ γ✝ : Type ?u.38630
x✝ : AddConst α α✝
g✝ : AddConst α (α✝ → β✝)
h✝ : AddConst α (β✝ → γ✝)
⊢ h✝ + (g✝ + x✝) = Const.map Function.comp h✝ + (g✝ + x✝)

Next tactic:
rfl
lemma Hom.toIsometry_injective (V W : QuadraticModuleCat.{v} R) :
    Function.Injective (Hom.toIsometry : Hom V W → _) :=
  fun ⟨f⟩ ⟨g⟩ _ => by 

Proof state:
R : Type u
inst✝ : CommRing R
V W : QuadraticModuleCat R
x✝² x✝¹ : Hom V W
f g : V.form →qᵢ W.form
x✝ : { toIsometry := f }.toIsometry = { toIsometry := g }.toIsometry
⊢ { toIsometry := f } = { toIsometry := g }

Next tactic:
congr
/-- Build a `QuadraticForm.IsometryEquiv` from an isomorphism in the category
`QuadraticModuleCat R`. -/
@[simps]
def toIsometryEquiv (i : X ≅ Y) : X.form.IsometryEquiv Y.form where
  toFun := i.hom.toIsometry
  invFun := i.inv.toIsometry
  left_inv x := by
    

Proof state:
R : Type u
inst✝ : CommRing R
X Y Z : QuadraticModuleCat R
i : X ≅ Y
x : ↑X.toModuleCat
⊢ i.inv.toIsometry
      (AddHom.toFun
        {
            toAddHom :=
              { toFun := ⇑i.hom.toIsometry,
                map_add' :=
                  (_ : ∀ (x y : ↑X.toModuleCat), i.hom.toIsometry (x + y) = i.hom.toIsometry x + i.hom.toIsometry y) },
            map_smul' :=
              (_ : ∀ (c : R) (x : ↑X.toModuleCat), i.hom.toIsometry (c • x) = c • i.hom.toIsometry x) }.toAddHom
        x) =
    x

Next tactic:
change (i.hom ≫ i.inv).toIsometry x = x
/-- Build a `QuadraticForm.IsometryEquiv` from an isomorphism in the category
`QuadraticModuleCat R`. -/
@[simps]
def toIsometryEquiv (i : X ≅ Y) : X.form.IsometryEquiv Y.form where
  toFun := i.hom.toIsometry
  invFun := i.inv.toIsometry
  left_inv x := by
    change (i.hom ≫ i.inv).toIsometry x = x
    

Proof state:
R : Type u
inst✝ : CommRing R
X Y Z : QuadraticModuleCat R
i : X ≅ Y
x : ↑X.toModuleCat
⊢ (i.hom ≫ i.inv).toIsometry x = x

Next tactic:
simp
/-- Build a `QuadraticForm.IsometryEquiv` from an isomorphism in the category
`QuadraticModuleCat R`. -/
@[simps]
def toIsometryEquiv (i : X ≅ Y) : X.form.IsometryEquiv Y.form where
  toFun := i.hom.toIsometry
  invFun := i.inv.toIsometry
  left_inv x := by
    change (i.hom ≫ i.inv).toIsometry x = x
    simp
  right_inv x := by
    

Proof state:
R : Type u
inst✝ : CommRing R
X Y Z : QuadraticModuleCat R
i : X ≅ Y
x : ↑Y.toModuleCat
⊢ AddHom.toFun
      {
          toAddHom :=
            { toFun := ⇑i.hom.toIsometry,
              map_add' :=
                (_ : ∀ (x y : ↑X.toModuleCat), i.hom.toIsometry (x + y) = i.hom.toIsometry x + i.hom.toIsometry y) },
          map_smul' :=
            (_ : ∀ (c : R) (x : ↑X.toModuleCat), i.hom.toIsometry (c • x) = c • i.hom.toIsometry x) }.toAddHom
      (i.inv.toIsometry x) =
    x

Next tactic:
change (i.inv ≫ i.hom).toIsometry x = x
/-- Build a `QuadraticForm.IsometryEquiv` from an isomorphism in the category
`QuadraticModuleCat R`. -/
@[simps]
def toIsometryEquiv (i : X ≅ Y) : X.form.IsometryEquiv Y.form where
  toFun := i.hom.toIsometry
  invFun := i.inv.toIsometry
  left_inv x := by
    change (i.hom ≫ i.inv).toIsometry x = x
    simp
  right_inv x := by
    change (i.inv ≫ i.hom).toIsometry x = x
    

Proof state:
R : Type u
inst✝ : CommRing R
X Y Z : QuadraticModuleCat R
i : X ≅ Y
x : ↑Y.toModuleCat
⊢ (i.inv ≫ i.hom).toIsometry x = x

Next tactic:
simp
theorem TensorProduct.isTensorProduct : IsTensorProduct (TensorProduct.mk R M N) := by
  

Proof state:
R : Type u_1
inst✝¹⁴ : CommRing R
M₁ : Type u_2
M₂ : Type u_3
M : Type u_4
M' : Type u_5
inst✝¹³ : AddCommMonoid M₁
inst✝¹² : AddCommMonoid M₂
inst✝¹¹ : AddCommMonoid M
inst✝¹⁰ : AddCommMonoid M'
inst✝⁹ : Module R M₁
inst✝⁸ : Module R M₂
inst✝⁷ : Module R M
inst✝⁶ : Module R M'
f : M₁ →ₗ[R] M₂ →ₗ[R] M
N₁ : Type u_6
N₂ : Type u_7
N : Type u_8
inst✝⁵ : AddCommMonoid N₁
inst✝⁴ : AddCommMonoid N₂
inst✝³ : AddCommMonoid N
inst✝² : Module R N₁
inst✝¹ : Module R N₂
inst✝ : Module R N
g : N₁ →ₗ[R] N₂ →ₗ[R] N
⊢ IsTensorProduct (mk R M N)

Next tactic:
delta IsTensorProduct
theorem TensorProduct.isTensorProduct : IsTensorProduct (TensorProduct.mk R M N) := by
  delta IsTensorProduct
  

Proof state:
R : Type u_1
inst✝¹⁴ : CommRing R
M₁ : Type u_2
M₂ : Type u_3
M : Type u_4
M' : Type u_5
inst✝¹³ : AddCommMonoid M₁
inst✝¹² : AddCommMonoid M₂
inst✝¹¹ : AddCommMonoid M
inst✝¹⁰ : AddCommMonoid M'
inst✝⁹ : Module R M₁
inst✝⁸ : Module R M₂
inst✝⁷ : Module R M
inst✝⁶ : Module R M'
f : M₁ →ₗ[R] M₂ →ₗ[R] M
N₁ : Type u_6
N₂ : Type u_7
N : Type u_8
inst✝⁵ : AddCommMonoid N₁
inst✝⁴ : AddCommMonoid N₂
inst✝³ : AddCommMonoid N
inst✝² : Module R N₁
inst✝¹ : Module R N₂
inst✝ : Module R N
g : N₁ →ₗ[R] N₂ →ₗ[R] N
⊢ Function.Bijective ⇑(lift (mk R M N))

Next tactic:
convert_to Function.Bijective (LinearMap.id : M ⊗[R] N →ₗ[R] M ⊗[R] N) using 2
theorem TensorProduct.isTensorProduct : IsTensorProduct (TensorProduct.mk R M N) := by
  delta IsTensorProduct
  convert_to Function.Bijective (LinearMap.id : M ⊗[R] N →ₗ[R] M ⊗[R] N) using 2
  · 

Proof state:
case h.e'_3.h.e'_5
R : Type u_1
inst✝¹⁴ : CommRing R
M₁ : Type u_2
M₂ : Type u_3
M : Type u_4
M' : Type u_5
inst✝¹³ : AddCommMonoid M₁
inst✝¹² : AddCommMonoid M₂
inst✝¹¹ : AddCommMonoid M
inst✝¹⁰ : AddCommMonoid M'
inst✝⁹ : Module R M₁
inst✝⁸ : Module R M₂
inst✝⁷ : Module R M
inst✝⁶ : Module R M'
f : M₁ →ₗ[R] M₂ →ₗ[R] M
N₁ : Type u_6
N₂ : Type u_7
N : Type u_8
inst✝⁵ : AddCommMonoid N₁
inst✝⁴ : AddCommMonoid N₂
inst✝³ : AddCommMonoid N
inst✝² : Module R N₁
inst✝¹ : Module R N₂
inst✝ : Module R N
g : N₁ →ₗ[R] N₂ →ₗ[R] N
⊢ lift (mk R M N) = LinearMap.id

Next tactic:
apply TensorProduct.ext'
theorem TensorProduct.isTensorProduct : IsTensorProduct (TensorProduct.mk R M N) := by
  delta IsTensorProduct
  convert_to Function.Bijective (LinearMap.id : M ⊗[R] N →ₗ[R] M ⊗[R] N) using 2
  · apply TensorProduct.ext'
    

Proof state:
case h.e'_3.h.e'_5.H
R : Type u_1
inst✝¹⁴ : CommRing R
M₁ : Type u_2
M₂ : Type u_3
M : Type u_4
M' : Type u_5
inst✝¹³ : AddCommMonoid M₁
inst✝¹² : AddCommMonoid M₂
inst✝¹¹ : AddCommMonoid M
inst✝¹⁰ : AddCommMonoid M'
inst✝⁹ : Module R M₁
inst✝⁸ : Module R M₂
inst✝⁷ : Module R M
inst✝⁶ : Module R M'
f : M₁ →ₗ[R] M₂ →ₗ[R] M
N₁ : Type u_6
N₂ : Type u_7
N : Type u_8
inst✝⁵ : AddCommMonoid N₁
inst✝⁴ : AddCommMonoid N₂
inst✝³ : AddCommMonoid N
inst✝² : Module R N₁
inst✝¹ : Module R N₂
inst✝ : Module R N
g : N₁ →ₗ[R] N₂ →ₗ[R] N
⊢ ∀ (x : M) (y : N), (lift (mk R M N)) (x ⊗ₜ[R] y) = LinearMap.id (x ⊗ₜ[R] y)

Next tactic:
simp
theorem TensorProduct.isTensorProduct : IsTensorProduct (TensorProduct.mk R M N) := by
  delta IsTensorProduct
  convert_to Function.Bijective (LinearMap.id : M ⊗[R] N →ₗ[R] M ⊗[R] N) using 2
  · apply TensorProduct.ext'
    simp
  · 

Proof state:
R : Type u_1
inst✝¹⁴ : CommRing R
M₁ : Type u_2
M₂ : Type u_3
M : Type u_4
M' : Type u_5
inst✝¹³ : AddCommMonoid M₁
inst✝¹² : AddCommMonoid M₂
inst✝¹¹ : AddCommMonoid M
inst✝¹⁰ : AddCommMonoid M'
inst✝⁹ : Module R M₁
inst✝⁸ : Module R M₂
inst✝⁷ : Module R M
inst✝⁶ : Module R M'
f : M₁ →ₗ[R] M₂ →ₗ[R] M
N₁ : Type u_6
N₂ : Type u_7
N : Type u_8
inst✝⁵ : AddCommMonoid N₁
inst✝⁴ : AddCommMonoid N₂
inst✝³ : AddCommMonoid N
inst✝² : Module R N₁
inst✝¹ : Module R N₂
inst✝ : Module R N
g : N₁ →ₗ[R] N₂ →ₗ[R] N
⊢ Function.Bijective ⇑LinearMap.id

Next tactic:
exact Function.bijective_id
@[simp]
theorem IsTensorProduct.equiv_symm_apply (h : IsTensorProduct f) (x₁ : M₁) (x₂ : M₂) :
    h.equiv.symm (f x₁ x₂) = x₁ ⊗ₜ x₂ := by
  

Proof state:
R : Type u_1
inst✝¹⁴ : CommRing R
M₁ : Type u_2
M₂ : Type u_3
M : Type u_4
M' : Type u_5
inst✝¹³ : AddCommMonoid M₁
inst✝¹² : AddCommMonoid M₂
inst✝¹¹ : AddCommMonoid M
inst✝¹⁰ : AddCommMonoid M'
inst✝⁹ : Module R M₁
inst✝⁸ : Module R M₂
inst✝⁷ : Module R M
inst✝⁶ : Module R M'
f : M₁ →ₗ[R] M₂ →ₗ[R] M
N₁ : Type u_6
N₂ : Type u_7
N : Type u_8
inst✝⁵ : AddCommMonoid N₁
inst✝⁴ : AddCommMonoid N₂
inst✝³ : AddCommMonoid N
inst✝² : Module R N₁
inst✝¹ : Module R N₂
inst✝ : Module R N
g : N₁ →ₗ[R] N₂ →ₗ[R] N
h : IsTensorProduct f
x₁ : M₁
x₂ : M₂
⊢ (LinearEquiv.symm (equiv h)) ((f x₁) x₂) = x₁ ⊗ₜ[R] x₂

Next tactic:
apply h.equiv.injective
@[simp]
theorem IsTensorProduct.equiv_symm_apply (h : IsTensorProduct f) (x₁ : M₁) (x₂ : M₂) :
    h.equiv.symm (f x₁ x₂) = x₁ ⊗ₜ x₂ := by
  apply h.equiv.injective
  

Proof state:
case a
R : Type u_1
inst✝¹⁴ : CommRing R
M₁ : Type u_2
M₂ : Type u_3
M : Type u_4
M' : Type u_5
inst✝¹³ : AddCommMonoid M₁
inst✝¹² : AddCommMonoid M₂
inst✝¹¹ : AddCommMonoid M
inst✝¹⁰ : AddCommMonoid M'
inst✝⁹ : Module R M₁
inst✝⁸ : Module R M₂
inst✝⁷ : Module R M
inst✝⁶ : Module R M'
f : M₁ →ₗ[R] M₂ →ₗ[R] M
N₁ : Type u_6
N₂ : Type u_7
N : Type u_8
inst✝⁵ : AddCommMonoid N₁
inst✝⁴ : AddCommMonoid N₂
inst✝³ : AddCommMonoid N
inst✝² : Module R N₁
inst✝¹ : Module R N₂
inst✝ : Module R N
g : N₁ →ₗ[R] N₂ →ₗ[R] N
h : IsTensorProduct f
x₁ : M₁
x₂ : M₂
⊢ (equiv h) ((LinearEquiv.symm (equiv h)) ((f x₁) x₂)) = (equiv h) (x₁ ⊗ₜ[R] x₂)

Next tactic:
refine' (h.equiv.apply_symm_apply _).trans _
@[simp]
theorem IsTensorProduct.equiv_symm_apply (h : IsTensorProduct f) (x₁ : M₁) (x₂ : M₂) :
    h.equiv.symm (f x₁ x₂) = x₁ ⊗ₜ x₂ := by
  apply h.equiv.injective
  refine' (h.equiv.apply_symm_apply _).trans _
  

Proof state:
case a
R : Type u_1
inst✝¹⁴ : CommRing R
M₁ : Type u_2
M₂ : Type u_3
M : Type u_4
M' : Type u_5
inst✝¹³ : AddCommMonoid M₁
inst✝¹² : AddCommMonoid M₂
inst✝¹¹ : AddCommMonoid M
inst✝¹⁰ : AddCommMonoid M'
inst✝⁹ : Module R M₁
inst✝⁸ : Module R M₂
inst✝⁷ : Module R M
inst✝⁶ : Module R M'
f : M₁ →ₗ[R] M₂ →ₗ[R] M
N₁ : Type u_6
N₂ : Type u_7
N : Type u_8
inst✝⁵ : AddCommMonoid N₁
inst✝⁴ : AddCommMonoid N₂
inst✝³ : AddCommMonoid N
inst✝² : Module R N₁
inst✝¹ : Module R N₂
inst✝ : Module R N
g : N₁ →ₗ[R] N₂ →ₗ[R] N
h : IsTensorProduct f
x₁ : M₁
x₂ : M₂
⊢ (f x₁) x₂ = (equiv h) (x₁ ⊗ₜ[R] x₂)

Next tactic:
simp
theorem IsTensorProduct.lift_eq (h : IsTensorProduct f) (f' : M₁ →ₗ[R] M₂ →ₗ[R] M') (x₁ : M₁)
    (x₂ : M₂) : h.lift f' (f x₁ x₂) = f' x₁ x₂ := by
  

Proof state:
R : Type u_1
inst✝¹⁴ : CommRing R
M₁ : Type u_2
M₂ : Type u_3
M : Type u_4
M' : Type u_5
inst✝¹³ : AddCommMonoid M₁
inst✝¹² : AddCommMonoid M₂
inst✝¹¹ : AddCommMonoid M
inst✝¹⁰ : AddCommMonoid M'
inst✝⁹ : Module R M₁
inst✝⁸ : Module R M₂
inst✝⁷ : Module R M
inst✝⁶ : Module R M'
f : M₁ →ₗ[R] M₂ →ₗ[R] M
N₁ : Type u_6
N₂ : Type u_7
N : Type u_8
inst✝⁵ : AddCommMonoid N₁
inst✝⁴ : AddCommMonoid N₂
inst✝³ : AddCommMonoid N
inst✝² : Module R N₁
inst✝¹ : Module R N₂
inst✝ : Module R N
g : N₁ →ₗ[R] N₂ →ₗ[R] N
h : IsTensorProduct f
f' : M₁ →ₗ[R] M₂ →ₗ[R] M'
x₁ : M₁
x₂ : M₂
⊢ (lift h f') ((f x₁) x₂) = (f' x₁) x₂

Next tactic:
delta IsTensorProduct.lift
theorem IsTensorProduct.lift_eq (h : IsTensorProduct f) (f' : M₁ →ₗ[R] M₂ →ₗ[R] M') (x₁ : M₁)
    (x₂ : M₂) : h.lift f' (f x₁ x₂) = f' x₁ x₂ := by
  delta IsTensorProduct.lift
  

Proof state:
R : Type u_1
inst✝¹⁴ : CommRing R
M₁ : Type u_2
M₂ : Type u_3
M : Type u_4
M' : Type u_5
inst✝¹³ : AddCommMonoid M₁
inst✝¹² : AddCommMonoid M₂
inst✝¹¹ : AddCommMonoid M
inst✝¹⁰ : AddCommMonoid M'
inst✝⁹ : Module R M₁
inst✝⁸ : Module R M₂
inst✝⁷ : Module R M
inst✝⁶ : Module R M'
f : M₁ →ₗ[R] M₂ →ₗ[R] M
N₁ : Type u_6
N₂ : Type u_7
N : Type u_8
inst✝⁵ : AddCommMonoid N₁
inst✝⁴ : AddCommMonoid N₂
inst✝³ : AddCommMonoid N
inst✝² : Module R N₁
inst✝¹ : Module R N₂
inst✝ : Module R N
g : N₁ →ₗ[R] N₂ →ₗ[R] N
h : IsTensorProduct f
f' : M₁ →ₗ[R] M₂ →ₗ[R] M'
x₁ : M₁
x₂ : M₂
⊢ (LinearMap.comp (TensorProduct.lift f') ↑(LinearEquiv.symm (equiv h))) ((f x₁) x₂) = (f' x₁) x₂

Next tactic:
simp
theorem IsTensorProduct.map_eq (hf : IsTensorProduct f) (hg : IsTensorProduct g) (i₁ : M₁ →ₗ[R] N₁)
    (i₂ : M₂ →ₗ[R] N₂) (x₁ : M₁) (x₂ : M₂) : hf.map hg i₁ i₂ (f x₁ x₂) = g (i₁ x₁) (i₂ x₂) := by
  

Proof state:
R : Type u_1
inst✝¹⁴ : CommRing R
M₁ : Type u_2
M₂ : Type u_3
M : Type u_4
M' : Type u_5
inst✝¹³ : AddCommMonoid M₁
inst✝¹² : AddCommMonoid M₂
inst✝¹¹ : AddCommMonoid M
inst✝¹⁰ : AddCommMonoid M'
inst✝⁹ : Module R M₁
inst✝⁸ : Module R M₂
inst✝⁷ : Module R M
inst✝⁶ : Module R M'
f : M₁ →ₗ[R] M₂ →ₗ[R] M
N₁ : Type u_6
N₂ : Type u_7
N : Type u_8
inst✝⁵ : AddCommMonoid N₁
inst✝⁴ : AddCommMonoid N₂
inst✝³ : AddCommMonoid N
inst✝² : Module R N₁
inst✝¹ : Module R N₂
inst✝ : Module R N
g : N₁ →ₗ[R] N₂ →ₗ[R] N
hf : IsTensorProduct f
hg : IsTensorProduct g
i₁ : M₁ →ₗ[R] N₁
i₂ : M₂ →ₗ[R] N₂
x₁ : M₁
x₂ : M₂
⊢ (map hf hg i₁ i₂) ((f x₁) x₂) = (g (i₁ x₁)) (i₂ x₂)

Next tactic:
delta IsTensorProduct.map
theorem IsTensorProduct.map_eq (hf : IsTensorProduct f) (hg : IsTensorProduct g) (i₁ : M₁ →ₗ[R] N₁)
    (i₂ : M₂ →ₗ[R] N₂) (x₁ : M₁) (x₂ : M₂) : hf.map hg i₁ i₂ (f x₁ x₂) = g (i₁ x₁) (i₂ x₂) := by
  delta IsTensorProduct.map
  

Proof state:
R : Type u_1
inst✝¹⁴ : CommRing R
M₁ : Type u_2
M₂ : Type u_3
M : Type u_4
M' : Type u_5
inst✝¹³ : AddCommMonoid M₁
inst✝¹² : AddCommMonoid M₂
inst✝¹¹ : AddCommMonoid M
inst✝¹⁰ : AddCommMonoid M'
inst✝⁹ : Module R M₁
inst✝⁸ : Module R M₂
inst✝⁷ : Module R M
inst✝⁶ : Module R M'
f : M₁ →ₗ[R] M₂ →ₗ[R] M
N₁ : Type u_6
N₂ : Type u_7
N : Type u_8
inst✝⁵ : AddCommMonoid N₁
inst✝⁴ : AddCommMonoid N₂
inst✝³ : AddCommMonoid N
inst✝² : Module R N₁
inst✝¹ : Module R N₂
inst✝ : Module R N
g : N₁ →ₗ[R] N₂ →ₗ[R] N
hf : IsTensorProduct f
hg : IsTensorProduct g
i₁ : M₁ →ₗ[R] N₁
i₂ : M₂ →ₗ[R] N₂
x₁ : M₁
x₂ : M₂
⊢ (LinearMap.comp (↑(equiv hg)) (LinearMap.comp (TensorProduct.map i₁ i₂) ↑(LinearEquiv.symm (equiv hf)))) ((f x₁) x₂) =
    (g (i₁ x₁)) (i₂ x₂)

Next tactic:
simp
theorem IsTensorProduct.inductionOn (h : IsTensorProduct f) {C : M → Prop} (m : M) (h0 : C 0)
    (htmul : ∀ x y, C (f x y)) (hadd : ∀ x y, C x → C y → C (x + y)) : C m := by
  

Proof state:
R : Type u_1
inst✝¹⁴ : CommRing R
M₁ : Type u_2
M₂ : Type u_3
M : Type u_4
M' : Type u_5
inst✝¹³ : AddCommMonoid M₁
inst✝¹² : AddCommMonoid M₂
inst✝¹¹ : AddCommMonoid M
inst✝¹⁰ : AddCommMonoid M'
inst✝⁹ : Module R M₁
inst✝⁸ : Module R M₂
inst✝⁷ : Module R M
inst✝⁶ : Module R M'
f : M₁ →ₗ[R] M₂ →ₗ[R] M
N₁ : Type u_6
N₂ : Type u_7
N : Type u_8
inst✝⁵ : AddCommMonoid N₁
inst✝⁴ : AddCommMonoid N₂
inst✝³ : AddCommMonoid N
inst✝² : Module R N₁
inst✝¹ : Module R N₂
inst✝ : Module R N
g : N₁ →ₗ[R] N₂ →ₗ[R] N
h : IsTensorProduct f
C : M → Prop
m : M
h0 : C 0
htmul : ∀ (x : M₁) (y : M₂), C ((f x) y)
hadd : ∀ (x y : M), C x → C y → C (x + y)
⊢ C m

Next tactic:
rw [← h.equiv.right_inv m]
theorem IsTensorProduct.inductionOn (h : IsTensorProduct f) {C : M → Prop} (m : M) (h0 : C 0)
    (htmul : ∀ x y, C (f x y)) (hadd : ∀ x y, C x → C y → C (x + y)) : C m := by
  rw [← h.equiv.right_inv m]
  

Proof state:
R : Type u_1
inst✝¹⁴ : CommRing R
M₁ : Type u_2
M₂ : Type u_3
M : Type u_4
M' : Type u_5
inst✝¹³ : AddCommMonoid M₁
inst✝¹² : AddCommMonoid M₂
inst✝¹¹ : AddCommMonoid M
inst✝¹⁰ : AddCommMonoid M'
inst✝⁹ : Module R M₁
inst✝⁸ : Module R M₂
inst✝⁷ : Module R M
inst✝⁶ : Module R M'
f : M₁ →ₗ[R] M₂ →ₗ[R] M
N₁ : Type u_6
N₂ : Type u_7
N : Type u_8
inst✝⁵ : AddCommMonoid N₁
inst✝⁴ : AddCommMonoid N₂
inst✝³ : AddCommMonoid N
inst✝² : Module R N₁
inst✝¹ : Module R N₂
inst✝ : Module R N
g : N₁ →ₗ[R] N₂ →ₗ[R] N
h : IsTensorProduct f
C : M → Prop
m : M
h0 : C 0
htmul : ∀ (x : M₁) (y : M₂), C ((f x) y)
hadd : ∀ (x y : M), C x → C y → C (x + y)
⊢ C (AddHom.toFun (↑(equiv h)).toAddHom (LinearEquiv.invFun (equiv h) m))

Next tactic:
generalize h.equiv.invFun m = y
theorem IsTensorProduct.inductionOn (h : IsTensorProduct f) {C : M → Prop} (m : M) (h0 : C 0)
    (htmul : ∀ x y, C (f x y)) (hadd : ∀ x y, C x → C y → C (x + y)) : C m := by
  rw [← h.equiv.right_inv m]
  generalize h.equiv.invFun m = y
  

Proof state:
R : Type u_1
inst✝¹⁴ : CommRing R
M₁ : Type u_2
M₂ : Type u_3
M : Type u_4
M' : Type u_5
inst✝¹³ : AddCommMonoid M₁
inst✝¹² : AddCommMonoid M₂
inst✝¹¹ : AddCommMonoid M
inst✝¹⁰ : AddCommMonoid M'
inst✝⁹ : Module R M₁
inst✝⁸ : Module R M₂
inst✝⁷ : Module R M
inst✝⁶ : Module R M'
f : M₁ →ₗ[R] M₂ →ₗ[R] M
N₁ : Type u_6
N₂ : Type u_7
N : Type u_8
inst✝⁵ : AddCommMonoid N₁
inst✝⁴ : AddCommMonoid N₂
inst✝³ : AddCommMonoid N
inst✝² : Module R N₁
inst✝¹ : Module R N₂
inst✝ : Module R N
g : N₁ →ₗ[R] N₂ →ₗ[R] N
h : IsTensorProduct f
C : M → Prop
m : M
h0 : C 0
htmul : ∀ (x : M₁) (y : M₂), C ((f x) y)
hadd : ∀ (x y : M), C x → C y → C (x + y)
y : M₁ ⊗[R] M₂
⊢ C (AddHom.toFun (↑(equiv h)).toAddHom y)

Next tactic:
change C (TensorProduct.lift f y)
theorem IsTensorProduct.inductionOn (h : IsTensorProduct f) {C : M → Prop} (m : M) (h0 : C 0)
    (htmul : ∀ x y, C (f x y)) (hadd : ∀ x y, C x → C y → C (x + y)) : C m := by
  rw [← h.equiv.right_inv m]
  generalize h.equiv.invFun m = y
  change C (TensorProduct.lift f y)
  

Proof state:
R : Type u_1
inst✝¹⁴ : CommRing R
M₁ : Type u_2
M₂ : Type u_3
M : Type u_4
M' : Type u_5
inst✝¹³ : AddCommMonoid M₁
inst✝¹² : AddCommMonoid M₂
inst✝¹¹ : AddCommMonoid M
inst✝¹⁰ : AddCommMonoid M'
inst✝⁹ : Module R M₁
inst✝⁸ : Module R M₂
inst✝⁷ : Module R M
inst✝⁶ : Module R M'
f : M₁ →ₗ[R] M₂ →ₗ[R] M
N₁ : Type u_6
N₂ : Type u_7
N : Type u_8
inst✝⁵ : AddCommMonoid N₁
inst✝⁴ : AddCommMonoid N₂
inst✝³ : AddCommMonoid N
inst✝² : Module R N₁
inst✝¹ : Module R N₂
inst✝ : Module R N
g : N₁ →ₗ[R] N₂ →ₗ[R] N
h : IsTensorProduct f
C : M → Prop
m : M
h0 : C 0
htmul : ∀ (x : M₁) (y : M₂), C ((f x) y)
hadd : ∀ (x y : M), C x → C y → C (x + y)
y : M₁ ⊗[R] M₂
⊢ C ((TensorProduct.lift f) y)

Next tactic:
induction y using TensorProduct.induction_on with
  | zero => rwa [map_zero]
  | tmul _ _ =>
    rw [TensorProduct.lift.tmul]
    apply htmul
  | add _ _ _ _ =>
    rw [map_add]
    apply hadd <;> assumption
theorem IsTensorProduct.inductionOn (h : IsTensorProduct f) {C : M → Prop} (m : M) (h0 : C 0)
    (htmul : ∀ x y, C (f x y)) (hadd : ∀ x y, C x → C y → C (x + y)) : C m := by
  rw [← h.equiv.right_inv m]
  generalize h.equiv.invFun m = y
  change C (TensorProduct.lift f y)
  induction y using TensorProduct.induction_on with
  

Proof state:
case zero
R : Type u_1
inst✝¹⁴ : CommRing R
M₁ : Type u_2
M₂ : Type u_3
M : Type u_4
M' : Type u_5
inst✝¹³ : AddCommMonoid M₁
inst✝¹² : AddCommMonoid M₂
inst✝¹¹ : AddCommMonoid M
inst✝¹⁰ : AddCommMonoid M'
inst✝⁹ : Module R M₁
inst✝⁸ : Module R M₂
inst✝⁷ : Module R M
inst✝⁶ : Module R M'
f : M₁ →ₗ[R] M₂ →ₗ[R] M
N₁ : Type u_6
N₂ : Type u_7
N : Type u_8
inst✝⁵ : AddCommMonoid N₁
inst✝⁴ : AddCommMonoid N₂
inst✝³ : AddCommMonoid N
inst✝² : Module R N₁
inst✝¹ : Module R N₂
inst✝ : Module R N
g : N₁ →ₗ[R] N₂ →ₗ[R] N
h : IsTensorProduct f
C : M → Prop
m : M
h0 : C 0
htmul : ∀ (x : M₁) (y : M₂), C ((f x) y)
hadd : ∀ (x y : M), C x → C y → C (x + y)
⊢ C ((TensorProduct.lift f) 0)

Next tactic:
| zero => rwa [map_zero]