l3lab/ntp-mathlib huggingface dataset:
theorem cast_eq_cast {i j} (h : i = j) :
    ⇑(cast R M h) = _root_.cast (congrArg (fun i => (⨂[R]^i) M) h) := by
  

Proof state:
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
i j : ℕ
h : i = j
⊢ ⇑(cast R M h) = _root_.cast (_ : (⨂[R]^i) M = (⨂[R]^j) M)

Next tactic:
subst h
theorem cast_eq_cast {i j} (h : i = j) :
    ⇑(cast R M h) = _root_.cast (congrArg (fun i => (⨂[R]^i) M) h) := by
  subst h
  

Proof state:
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
i : ℕ
⊢ ⇑(cast R M (_ : i = i)) = _root_.cast (_ : (⨂[R]^i) M = (⨂[R]^i) M)

Next tactic:
rw [cast_refl]
theorem cast_eq_cast {i j} (h : i = j) :
    ⇑(cast R M h) = _root_.cast (congrArg (fun i => (⨂[R]^i) M) h) := by
  subst h
  rw [cast_refl]
  

Proof state:
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
i : ℕ
⊢ ⇑(LinearEquiv.refl R ((⨂[R]^i) M)) = _root_.cast (_ : (⨂[R]^i) M = (⨂[R]^i) M)

Next tactic:
rfl
theorem tprod_mul_tprod {na nb} (a : Fin na → M) (b : Fin nb → M) :
    tprod R a ₜ* tprod R b = tprod R (Fin.append a b) := by
  

Proof state:
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
na nb : ℕ
a : Fin na → M
b : Fin nb → M
⊢ GradedMonoid.GMul.mul ((tprod R) a) ((tprod R) b) = (tprod R) (Fin.append a b)

Next tactic:
dsimp [gMul_def, mulEquiv]
theorem tprod_mul_tprod {na nb} (a : Fin na → M) (b : Fin nb → M) :
    tprod R a ₜ* tprod R b = tprod R (Fin.append a b) := by
  dsimp [gMul_def, mulEquiv]
  

Proof state:
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
na nb : ℕ
a : Fin na → M
b : Fin nb → M
⊢ (reindex R M finSumFinEquiv) ((tmulEquiv R M) ((tprod R) a ⊗ₜ[R] (tprod R) b)) = (tprod R) (Fin.append a b)

Next tactic:
rw [tmulEquiv_apply R M a b]
theorem tprod_mul_tprod {na nb} (a : Fin na → M) (b : Fin nb → M) :
    tprod R a ₜ* tprod R b = tprod R (Fin.append a b) := by
  dsimp [gMul_def, mulEquiv]
  rw [tmulEquiv_apply R M a b]
  

Proof state:
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
na nb : ℕ
a : Fin na → M
b : Fin nb → M
⊢ (reindex R M finSumFinEquiv) ((tprod R) fun i => Sum.elim a b i) = (tprod R) (Fin.append a b)

Next tactic:
refine' (reindex_tprod _ _).trans _
theorem tprod_mul_tprod {na nb} (a : Fin na → M) (b : Fin nb → M) :
    tprod R a ₜ* tprod R b = tprod R (Fin.append a b) := by
  dsimp [gMul_def, mulEquiv]
  rw [tmulEquiv_apply R M a b]
  refine' (reindex_tprod _ _).trans _
  

Proof state:
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
na nb : ℕ
a : Fin na → M
b : Fin nb → M
⊢ ((tprod R) fun i => Sum.elim a b (finSumFinEquiv.symm i)) = (tprod R) (Fin.append a b)

Next tactic:
congr 1
theorem tprod_mul_tprod {na nb} (a : Fin na → M) (b : Fin nb → M) :
    tprod R a ₜ* tprod R b = tprod R (Fin.append a b) := by
  dsimp [gMul_def, mulEquiv]
  rw [tmulEquiv_apply R M a b]
  refine' (reindex_tprod _ _).trans _
  congr 1
  

Proof state:
case h.e_6.h
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
na nb : ℕ
a : Fin na → M
b : Fin nb → M
⊢ (fun i => Sum.elim a b (finSumFinEquiv.symm i)) = Fin.append a b

Next tactic:
dsimp only [Fin.append, finSumFinEquiv, Equiv.coe_fn_symm_mk]
theorem tprod_mul_tprod {na nb} (a : Fin na → M) (b : Fin nb → M) :
    tprod R a ₜ* tprod R b = tprod R (Fin.append a b) := by
  dsimp [gMul_def, mulEquiv]
  rw [tmulEquiv_apply R M a b]
  refine' (reindex_tprod _ _).trans _
  congr 1
  dsimp only [Fin.append, finSumFinEquiv, Equiv.coe_fn_symm_mk]
  

