l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem sym_eq_empty : s.sym n = ∅ ↔ n ≠ 0 ∧ s = ∅ := by
  cases n
  · exact iff_of_false (singleton_ne_empty _) fun h ↦ (h.1 rfl).elim
  · 

Proof state:
case succ
α : Type u_1
inst✝ : DecidableEq α
s t : Finset α
a b : α
n✝ : ℕ
m : Sym α (Nat.succ n✝)
⊢ Finset.sym s (Nat.succ n✝) = ∅ ↔ Nat.succ n✝ ≠ 0 ∧ s = ∅

Next tactic:
refine ⟨fun h ↦ ⟨Nat.succ_ne_zero _, eq_empty_of_sym_eq_empty h⟩, ?_⟩
@[simp]
theorem sym_eq_empty : s.sym n = ∅ ↔ n ≠ 0 ∧ s = ∅ := by
  cases n
  · exact iff_of_false (singleton_ne_empty _) fun h ↦ (h.1 rfl).elim
  · refine ⟨fun h ↦ ⟨Nat.succ_ne_zero _, eq_empty_of_sym_eq_empty h⟩, ?_⟩
    

Proof state:
case succ
α : Type u_1
inst✝ : DecidableEq α
s t : Finset α
a b : α
n✝ : ℕ
m : Sym α (Nat.succ n✝)
⊢ Nat.succ n✝ ≠ 0 ∧ s = ∅ → Finset.sym s (Nat.succ n✝) = ∅

Next tactic:
rintro ⟨_, rfl⟩
@[simp]
theorem sym_eq_empty : s.sym n = ∅ ↔ n ≠ 0 ∧ s = ∅ := by
  cases n
  · exact iff_of_false (singleton_ne_empty _) fun h ↦ (h.1 rfl).elim
  · refine ⟨fun h ↦ ⟨Nat.succ_ne_zero _, eq_empty_of_sym_eq_empty h⟩, ?_⟩
    rintro ⟨_, rfl⟩
    

Proof state:
case succ.intro
α : Type u_1
inst✝ : DecidableEq α
t : Finset α
a b : α
n✝ : ℕ
m : Sym α (Nat.succ n✝)
left✝ : Nat.succ n✝ ≠ 0
⊢ Finset.sym ∅ (Nat.succ n✝) = ∅

Next tactic:
exact sym_empty _
@[simp]
theorem sym_nonempty : (s.sym n).Nonempty ↔ n = 0 ∨ s.Nonempty := by
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s t : Finset α
a b : α
n : ℕ
m : Sym α n
⊢ Finset.Nonempty (Finset.sym s n) ↔ n = 0 ∨ Finset.Nonempty s

Next tactic:
simp_rw [nonempty_iff_ne_empty, Ne.def]
@[simp]
theorem sym_nonempty : (s.sym n).Nonempty ↔ n = 0 ∨ s.Nonempty := by
  simp_rw [nonempty_iff_ne_empty, Ne.def]
-- Porting note: using simp_rw does not work here, it does nothing...
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s t : Finset α
a b : α
n : ℕ
m : Sym α n
⊢ ¬Finset.sym s n = ∅ ↔ n = 0 ∨ ¬s = ∅

Next tactic:
rwa [sym_eq_empty, not_and_or, not_ne_iff]
@[simp]
theorem sym_inter (s t : Finset α) (n : ℕ) : (s ∩ t).sym n = s.sym n ∩ t.sym n := by
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s✝ t✝ : Finset α
a b : α
n✝ : ℕ
m : Sym α n✝
s t : Finset α
n : ℕ
⊢ Finset.sym (s ∩ t) n = Finset.sym s n ∩ Finset.sym t n

Next tactic:
ext m
@[simp]
theorem sym_inter (s t : Finset α) (n : ℕ) : (s ∩ t).sym n = s.sym n ∩ t.sym n := by
  ext m
  

Proof state:
case a
α : Type u_1
inst✝ : DecidableEq α
s✝ t✝ : Finset α
a b : α
n✝ : ℕ
m✝ : Sym α n✝
s t : Finset α
n : ℕ
m : Sym α n
⊢ m ∈ Finset.sym (s ∩ t) n ↔ m ∈ Finset.sym s n ∩ Finset.sym t n