Proof state:
case h.e_6.h
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
na nb : ℕ
a : Fin na → M
b : Fin nb → M
⊢ (fun i => Sum.elim a b (Fin.addCases Sum.inl Sum.inr i)) = Fin.addCases a b

Next tactic:
apply funext
theorem tprod_mul_tprod {na nb} (a : Fin na → M) (b : Fin nb → M) :
    tprod R a ₜ* tprod R b = tprod R (Fin.append a b) := by
  dsimp [gMul_def, mulEquiv]
  rw [tmulEquiv_apply R M a b]
  refine' (reindex_tprod _ _).trans _
  congr 1
  dsimp only [Fin.append, finSumFinEquiv, Equiv.coe_fn_symm_mk]
  apply funext
  

Proof state:
case h.e_6.h.h
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
na nb : ℕ
a : Fin na → M
b : Fin nb → M
⊢ ∀ (x : Fin (na + nb)), Sum.elim a b (Fin.addCases Sum.inl Sum.inr x) = Fin.addCases a b x

Next tactic:
apply Fin.addCases
theorem tprod_mul_tprod {na nb} (a : Fin na → M) (b : Fin nb → M) :
    tprod R a ₜ* tprod R b = tprod R (Fin.append a b) := by
  dsimp [gMul_def, mulEquiv]
  rw [tmulEquiv_apply R M a b]
  refine' (reindex_tprod _ _).trans _
  congr 1
  dsimp only [Fin.append, finSumFinEquiv, Equiv.coe_fn_symm_mk]
  apply funext
  apply Fin.addCases <;> 

Proof state:
case h.e_6.h.h.left
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
na nb : ℕ
a : Fin na → M
b : Fin nb → M
⊢ ∀ (i : Fin na), Sum.elim a b (Fin.addCases Sum.inl Sum.inr (Fin.castAdd nb i)) = Fin.addCases a b (Fin.castAdd nb i)

Next tactic:
simp
theorem tprod_mul_tprod {na nb} (a : Fin na → M) (b : Fin nb → M) :
    tprod R a ₜ* tprod R b = tprod R (Fin.append a b) := by
  dsimp [gMul_def, mulEquiv]
  rw [tmulEquiv_apply R M a b]
  refine' (reindex_tprod _ _).trans _
  congr 1
  dsimp only [Fin.append, finSumFinEquiv, Equiv.coe_fn_symm_mk]
  apply funext
  apply Fin.addCases <;> 

Proof state:
case h.e_6.h.h.right
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
na nb : ℕ
a : Fin na → M
b : Fin nb → M
⊢ ∀ (i : Fin nb), Sum.elim a b (Fin.addCases Sum.inl Sum.inr (Fin.natAdd na i)) = Fin.addCases a b (Fin.natAdd na i)

Next tactic:
simp
theorem one_mul {n} (a : (⨂[R]^n) M) : cast R M (zero_add n) (ₜ1 ₜ* a) = a := by
  

Proof state:
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
n : ℕ
a : (⨂[R]^n) M
⊢ (cast R M (_ : 0 + n = n)) (GradedMonoid.GMul.mul GradedMonoid.GOne.one a) = a

Next tactic:
rw [gMul_def, gOne_def]
theorem one_mul {n} (a : (⨂[R]^n) M) : cast R M (zero_add n) (ₜ1 ₜ* a) = a := by
  rw [gMul_def, gOne_def]
  