Next tactic:
simp only [mem_inter, mem_sym_iff, imp_and, forall_and]
/-- If `a` does not belong to the finset `s`, then the `n`th symmetric power of `{a} ∪ s` is
  in 1-1 correspondence with the disjoint union of the `n - i`th symmetric powers of `s`,
  for `0 ≤ i ≤ n`. -/
@[simps]
def symInsertEquiv (h : a ∉ s) : (insert a s).sym n ≃ Σi : Fin (n + 1), s.sym (n - i)
    where
  toFun m := ⟨_, (m.1.filterNe a).2, by 

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s t : Finset α
a b : α
n : ℕ
m✝ : Sym α n
h : a ∉ s
m : { x // x ∈ Finset.sym (insert a s) n }
⊢ (Sym.filterNe a ↑m).snd ∈ Finset.sym s (n - ↑(Sym.filterNe a ↑m).fst)

Next tactic:
convert sym_filterNe_mem a m.2
/-- If `a` does not belong to the finset `s`, then the `n`th symmetric power of `{a} ∪ s` is
  in 1-1 correspondence with the disjoint union of the `n - i`th symmetric powers of `s`,
  for `0 ≤ i ≤ n`. -/
@[simps]
def symInsertEquiv (h : a ∉ s) : (insert a s).sym n ≃ Σi : Fin (n + 1), s.sym (n - i)
    where
  toFun m := ⟨_, (m.1.filterNe a).2, by convert sym_filterNe_mem a m.2; 

Proof state:
case h.e'_5.h.e'_3
α : Type u_1
inst✝ : DecidableEq α
s t : Finset α
a b : α
n : ℕ
m✝ : Sym α n
h : a ∉ s
m : { x // x ∈ Finset.sym (insert a s) n }
⊢ s = erase (insert a s) a

Next tactic:
rw [erase_insert h]
/-- If `a` does not belong to the finset `s`, then the `n`th symmetric power of `{a} ∪ s` is
  in 1-1 correspondence with the disjoint union of the `n - i`th symmetric powers of `s`,
  for `0 ≤ i ≤ n`. -/
@[simps]
def symInsertEquiv (h : a ∉ s) : (insert a s).sym n ≃ Σi : Fin (n + 1), s.sym (n - i)
    where
  toFun m := ⟨_, (m.1.filterNe a).2, by convert sym_filterNe_mem a m.2; rw [erase_insert h]⟩
  invFun m := ⟨m.2.1.fill a m.1, sym_fill_mem a m.2.2⟩
  left_inv m := Subtype.ext <| m.1.fill_filterNe a
  right_inv := fun ⟨i, m, hm⟩ ↦ by
    

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s t : Finset α
a b : α
n : ℕ
m✝ : Sym α n
h : a ∉ s
x✝ : (i : Fin (n + 1)) × { x // x ∈ Finset.sym s (n - ↑i) }
i : Fin (n + 1)
m : Sym α (n - ↑i)
hm : m ∈ Finset.sym s (n - ↑i)
⊢ (fun m =>
        { fst := (Sym.filterNe a ↑m).fst,
          snd :=
            { val := (Sym.filterNe a ↑m).snd,
              property := (_ : (Sym.filterNe a ↑m).snd ∈ Finset.sym s (n - ↑(Sym.filterNe a ↑m).fst)) } })
      ((fun m =>
          { val := Sym.fill a m.fst ↑m.snd, property := (_ : Sym.fill a m.fst ↑m.snd ∈ Finset.sym (insert a s) n) })
        { fst := i, snd := { val := m, property := hm } }) =
    { fst := i, snd := { val := m, property := hm } }

Next tactic:
refine' Function.Injective.sigma_map (Function.injective_id) (fun i ↦ _) _
/-- If `a` does not belong to the finset `s`, then the `n`th symmetric power of `{a} ∪ s` is
  in 1-1 correspondence with the disjoint union of the `n - i`th symmetric powers of `s`,
  for `0 ≤ i ≤ n`. -/
@[simps]
def symInsertEquiv (h : a ∉ s) : (insert a s).sym n ≃ Σi : Fin (n + 1), s.sym (n - i)
    where
  toFun m := ⟨_, (m.1.filterNe a).2, by convert sym_filterNe_mem a m.2; rw [erase_insert h]⟩
  invFun m := ⟨m.2.1.fill a m.1, sym_fill_mem a m.2.2⟩
  left_inv m := Subtype.ext <| m.1.fill_filterNe a
  right_inv := fun ⟨i, m, hm⟩ ↦ by
    refine' Function.Injective.sigma_map (Function.injective_id) (fun i ↦ _) _
    

Proof state:
case refine'_1
α : Type u_1
inst✝ : DecidableEq α
s t : Finset α
a b : α
n : ℕ
m✝ : Sym α n
h : a ∉ s
x✝ : (i : Fin (n + 1)) × { x // x ∈ Finset.sym s (n - ↑i) }
i : Fin (n + 1)
m : Sym α (n - ↑i)
hm : m ∈ Finset.sym s (n - ↑i)
⊢ Fin (n + 1) → Type ?u.24154
case refine'_2
α : Type u_1
inst✝ : DecidableEq α
s t : Finset α
a b : α
n : ℕ
m✝ : Sym α n
h : a ∉ s
x✝ : (i : Fin (n + 1)) × { x // x ∈ Finset.sym s (n - ↑i) }
i : Fin (n + 1)
m : Sym α (n - ↑i)
hm : m ∈ Finset.sym s (n - ↑i)
⊢ (a : Fin (n + 1)) → { x // x ∈ Finset.sym s (n - ↑a) } → ?refine'_1 (id a)
case refine'_3
α : Type u_1
inst✝ : DecidableEq α
s t : Finset α
a b : α
n : ℕ
m✝ : Sym α n
h : a ∉ s
x✝ : (i : Fin (n + 1)) × { x // x ∈ Finset.sym s (n - ↑i) }
i✝ : Fin (n + 1)
m : Sym α (n - ↑i✝)
hm : m ∈ Finset.sym s (n - ↑i✝)
i : Fin (n + 1)
⊢ Function.Injective (?refine'_2 i)
case refine'_4
α : Type u_1
inst✝ : DecidableEq α
s t : Finset α
a b : α
n : ℕ
m✝ : Sym α n
h : a ∉ s
x✝ : (i : Fin (n + 1)) × { x // x ∈ Finset.sym s (n - ↑i) }
i : Fin (n + 1)
m : Sym α (n - ↑i)
hm : m ∈ Finset.sym s (n - ↑i)
⊢ Sigma.map id ?refine'_2
      ((fun m =>
          { fst := (Sym.filterNe a ↑m).fst,
            snd :=
              { val := (Sym.filterNe a ↑m).snd,
                property := (_ : (Sym.filterNe a ↑m).snd ∈ Finset.sym s (n - ↑(Sym.filterNe a ↑m).fst)) } })
        ((fun m =>
            { val := Sym.fill a m.fst ↑m.snd, property := (_ : Sym.fill a m.fst ↑m.snd ∈ Finset.sym (insert a s) n) })
          { fst := i, snd := { val := m, property := hm } })) =
    Sigma.map id ?refine'_2 { fst := i, snd := { val := m, property := hm } }

Next tactic:
exact fun i ↦ Sym α (n - i)
/-- If `a` does not belong to the finset `s`, then the `n`th symmetric power of `{a} ∪ s` is
  in 1-1 correspondence with the disjoint union of the `n - i`th symmetric powers of `s`,
  for `0 ≤ i ≤ n`. -/
@[simps]
def symInsertEquiv (h : a ∉ s) : (insert a s).sym n ≃ Σi : Fin (n + 1), s.sym (n - i)
    where
  toFun m := ⟨_, (m.1.filterNe a).2, by convert sym_filterNe_mem a m.2; rw [erase_insert h]⟩
  invFun m := ⟨m.2.1.fill a m.1, sym_fill_mem a m.2.2⟩
  left_inv m := Subtype.ext <| m.1.fill_filterNe a
  right_inv := fun ⟨i, m, hm⟩ ↦ by
    refine' Function.Injective.sigma_map (Function.injective_id) (fun i ↦ _) _
    exact fun i ↦ Sym α (n - i)
    

Proof state:
case refine'_2
α : Type u_1
inst✝ : DecidableEq α
s t : Finset α
a b : α
n : ℕ
m✝ : Sym α n
h : a ∉ s
x✝ : (i : Fin (n + 1)) × { x // x ∈ Finset.sym s (n - ↑i) }
i : Fin (n + 1)
m : Sym α (n - ↑i)
hm : m ∈ Finset.sym s (n - ↑i)
⊢ (a : Fin (n + 1)) → { x // x ∈ Finset.sym s (n - ↑a) } → Sym α (n - ↑(id a))
case refine'_3
α : Type u_1
inst✝ : DecidableEq α
s t : Finset α
a b : α
n : ℕ
m✝ : Sym α n
h : a ∉ s
x✝ : (i : Fin (n + 1)) × { x // x ∈ Finset.sym s (n - ↑i) }
i✝ : Fin (n + 1)
m : Sym α (n - ↑i✝)
hm : m ∈ Finset.sym s (n - ↑i✝)
i : Fin (n + 1)
⊢ Function.Injective (?refine'_2 i)
case refine'_4
α : Type u_1
inst✝ : DecidableEq α
s t : Finset α
a b : α
n : ℕ
m✝ : Sym α n
h : a ∉ s
x✝ : (i : Fin (n + 1)) × { x // x ∈ Finset.sym s (n - ↑i) }
i : Fin (n + 1)
m : Sym α (n - ↑i)
hm : m ∈ Finset.sym s (n - ↑i)
⊢ Sigma.map id ?refine'_2
      ((fun m =>
          { fst := (Sym.filterNe a ↑m).fst,
            snd :=
              { val := (Sym.filterNe a ↑m).snd,
                property := (_ : (Sym.filterNe a ↑m).snd ∈ Finset.sym s (n - ↑(Sym.filterNe a ↑m).fst)) } })
        ((fun m =>
            { val := Sym.fill a m.fst ↑m.snd, property := (_ : Sym.fill a m.fst ↑m.snd ∈ Finset.sym (insert a s) n) })
          { fst := i, snd := { val := m, property := hm } })) =
    Sigma.map id ?refine'_2 { fst := i, snd := { val := m, property := hm } }

Next tactic:
swap
/-- If `a` does not belong to the finset `s`, then the `n`th symmetric power of `{a} ∪ s` is
  in 1-1 correspondence with the disjoint union of the `n - i`th symmetric powers of `s`,
  for `0 ≤ i ≤ n`. -/
@[simps]
def symInsertEquiv (h : a ∉ s) : (insert a s).sym n ≃ Σi : Fin (n + 1), s.sym (n - i)
    where
  toFun m := ⟨_, (m.1.filterNe a).2, by convert sym_filterNe_mem a m.2; rw [erase_insert h]⟩
  invFun m := ⟨m.2.1.fill a m.1, sym_fill_mem a m.2.2⟩
  left_inv m := Subtype.ext <| m.1.fill_filterNe a
  right_inv := fun ⟨i, m, hm⟩ ↦ by
    refine' Function.Injective.sigma_map (Function.injective_id) (fun i ↦ _) _
    exact fun i ↦ Sym α (n - i)
    swap; 

Proof state:
case refine'_3
α : Type u_1
inst✝ : DecidableEq α
s t : Finset α
a b : α
n : ℕ
m✝ : Sym α n
h : a ∉ s
x✝ : (i : Fin (n + 1)) × { x // x ∈ Finset.sym s (n - ↑i) }
i✝ : Fin (n + 1)
m : Sym α (n - ↑i✝)
hm : m ∈ Finset.sym s (n - ↑i✝)
i : Fin (n + 1)
⊢ Function.Injective (?refine'_2 i)
case refine'_2
α : Type u_1
inst✝ : DecidableEq α
s t : Finset α
a b : α
n : ℕ
m✝ : Sym α n
h : a ∉ s
x✝ : (i : Fin (n + 1)) × { x // x ∈ Finset.sym s (n - ↑i) }
i : Fin (n + 1)
m : Sym α (n - ↑i)
hm : m ∈ Finset.sym s (n - ↑i)
⊢ (a : Fin (n + 1)) → { x // x ∈ Finset.sym s (n - ↑a) } → Sym α (n - ↑(id a))
case refine'_4
α : Type u_1
inst✝ : DecidableEq α
s t : Finset α
a b : α
n : ℕ
m✝ : Sym α n
h : a ∉ s
x✝ : (i : Fin (n + 1)) × { x // x ∈ Finset.sym s (n - ↑i) }
i : Fin (n + 1)
m : Sym α (n - ↑i)
hm : m ∈ Finset.sym s (n - ↑i)
⊢ Sigma.map id ?refine'_2
      ((fun m =>
          { fst := (Sym.filterNe a ↑m).fst,
            snd :=
              { val := (Sym.filterNe a ↑m).snd,
                property := (_ : (Sym.filterNe a ↑m).snd ∈ Finset.sym s (n - ↑(Sym.filterNe a ↑m).fst)) } })
        ((fun m =>
            { val := Sym.fill a m.fst ↑m.snd, property := (_ : Sym.fill a m.fst ↑m.snd ∈ Finset.sym (insert a s) n) })
          { fst := i, snd := { val := m, property := hm } })) =
    Sigma.map id ?refine'_2 { fst := i, snd := { val := m, property := hm } }

Next tactic:
exact Subtype.coe_injective
/-- If `a` does not belong to the finset `s`, then the `n`th symmetric power of `{a} ∪ s` is
  in 1-1 correspondence with the disjoint union of the `n - i`th symmetric powers of `s`,
  for `0 ≤ i ≤ n`. -/
@[simps]
def symInsertEquiv (h : a ∉ s) : (insert a s).sym n ≃ Σi : Fin (n + 1), s.sym (n - i)
    where
  toFun m := ⟨_, (m.1.filterNe a).2, by convert sym_filterNe_mem a m.2; rw [erase_insert h]⟩
  invFun m := ⟨m.2.1.fill a m.1, sym_fill_mem a m.2.2⟩
  left_inv m := Subtype.ext <| m.1.fill_filterNe a
  right_inv := fun ⟨i, m, hm⟩ ↦ by
    refine' Function.Injective.sigma_map (Function.injective_id) (fun i ↦ _) _
    exact fun i ↦ Sym α (n - i)
    swap; exact Subtype.coe_injective
    

Proof state:
case refine'_4
α : Type u_1
inst✝ : DecidableEq α
s t : Finset α
a b : α
n : ℕ
m✝ : Sym α n
h : a ∉ s
x✝ : (i : Fin (n + 1)) × { x // x ∈ Finset.sym s (n - ↑i) }
i : Fin (n + 1)
m : Sym α (n - ↑i)
hm : m ∈ Finset.sym s (n - ↑i)
⊢ Sigma.map id (fun i a => ↑a)
      ((fun m =>
          { fst := (Sym.filterNe a ↑m).fst,
            snd :=
              { val := (Sym.filterNe a ↑m).snd,
                property := (_ : (Sym.filterNe a ↑m).snd ∈ Finset.sym s (n - ↑(Sym.filterNe a ↑m).fst)) } })
        ((fun m =>
            { val := Sym.fill a m.fst ↑m.snd, property := (_ : Sym.fill a m.fst ↑m.snd ∈ Finset.sym (insert a s) n) })
          { fst := i, snd := { val := m, property := hm } })) =
    Sigma.map id (fun i a => ↑a) { fst := i, snd := { val := m, property := hm } }

Next tactic:
refine Eq.trans ?_ (Sym.filter_ne_fill a _ ?_)
/-- If `a` does not belong to the finset `s`, then the `n`th symmetric power of `{a} ∪ s` is
  in 1-1 correspondence with the disjoint union of the `n - i`th symmetric powers of `s`,
  for `0 ≤ i ≤ n`. -/
@[simps]
def symInsertEquiv (h : a ∉ s) : (insert a s).sym n ≃ Σi : Fin (n + 1), s.sym (n - i)
    where
  toFun m := ⟨_, (m.1.filterNe a).2, by convert sym_filterNe_mem a m.2; rw [erase_insert h]⟩
  invFun m := ⟨m.2.1.fill a m.1, sym_fill_mem a m.2.2⟩
  left_inv m := Subtype.ext <| m.1.fill_filterNe a
  right_inv := fun ⟨i, m, hm⟩ ↦ by
    refine' Function.Injective.sigma_map (Function.injective_id) (fun i ↦ _) _
    exact fun i ↦ Sym α (n - i)
    swap; exact Subtype.coe_injective
    refine Eq.trans ?_ (Sym.filter_ne_fill a _ ?_)
    

Proof state:
case refine'_4.refine_1
α : Type u_1
inst✝ : DecidableEq α
s t : Finset α
a b : α
n : ℕ
m✝ : Sym α n
h : a ∉ s
x✝ : (i : Fin (n + 1)) × { x // x ∈ Finset.sym s (n - ↑i) }
i : Fin (n + 1)
m : Sym α (n - ↑i)
hm : m ∈ Finset.sym s (n - ↑i)
⊢ Sigma.map id (fun i a => ↑a)
      ((fun m =>
          { fst := (Sym.filterNe a ↑m).fst,
            snd :=
              { val := (Sym.filterNe a ↑m).snd,
                property := (_ : (Sym.filterNe a ↑m).snd ∈ Finset.sym s (n - ↑(Sym.filterNe a ↑m).fst)) } })
        ((fun m =>
            { val := Sym.fill a m.fst ↑m.snd, property := (_ : Sym.fill a m.fst ↑m.snd ∈ Finset.sym (insert a s) n) })
          { fst := i, snd := { val := m, property := hm } })) =
    Sym.filterNe a
      (Sym.fill a (Sigma.map id (fun i a => ↑a) { fst := i, snd := { val := m, property := hm } }).fst
        (Sigma.map id (fun i a => ↑a) { fst := i, snd := { val := m, property := hm } }).snd)
case refine'_4.refine_2
α : Type u_1
inst✝ : DecidableEq α
s t : Finset α
a b : α
n : ℕ
m✝ : Sym α n
h : a ∉ s
x✝ : (i : Fin (n + 1)) × { x // x ∈ Finset.sym s (n - ↑i) }
i : Fin (n + 1)
m : Sym α (n - ↑i)
hm : m ∈ Finset.sym s (n - ↑i)
⊢ a ∉ (Sigma.map id (fun i a => ↑a) { fst := i, snd := { val := m, property := hm } }).snd

Next tactic:
exacts [rfl, h ∘ mem_sym_iff.1 hm a]
/-- `latToBddLat` is left adjoint to the forgetful functor, meaning it is the free
functor from `Lat` to `BddLat`. -/
def latToBddLatForgetAdjunction : latToBddLat.{u} ⊣ forget₂ BddLat Lat :=
  Adjunction.mkOfHomEquiv
    { homEquiv := fun X Y =>
        { toFun := fun f =>
            { toFun := f ∘ some ∘ some
              map_sup' := fun a b => (congr_arg f <| by 

Proof state:
X : Lat
Y : BddLat
f : latToBddLat.obj X ⟶ Y
a b : ↑X
⊢ (some ∘ some) (a ⊔ b) = (some ∘ some) a ⊔ (some ∘ some) b

Next tactic:
rfl
/-- `latToBddLat` is left adjoint to the forgetful functor, meaning it is the free
functor from `Lat` to `BddLat`. -/
def latToBddLatForgetAdjunction : latToBddLat.{u} ⊣ forget₂ BddLat Lat :=
  Adjunction.mkOfHomEquiv
    { homEquiv := fun X Y =>
        { toFun := fun f =>
            { toFun := f ∘ some ∘ some
              map_sup' := fun a b => (congr_arg f <| by rfl).trans (f.map_sup' _ _)
              map_inf' := fun a b => (congr_arg f <| by 

Proof state:
X : Lat
Y : BddLat
f : latToBddLat.obj X ⟶ Y
a b : ↑X
⊢ (some ∘ some) (a ⊓ b) = (some ∘ some) a ⊓ (some ∘ some) b

Next tactic:
rfl
theorem not_neZero {n : R} : ¬NeZero n ↔ n = 0 := by 

Proof state:
R : Type u_1
inst✝ : Zero R
n : R
⊢ ¬NeZero n ↔ n = 0

Next tactic:
simp [neZero_iff]
@[simp]
theorem toDirectSum_mul [DecidableEq ι] [AddMonoid ι] [Semiring M] (f g : AddMonoidAlgebra M ι) :
    (f * g).toDirectSum = f.toDirectSum * g.toDirectSum := by
  

Proof state:
ι : Type u_1
R : Type u_2
M : Type u_3
A : Type u_4
inst✝² : DecidableEq ι
inst✝¹ : AddMonoid ι
inst✝ : Semiring M
f g : M[ι]
⊢ toDirectSum (f * g) = toDirectSum f * toDirectSum g

Next tactic:
let to_hom : AddMonoidAlgebra M ι →+ ⨁ _ : ι, M :=
  { toFun := toDirectSum
    map_zero' := toDirectSum_zero
    map_add' := toDirectSum_add }
@[simp]
theorem toDirectSum_mul [DecidableEq ι] [AddMonoid ι] [Semiring M] (f g : AddMonoidAlgebra M ι) :
    (f * g).toDirectSum = f.toDirectSum * g.toDirectSum := by
  let to_hom : AddMonoidAlgebra M ι →+ ⨁ _ : ι, M :=
  { toFun := toDirectSum
    map_zero' := toDirectSum_zero
    map_add' := toDirectSum_add }
  

Proof state:
ι : Type u_1
R : Type u_2
M : Type u_3
A : Type u_4
inst✝² : DecidableEq ι
inst✝¹ : AddMonoid ι
inst✝ : Semiring M
f g : M[ι]
to_hom : M[ι] →+ ⨁ (x : ι), M :=
  { toZeroHom := { toFun := toDirectSum, map_zero' := (_ : toDirectSum 0 = 0) },
    map_add' := (_ : ∀ (f g : M[ι]), toDirectSum (f + g) = toDirectSum f + toDirectSum g) }
⊢ toDirectSum (f * g) = toDirectSum f * toDirectSum g

Next tactic:
show to_hom (f * g) = to_hom f * to_hom g
@[simp]
theorem toDirectSum_mul [DecidableEq ι] [AddMonoid ι] [Semiring M] (f g : AddMonoidAlgebra M ι) :
    (f * g).toDirectSum = f.toDirectSum * g.toDirectSum := by
  let to_hom : AddMonoidAlgebra M ι →+ ⨁ _ : ι, M :=
  { toFun := toDirectSum
    map_zero' := toDirectSum_zero
    map_add' := toDirectSum_add }
  show to_hom (f * g) = to_hom f * to_hom g
  

Proof state:
ι : Type u_1
R : Type u_2
M : Type u_3
A : Type u_4
inst✝² : DecidableEq ι
inst✝¹ : AddMonoid ι
inst✝ : Semiring M
f g : M[ι]
to_hom : M[ι] →+ ⨁ (x : ι), M :=
  { toZeroHom := { toFun := toDirectSum, map_zero' := (_ : toDirectSum 0 = 0) },
    map_add' := (_ : ∀ (f g : M[ι]), toDirectSum (f + g) = toDirectSum f + toDirectSum g) }
⊢ to_hom (f * g) = to_hom f * to_hom g

Next tactic:
let _ : NonUnitalNonAssocSemiring (ι →₀ M) := AddMonoidAlgebra.nonUnitalNonAssocSemiring
@[simp]
theorem toDirectSum_mul [DecidableEq ι] [AddMonoid ι] [Semiring M] (f g : AddMonoidAlgebra M ι) :
    (f * g).toDirectSum = f.toDirectSum * g.toDirectSum := by
  let to_hom : AddMonoidAlgebra M ι →+ ⨁ _ : ι, M :=
  { toFun := toDirectSum
    map_zero' := toDirectSum_zero
    map_add' := toDirectSum_add }
  show to_hom (f * g) = to_hom f * to_hom g
  let _ : NonUnitalNonAssocSemiring (ι →₀ M) := AddMonoidAlgebra.nonUnitalNonAssocSemiring
  

Proof state:
ι : Type u_1
R : Type u_2
M : Type u_3
A : Type u_4
inst✝² : DecidableEq ι
inst✝¹ : AddMonoid ι
inst✝ : Semiring M
f g : M[ι]
to_hom : M[ι] →+ ⨁ (x : ι), M :=
  { toZeroHom := { toFun := toDirectSum, map_zero' := (_ : toDirectSum 0 = 0) },
    map_add' := (_ : ∀ (f g : M[ι]), toDirectSum (f + g) = toDirectSum f + toDirectSum g) }
x✝ : NonUnitalNonAssocSemiring (ι →₀ M) := nonUnitalNonAssocSemiring
⊢ to_hom (f * g) = to_hom f * to_hom g

Next tactic:
revert f g
@[simp]
theorem toDirectSum_mul [DecidableEq ι] [AddMonoid ι] [Semiring M] (f g : AddMonoidAlgebra M ι) :
    (f * g).toDirectSum = f.toDirectSum * g.toDirectSum := by
  let to_hom : AddMonoidAlgebra M ι →+ ⨁ _ : ι, M :=
  { toFun := toDirectSum
    map_zero' := toDirectSum_zero
    map_add' := toDirectSum_add }
  show to_hom (f * g) = to_hom f * to_hom g
  let _ : NonUnitalNonAssocSemiring (ι →₀ M) := AddMonoidAlgebra.nonUnitalNonAssocSemiring
  revert f g
  

Proof state:
ι : Type u_1
R : Type u_2
M : Type u_3
A : Type u_4
inst✝² : DecidableEq ι
inst✝¹ : AddMonoid ι
inst✝ : Semiring M
to_hom : M[ι] →+ ⨁ (x : ι), M :=
  { toZeroHom := { toFun := toDirectSum, map_zero' := (_ : toDirectSum 0 = 0) },
    map_add' := (_ : ∀ (f g : M[ι]), toDirectSum (f + g) = toDirectSum f + toDirectSum g) }
x✝ : NonUnitalNonAssocSemiring (ι →₀ M) := nonUnitalNonAssocSemiring
⊢ ∀ (f g : M[ι]), to_hom (f * g) = to_hom f * to_hom g

Next tactic:
rw [AddMonoidHom.map_mul_iff]
@[simp]
theorem toDirectSum_mul [DecidableEq ι] [AddMonoid ι] [Semiring M] (f g : AddMonoidAlgebra M ι) :
    (f * g).toDirectSum = f.toDirectSum * g.toDirectSum := by
  let to_hom : AddMonoidAlgebra M ι →+ ⨁ _ : ι, M :=
  { toFun := toDirectSum
    map_zero' := toDirectSum_zero
    map_add' := toDirectSum_add }
  show to_hom (f * g) = to_hom f * to_hom g
  let _ : NonUnitalNonAssocSemiring (ι →₀ M) := AddMonoidAlgebra.nonUnitalNonAssocSemiring
  revert f g
  rw [AddMonoidHom.map_mul_iff]
  -- porting note: does not find `addHom_ext'`, was `ext (xi xv yi yv) : 4`
  

Proof state:
ι : Type u_1
R : Type u_2
M : Type u_3
A : Type u_4
inst✝² : DecidableEq ι
inst✝¹ : AddMonoid ι
inst✝ : Semiring M
to_hom : M[ι] →+ ⨁ (x : ι), M :=
  { toZeroHom := { toFun := toDirectSum, map_zero' := (_ : toDirectSum 0 = 0) },
    map_add' := (_ : ∀ (f g : M[ι]), toDirectSum (f + g) = toDirectSum f + toDirectSum g) }
x✝ : NonUnitalNonAssocSemiring (ι →₀ M) := nonUnitalNonAssocSemiring
⊢ AddMonoidHom.compr₂ AddMonoidHom.mul to_hom = AddMonoidHom.compl₂ (AddMonoidHom.comp AddMonoidHom.mul to_hom) to_hom

Next tactic:
refine Finsupp.addHom_ext' fun xi => AddMonoidHom.ext fun xv => ?_
@[simp]
theorem toDirectSum_mul [DecidableEq ι] [AddMonoid ι] [Semiring M] (f g : AddMonoidAlgebra M ι) :
    (f * g).toDirectSum = f.toDirectSum * g.toDirectSum := by
  let to_hom : AddMonoidAlgebra M ι →+ ⨁ _ : ι, M :=
  { toFun := toDirectSum
    map_zero' := toDirectSum_zero
    map_add' := toDirectSum_add }
  show to_hom (f * g) = to_hom f * to_hom g
  let _ : NonUnitalNonAssocSemiring (ι →₀ M) := AddMonoidAlgebra.nonUnitalNonAssocSemiring
  revert f g
  rw [AddMonoidHom.map_mul_iff]
  -- porting note: does not find `addHom_ext'`, was `ext (xi xv yi yv) : 4`
  refine Finsupp.addHom_ext' fun xi => AddMonoidHom.ext fun xv => ?_
  

Proof state:
ι : Type u_1
R : Type u_2
M : Type u_3
A : Type u_4
inst✝² : DecidableEq ι
inst✝¹ : AddMonoid ι
inst✝ : Semiring M
to_hom : M[ι] →+ ⨁ (x : ι), M :=
  { toZeroHom := { toFun := toDirectSum, map_zero' := (_ : toDirectSum 0 = 0) },
    map_add' := (_ : ∀ (f g : M[ι]), toDirectSum (f + g) = toDirectSum f + toDirectSum g) }
x✝ : NonUnitalNonAssocSemiring (ι →₀ M) := nonUnitalNonAssocSemiring
xi : ι
xv : M
⊢ (AddMonoidHom.comp (AddMonoidHom.compr₂ AddMonoidHom.mul to_hom) (Finsupp.singleAddHom xi)) xv =
    (AddMonoidHom.comp (AddMonoidHom.compl₂ (AddMonoidHom.comp AddMonoidHom.mul to_hom) to_hom)
        (Finsupp.singleAddHom xi))
      xv

Next tactic:
refine Finsupp.addHom_ext' fun yi => AddMonoidHom.ext fun yv => ?_