Proof state:
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
n : ℕ
a : (⨂[R]^n) M
⊢ (cast R M (_ : 0 + n = n)) (mulEquiv ((tprod R) Fin.elim0' ⊗ₜ[R] a)) = a

Next tactic:
induction' a using PiTensorProduct.induction_on with r a x y hx hy
theorem one_mul {n} (a : (⨂[R]^n) M) : cast R M (zero_add n) (ₜ1 ₜ* a) = a := by
  rw [gMul_def, gOne_def]
  induction' a using PiTensorProduct.induction_on with r a x y hx hy
  · 

Proof state:
case C1
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
n : ℕ
r : R
a : Fin n → M
⊢ (cast R M (_ : 0 + n = n)) (mulEquiv ((tprod R) Fin.elim0' ⊗ₜ[R] (r • (tprod R) a))) = r • (tprod R) a

Next tactic:
rw [TensorProduct.tmul_smul, LinearEquiv.map_smul, LinearEquiv.map_smul, ← gMul_def,
      tprod_mul_tprod, cast_tprod]
theorem one_mul {n} (a : (⨂[R]^n) M) : cast R M (zero_add n) (ₜ1 ₜ* a) = a := by
  rw [gMul_def, gOne_def]
  induction' a using PiTensorProduct.induction_on with r a x y hx hy
  · rw [TensorProduct.tmul_smul, LinearEquiv.map_smul, LinearEquiv.map_smul, ← gMul_def,
      tprod_mul_tprod, cast_tprod]
    

Proof state:
case C1
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
n : ℕ
r : R
a : Fin n → M
⊢ r • (tprod R) (Fin.append Fin.elim0' a ∘ Fin.cast (_ : n = 0 + n)) = r • (tprod R) a

Next tactic:
congr 2 with i
theorem one_mul {n} (a : (⨂[R]^n) M) : cast R M (zero_add n) (ₜ1 ₜ* a) = a := by
  rw [gMul_def, gOne_def]
  induction' a using PiTensorProduct.induction_on with r a x y hx hy
  · rw [TensorProduct.tmul_smul, LinearEquiv.map_smul, LinearEquiv.map_smul, ← gMul_def,
      tprod_mul_tprod, cast_tprod]
    congr 2 with i
    

Proof state:
case C1.e_a.h.e_6.h.h
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
n : ℕ
r : R
a : Fin n → M
i : Fin n
⊢ (Fin.append Fin.elim0' a ∘ Fin.cast (_ : n = 0 + n)) i = a i

Next tactic:
rw [Fin.elim0'_append]
theorem one_mul {n} (a : (⨂[R]^n) M) : cast R M (zero_add n) (ₜ1 ₜ* a) = a := by
  rw [gMul_def, gOne_def]
  induction' a using PiTensorProduct.induction_on with r a x y hx hy
  · rw [TensorProduct.tmul_smul, LinearEquiv.map_smul, LinearEquiv.map_smul, ← gMul_def,
      tprod_mul_tprod, cast_tprod]
    congr 2 with i
    rw [Fin.elim0'_append]
    

Proof state:
case C1.e_a.h.e_6.h.h
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
n : ℕ
r : R
a : Fin n → M
i : Fin n
⊢ ((a ∘ Fin.cast (_ : 0 + n = n)) ∘ Fin.cast (_ : n = 0 + n)) i = a i

Next tactic:
refine' congr_arg a (Fin.ext _)
theorem one_mul {n} (a : (⨂[R]^n) M) : cast R M (zero_add n) (ₜ1 ₜ* a) = a := by
  rw [gMul_def, gOne_def]
  induction' a using PiTensorProduct.induction_on with r a x y hx hy
  · rw [TensorProduct.tmul_smul, LinearEquiv.map_smul, LinearEquiv.map_smul, ← gMul_def,
      tprod_mul_tprod, cast_tprod]
    congr 2 with i
    rw [Fin.elim0'_append]
    refine' congr_arg a (Fin.ext _)
    

Proof state:
case C1.e_a.h.e_6.h.h
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
n : ℕ
r : R
a : Fin n → M
i : Fin n
⊢ ↑(Fin.cast (_ : 0 + n = n) (Fin.cast (_ : n = 0 + n) i)) = ↑i

Next tactic:
simp
theorem one_mul {n} (a : (⨂[R]^n) M) : cast R M (zero_add n) (ₜ1 ₜ* a) = a := by
  rw [gMul_def, gOne_def]
  induction' a using PiTensorProduct.induction_on with r a x y hx hy
  · rw [TensorProduct.tmul_smul, LinearEquiv.map_smul, LinearEquiv.map_smul, ← gMul_def,
      tprod_mul_tprod, cast_tprod]
    congr 2 with i
    rw [Fin.elim0'_append]
    refine' congr_arg a (Fin.ext _)
    simp
  · 

Proof state:
case Cp
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
n : ℕ
x y : ⨂[R] (i : Fin n), M
hx : (cast R M (_ : 0 + n = n)) (mulEquiv ((tprod R) Fin.elim0' ⊗ₜ[R] x)) = x
hy : (cast R M (_ : 0 + n = n)) (mulEquiv ((tprod R) Fin.elim0' ⊗ₜ[R] y)) = y
⊢ (cast R M (_ : 0 + n = n)) (mulEquiv ((tprod R) Fin.elim0' ⊗ₜ[R] (x + y))) = x + y

Next tactic:
rw [TensorProduct.tmul_add, map_add, map_add, hx, hy]
theorem mul_one {n} (a : (⨂[R]^n) M) : cast R M (add_zero _) (a ₜ* ₜ1) = a := by
  

Proof state:
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
n : ℕ
a : (⨂[R]^n) M
⊢ (cast R M (_ : n + 0 = n)) (GradedMonoid.GMul.mul a GradedMonoid.GOne.one) = a

Next tactic:
rw [gMul_def, gOne_def]
theorem mul_one {n} (a : (⨂[R]^n) M) : cast R M (add_zero _) (a ₜ* ₜ1) = a := by
  rw [gMul_def, gOne_def]
  

Proof state:
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
n : ℕ
a : (⨂[R]^n) M
⊢ (cast R M (_ : n + 0 = n)) (mulEquiv (a ⊗ₜ[R] (tprod R) Fin.elim0')) = a

Next tactic:
induction' a using PiTensorProduct.induction_on with r a x y hx hy
theorem mul_one {n} (a : (⨂[R]^n) M) : cast R M (add_zero _) (a ₜ* ₜ1) = a := by
  rw [gMul_def, gOne_def]
  induction' a using PiTensorProduct.induction_on with r a x y hx hy
  · 

Proof state:
case C1
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
n : ℕ
r : R
a : Fin n → M
⊢ (cast R M (_ : n + 0 = n)) (mulEquiv ((r • (tprod R) a) ⊗ₜ[R] (tprod R) Fin.elim0')) = r • (tprod R) a

Next tactic:
rw [← TensorProduct.smul_tmul', LinearEquiv.map_smul, LinearEquiv.map_smul, ← gMul_def,
      tprod_mul_tprod R a _, cast_tprod]
theorem mul_one {n} (a : (⨂[R]^n) M) : cast R M (add_zero _) (a ₜ* ₜ1) = a := by
  rw [gMul_def, gOne_def]
  induction' a using PiTensorProduct.induction_on with r a x y hx hy
  · rw [← TensorProduct.smul_tmul', LinearEquiv.map_smul, LinearEquiv.map_smul, ← gMul_def,
      tprod_mul_tprod R a _, cast_tprod]
    

Proof state:
case C1
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
n : ℕ
r : R
a : Fin n → M
⊢ r • (tprod R) (Fin.append a Fin.elim0' ∘ Fin.cast (_ : n = n + 0)) = r • (tprod R) a

Next tactic:
congr 2 with i
theorem mul_one {n} (a : (⨂[R]^n) M) : cast R M (add_zero _) (a ₜ* ₜ1) = a := by
  rw [gMul_def, gOne_def]
  induction' a using PiTensorProduct.induction_on with r a x y hx hy
  · rw [← TensorProduct.smul_tmul', LinearEquiv.map_smul, LinearEquiv.map_smul, ← gMul_def,
      tprod_mul_tprod R a _, cast_tprod]
    congr 2 with i
    

Proof state:
case C1.e_a.h.e_6.h.h
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
n : ℕ
r : R
a : Fin n → M
i : Fin n
⊢ (Fin.append a Fin.elim0' ∘ Fin.cast (_ : n = n + 0)) i = a i

Next tactic:
rw [Fin.append_elim0']
theorem mul_one {n} (a : (⨂[R]^n) M) : cast R M (add_zero _) (a ₜ* ₜ1) = a := by
  rw [gMul_def, gOne_def]
  induction' a using PiTensorProduct.induction_on with r a x y hx hy
  · rw [← TensorProduct.smul_tmul', LinearEquiv.map_smul, LinearEquiv.map_smul, ← gMul_def,
      tprod_mul_tprod R a _, cast_tprod]
    congr 2 with i
    rw [Fin.append_elim0']
    

Proof state:
case C1.e_a.h.e_6.h.h
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
n : ℕ
r : R
a : Fin n → M
i : Fin n
⊢ ((a ∘ Fin.cast (_ : n + 0 = n)) ∘ Fin.cast (_ : n = n + 0)) i = a i

Next tactic:
refine' congr_arg a (Fin.ext _)
theorem mul_one {n} (a : (⨂[R]^n) M) : cast R M (add_zero _) (a ₜ* ₜ1) = a := by
  rw [gMul_def, gOne_def]
  induction' a using PiTensorProduct.induction_on with r a x y hx hy
  · rw [← TensorProduct.smul_tmul', LinearEquiv.map_smul, LinearEquiv.map_smul, ← gMul_def,
      tprod_mul_tprod R a _, cast_tprod]
    congr 2 with i
    rw [Fin.append_elim0']
    refine' congr_arg a (Fin.ext _)
    

Proof state:
case C1.e_a.h.e_6.h.h
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
n : ℕ
r : R
a : Fin n → M
i : Fin n
⊢ ↑(Fin.cast (_ : n + 0 = n) (Fin.cast (_ : n = n + 0) i)) = ↑i

Next tactic:
simp
theorem mul_one {n} (a : (⨂[R]^n) M) : cast R M (add_zero _) (a ₜ* ₜ1) = a := by
  rw [gMul_def, gOne_def]
  induction' a using PiTensorProduct.induction_on with r a x y hx hy
  · rw [← TensorProduct.smul_tmul', LinearEquiv.map_smul, LinearEquiv.map_smul, ← gMul_def,
      tprod_mul_tprod R a _, cast_tprod]
    congr 2 with i
    rw [Fin.append_elim0']
    refine' congr_arg a (Fin.ext _)
    simp
  · 

Proof state:
case Cp
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
n : ℕ
x y : ⨂[R] (i : Fin n), M
hx : (cast R M (_ : n + 0 = n)) (mulEquiv (x ⊗ₜ[R] (tprod R) Fin.elim0')) = x
hy : (cast R M (_ : n + 0 = n)) (mulEquiv (y ⊗ₜ[R] (tprod R) Fin.elim0')) = y
⊢ (cast R M (_ : n + 0 = n)) (mulEquiv ((x + y) ⊗ₜ[R] (tprod R) Fin.elim0')) = x + y

Next tactic:
rw [TensorProduct.add_tmul, map_add, map_add, hx, hy]
theorem mul_assoc {na nb nc} (a : (⨂[R]^na) M) (b : (⨂[R]^nb) M) (c : (⨂[R]^nc) M) :
    cast R M (add_assoc _ _ _) (a ₜ* b ₜ* c) = a ₜ* (b ₜ* c) := by
  

Proof state:
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
na nb nc : ℕ
a : (⨂[R]^na) M
b : (⨂[R]^nb) M
c : (⨂[R]^nc) M
⊢ (cast R M (_ : na + nb + nc = na + (nb + nc))) (GradedMonoid.GMul.mul (GradedMonoid.GMul.mul a b) c) =
    GradedMonoid.GMul.mul a (GradedMonoid.GMul.mul b c)

Next tactic:
let mul : ∀ n m : ℕ, (⨂[R]^n) M →ₗ[R] (⨂[R]^m) M →ₗ[R] (⨂[R]^(n + m)) M := fun n m =>
    (TensorProduct.mk R _ _).compr₂ ↑(mulEquiv : _ ≃ₗ[R] (⨂[R]^(n + m)) M)
theorem mul_assoc {na nb nc} (a : (⨂[R]^na) M) (b : (⨂[R]^nb) M) (c : (⨂[R]^nc) M) :
    cast R M (add_assoc _ _ _) (a ₜ* b ₜ* c) = a ₜ* (b ₜ* c) := by
  let mul : ∀ n m : ℕ, (⨂[R]^n) M →ₗ[R] (⨂[R]^m) M →ₗ[R] (⨂[R]^(n + m)) M := fun n m =>
    (TensorProduct.mk R _ _).compr₂ ↑(mulEquiv : _ ≃ₗ[R] (⨂[R]^(n + m)) M)
  -- replace `a`, `b`, `c` with `tprod R a`, `tprod R b`, `tprod R c`
  

Proof state:
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
na nb nc : ℕ
a : (⨂[R]^na) M
b : (⨂[R]^nb) M
c : (⨂[R]^nc) M
mul : (n m : ℕ) → (⨂[R]^n) M →ₗ[R] (⨂[R]^m) M →ₗ[R] (⨂[R]^(n + m)) M :=
  fun n m => LinearMap.compr₂ (TensorProduct.mk R ((⨂[R]^n) M) ((⨂[R]^m) M)) ↑mulEquiv
⊢ (cast R M (_ : na + nb + nc = na + (nb + nc))) (GradedMonoid.GMul.mul (GradedMonoid.GMul.mul a b) c) =
    GradedMonoid.GMul.mul a (GradedMonoid.GMul.mul b c)

Next tactic:
let e : (⨂[R]^(na + nb + nc)) M ≃ₗ[R] (⨂[R]^(na + (nb + nc))) M := cast R M (add_assoc _ _ _)
theorem mul_assoc {na nb nc} (a : (⨂[R]^na) M) (b : (⨂[R]^nb) M) (c : (⨂[R]^nc) M) :
    cast R M (add_assoc _ _ _) (a ₜ* b ₜ* c) = a ₜ* (b ₜ* c) := by
  let mul : ∀ n m : ℕ, (⨂[R]^n) M →ₗ[R] (⨂[R]^m) M →ₗ[R] (⨂[R]^(n + m)) M := fun n m =>
    (TensorProduct.mk R _ _).compr₂ ↑(mulEquiv : _ ≃ₗ[R] (⨂[R]^(n + m)) M)
  -- replace `a`, `b`, `c` with `tprod R a`, `tprod R b`, `tprod R c`
  let e : (⨂[R]^(na + nb + nc)) M ≃ₗ[R] (⨂[R]^(na + (nb + nc))) M := cast R M (add_assoc _ _ _)
  

Proof state:
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
na nb nc : ℕ
a : (⨂[R]^na) M
b : (⨂[R]^nb) M
c : (⨂[R]^nc) M
mul : (n m : ℕ) → (⨂[R]^n) M →ₗ[R] (⨂[R]^m) M →ₗ[R] (⨂[R]^(n + m)) M :=
  fun n m => LinearMap.compr₂ (TensorProduct.mk R ((⨂[R]^n) M) ((⨂[R]^m) M)) ↑mulEquiv
e : (⨂[R]^(na + nb + nc)) M ≃ₗ[R] (⨂[R]^(na + (nb + nc))) M := cast R M (_ : na + nb + nc = na + (nb + nc))
⊢ (cast R M (_ : na + nb + nc = na + (nb + nc))) (GradedMonoid.GMul.mul (GradedMonoid.GMul.mul a b) c) =
    GradedMonoid.GMul.mul a (GradedMonoid.GMul.mul b c)

Next tactic:
let lhs : (⨂[R]^na) M →ₗ[R] (⨂[R]^nb) M →ₗ[R] (⨂[R]^nc) M →ₗ[R] (⨂[R]^(na + (nb + nc))) M :=
    (LinearMap.llcomp R _ _ _ ((mul _ nc).compr₂ e.toLinearMap)).comp (mul na nb)
theorem mul_assoc {na nb nc} (a : (⨂[R]^na) M) (b : (⨂[R]^nb) M) (c : (⨂[R]^nc) M) :
    cast R M (add_assoc _ _ _) (a ₜ* b ₜ* c) = a ₜ* (b ₜ* c) := by
  let mul : ∀ n m : ℕ, (⨂[R]^n) M →ₗ[R] (⨂[R]^m) M →ₗ[R] (⨂[R]^(n + m)) M := fun n m =>
    (TensorProduct.mk R _ _).compr₂ ↑(mulEquiv : _ ≃ₗ[R] (⨂[R]^(n + m)) M)
  -- replace `a`, `b`, `c` with `tprod R a`, `tprod R b`, `tprod R c`
  let e : (⨂[R]^(na + nb + nc)) M ≃ₗ[R] (⨂[R]^(na + (nb + nc))) M := cast R M (add_assoc _ _ _)
  let lhs : (⨂[R]^na) M →ₗ[R] (⨂[R]^nb) M →ₗ[R] (⨂[R]^nc) M →ₗ[R] (⨂[R]^(na + (nb + nc))) M :=
    (LinearMap.llcomp R _ _ _ ((mul _ nc).compr₂ e.toLinearMap)).comp (mul na nb)
  

Proof state:
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
na nb nc : ℕ
a : (⨂[R]^na) M
b : (⨂[R]^nb) M
c : (⨂[R]^nc) M
mul : (n m : ℕ) → (⨂[R]^n) M →ₗ[R] (⨂[R]^m) M →ₗ[R] (⨂[R]^(n + m)) M :=
  fun n m => LinearMap.compr₂ (TensorProduct.mk R ((⨂[R]^n) M) ((⨂[R]^m) M)) ↑mulEquiv
e : (⨂[R]^(na + nb + nc)) M ≃ₗ[R] (⨂[R]^(na + (nb + nc))) M := cast R M (_ : na + nb + nc = na + (nb + nc))
lhs : (⨂[R]^na) M →ₗ[R] (⨂[R]^nb) M →ₗ[R] (⨂[R]^nc) M →ₗ[R] (⨂[R]^(na + (nb + nc))) M :=
  (LinearMap.llcomp R ((⨂[R]^nb) M) ((⨂[R]^(na + nb)) M) ((⨂[R]^nc) M →ₗ[R] (⨂[R]^(na + (nb + nc))) M))
      (LinearMap.compr₂ (mul (na + nb) nc) ↑e) ∘ₗ
    mul na nb
⊢ (cast R M (_ : na + nb + nc = na + (nb + nc))) (GradedMonoid.GMul.mul (GradedMonoid.GMul.mul a b) c) =
    GradedMonoid.GMul.mul a (GradedMonoid.GMul.mul b c)

Next tactic:
have lhs_eq : ∀ a b c, lhs a b c = e (a ₜ* b ₜ* c) := fun _ _ _ => rfl
theorem mul_assoc {na nb nc} (a : (⨂[R]^na) M) (b : (⨂[R]^nb) M) (c : (⨂[R]^nc) M) :
    cast R M (add_assoc _ _ _) (a ₜ* b ₜ* c) = a ₜ* (b ₜ* c) := by
  let mul : ∀ n m : ℕ, (⨂[R]^n) M →ₗ[R] (⨂[R]^m) M →ₗ[R] (⨂[R]^(n + m)) M := fun n m =>
    (TensorProduct.mk R _ _).compr₂ ↑(mulEquiv : _ ≃ₗ[R] (⨂[R]^(n + m)) M)
  -- replace `a`, `b`, `c` with `tprod R a`, `tprod R b`, `tprod R c`
  let e : (⨂[R]^(na + nb + nc)) M ≃ₗ[R] (⨂[R]^(na + (nb + nc))) M := cast R M (add_assoc _ _ _)
  let lhs : (⨂[R]^na) M →ₗ[R] (⨂[R]^nb) M →ₗ[R] (⨂[R]^nc) M →ₗ[R] (⨂[R]^(na + (nb + nc))) M :=
    (LinearMap.llcomp R _ _ _ ((mul _ nc).compr₂ e.toLinearMap)).comp (mul na nb)
  have lhs_eq : ∀ a b c, lhs a b c = e (a ₜ* b ₜ* c) := fun _ _ _ => rfl
  

Proof state:
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
na nb nc : ℕ
a : (⨂[R]^na) M
b : (⨂[R]^nb) M
c : (⨂[R]^nc) M
mul : (n m : ℕ) → (⨂[R]^n) M →ₗ[R] (⨂[R]^m) M →ₗ[R] (⨂[R]^(n + m)) M :=
  fun n m => LinearMap.compr₂ (TensorProduct.mk R ((⨂[R]^n) M) ((⨂[R]^m) M)) ↑mulEquiv
e : (⨂[R]^(na + nb + nc)) M ≃ₗ[R] (⨂[R]^(na + (nb + nc))) M := cast R M (_ : na + nb + nc = na + (nb + nc))
lhs : (⨂[R]^na) M →ₗ[R] (⨂[R]^nb) M →ₗ[R] (⨂[R]^nc) M →ₗ[R] (⨂[R]^(na + (nb + nc))) M :=
  (LinearMap.llcomp R ((⨂[R]^nb) M) ((⨂[R]^(na + nb)) M) ((⨂[R]^nc) M →ₗ[R] (⨂[R]^(na + (nb + nc))) M))
      (LinearMap.compr₂ (mul (na + nb) nc) ↑e) ∘ₗ
    mul na nb
lhs_eq :
  ∀ (a : (⨂[R]^na) M) (b : (⨂[R]^nb) M) (c : (⨂[R]^nc) M),
    ((lhs a) b) c = e (GradedMonoid.GMul.mul (GradedMonoid.GMul.mul a b) c)
⊢ (cast R M (_ : na + nb + nc = na + (nb + nc))) (GradedMonoid.GMul.mul (GradedMonoid.GMul.mul a b) c) =
    GradedMonoid.GMul.mul a (GradedMonoid.GMul.mul b c)

Next tactic:
let rhs : (⨂[R]^na) M →ₗ[R] (⨂[R]^nb) M →ₗ[R] (⨂[R]^nc) M →ₗ[R] (⨂[R]^(na + (nb + nc))) M :=
    (LinearMap.llcomp R _ _ _ (LinearMap.lflip (R := R)) <|
        (LinearMap.llcomp R _ _ _ (mul na _).flip).comp (mul nb nc)).flip
theorem mul_assoc {na nb nc} (a : (⨂[R]^na) M) (b : (⨂[R]^nb) M) (c : (⨂[R]^nc) M) :
    cast R M (add_assoc _ _ _) (a ₜ* b ₜ* c) = a ₜ* (b ₜ* c) := by
  let mul : ∀ n m : ℕ, (⨂[R]^n) M →ₗ[R] (⨂[R]^m) M →ₗ[R] (⨂[R]^(n + m)) M := fun n m =>
    (TensorProduct.mk R _ _).compr₂ ↑(mulEquiv : _ ≃ₗ[R] (⨂[R]^(n + m)) M)
  -- replace `a`, `b`, `c` with `tprod R a`, `tprod R b`, `tprod R c`
  let e : (⨂[R]^(na + nb + nc)) M ≃ₗ[R] (⨂[R]^(na + (nb + nc))) M := cast R M (add_assoc _ _ _)
  let lhs : (⨂[R]^na) M →ₗ[R] (⨂[R]^nb) M →ₗ[R] (⨂[R]^nc) M →ₗ[R] (⨂[R]^(na + (nb + nc))) M :=
    (LinearMap.llcomp R _ _ _ ((mul _ nc).compr₂ e.toLinearMap)).comp (mul na nb)
  have lhs_eq : ∀ a b c, lhs a b c = e (a ₜ* b ₜ* c) := fun _ _ _ => rfl
  let rhs : (⨂[R]^na) M →ₗ[R] (⨂[R]^nb) M →ₗ[R] (⨂[R]^nc) M →ₗ[R] (⨂[R]^(na + (nb + nc))) M :=
    (LinearMap.llcomp R _ _ _ (LinearMap.lflip (R := R)) <|
        (LinearMap.llcomp R _ _ _ (mul na _).flip).comp (mul nb nc)).flip
  

Proof state:
R : Type u_1
M : Type u_2
inst✝² : CommSemiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
na nb nc : ℕ
a : (⨂[R]^na) M
b : (⨂[R]^nb) M
c : (⨂[R]^nc) M
mul : (n m : ℕ) → (⨂[R]^n) M →ₗ[R] (⨂[R]^m) M →ₗ[R] (⨂[R]^(n + m)) M :=
  fun n m => LinearMap.compr₂ (TensorProduct.mk R ((⨂[R]^n) M) ((⨂[R]^m) M)) ↑mulEquiv
e : (⨂[R]^(na + nb + nc)) M ≃ₗ[R] (⨂[R]^(na + (nb + nc))) M := cast R M (_ : na + nb + nc = na + (nb + nc))
lhs : (⨂[R]^na) M →ₗ[R] (⨂[R]^nb) M →ₗ[R] (⨂[R]^nc) M →ₗ[R] (⨂[R]^(na + (nb + nc))) M :=
  (LinearMap.llcomp R ((⨂[R]^nb) M) ((⨂[R]^(na + nb)) M) ((⨂[R]^nc) M →ₗ[R] (⨂[R]^(na + (nb + nc))) M))
      (LinearMap.compr₂ (mul (na + nb) nc) ↑e) ∘ₗ
    mul na nb
lhs_eq :
  ∀ (a : (⨂[R]^na) M) (b : (⨂[R]^nb) M) (c : (⨂[R]^nc) M),
    ((lhs a) b) c = e (GradedMonoid.GMul.mul (GradedMonoid.GMul.mul a b) c)
rhs : (⨂[R]^na) M →ₗ[R] (⨂[R]^nb) M →ₗ[R] (⨂[R]^nc) M →ₗ[R] (⨂[R]^(na + (nb + nc))) M :=
  LinearMap.flip
    (((LinearMap.llcomp R ((⨂[R]^nb) M) ((⨂[R]^nc) M →ₗ[R] (⨂[R]^na) M →ₗ[R] (⨂[R]^(na + (nb + nc))) M)
          ((⨂[R]^na) M →ₗ[R] (⨂[R]^nc) M →ₗ[R] (⨂[R]^(na + (nb + nc))) M))
        LinearMap.lflip)
      ((LinearMap.llcomp R ((⨂[R]^nc) M) ((⨂[R]^(nb + nc)) M) ((⨂[R]^na) M →ₗ[R] (⨂[R]^(na + (nb + nc))) M))
          (LinearMap.flip (mul na (nb + nc))) ∘ₗ
        mul nb nc))
⊢ (cast R M (_ : na + nb + nc = na + (nb + nc))) (GradedMonoid.GMul.mul (GradedMonoid.GMul.mul a b) c) =
    GradedMonoid.GMul.mul a (GradedMonoid.GMul.mul b c)

Next tactic:
have rhs_eq : ∀ a b c, rhs a b c = a ₜ* (b ₜ* c) := fun _ _ _ => rfl