l3lab/ntp-mathlib huggingface dataset:
theorem mem_smul_iff {i j : ι} {m₁ : M i} {m₂ : M j} {w : Word M} :
    ⟨_, m₁⟩ ∈ (of m₂ • w).toList ↔
      (¬i = j ∧ ⟨i, m₁⟩ ∈ w.toList)
      ∨ (m₁ ≠ 1 ∧ ∃ (hij : i = j),(⟨i, m₁⟩ ∈ w.toList.tail) ∨
        (∃ m', ⟨j, m'⟩ ∈ w.toList.head? ∧ m₁ = hij ▸ (m₂ * m')) ∨
        (w.fstIdx ≠ some j ∧ m₁ = hij ▸ m₂)) := by
  rw [of_smul_def, mem_rcons_iff, mem_equivPair_tail_iff, equivPair_head, or_assoc]
  by_cases hij : i = j
  · subst i
    simp only [not_true, ne_eq, false_and, exists_prop, true_and, false_or]
    by_cases hw : ⟨j, m₁⟩ ∈ w.toList.tail
    · simp [hw, show m₁ ≠ 1 from w.ne_one _ (List.mem_of_mem_tail hw)]
    · simp only [hw, false_or, Option.mem_def, ne_eq, and_congr_right_iff]
      intro hm1
      split_ifs with h
      · rcases h with ⟨hnil, rfl⟩
        simp only [List.head?_eq_head _ hnil, Option.some.injEq, ne_eq]
        constructor
        · rintro rfl
          exact Or.inl ⟨_, rfl, rfl⟩
        · rintro (⟨_, h, rfl⟩ | hm')
          · simp [Sigma.ext_iff] at h
            subst h
            rfl
          · 

Proof state:
case pos.intro.mpr.inr
ι : Type u_1
M : ι → Type u_2
inst✝³ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝² : Monoid N
inst✝¹ : (i : ι) → DecidableEq (M i)
inst✝ : DecidableEq ι
w : Word M
hnil : ¬w.toList = []
m₂ m₁ : M (List.head w.toList hnil).fst
hw : { fst := (List.head w.toList hnil).fst, snd := m₁ } ∉ List.tail w.toList
hm1 : ¬m₁ = 1
hm' : ¬fstIdx w = some (List.head w.toList hnil).fst ∧ m₁ = m₂
⊢ m₁ = m₂ * (List.head w.toList (_ : ¬w.toList = [])).snd

Next tactic:
simp only [fstIdx, Option.map_eq_some', Sigma.exists,
              exists_and_right, exists_eq_right, not_exists, ne_eq] at hm'
theorem mem_smul_iff {i j : ι} {m₁ : M i} {m₂ : M j} {w : Word M} :
    ⟨_, m₁⟩ ∈ (of m₂ • w).toList ↔
      (¬i = j ∧ ⟨i, m₁⟩ ∈ w.toList)
      ∨ (m₁ ≠ 1 ∧ ∃ (hij : i = j),(⟨i, m₁⟩ ∈ w.toList.tail) ∨
        (∃ m', ⟨j, m'⟩ ∈ w.toList.head? ∧ m₁ = hij ▸ (m₂ * m')) ∨
        (w.fstIdx ≠ some j ∧ m₁ = hij ▸ m₂)) := by
  rw [of_smul_def, mem_rcons_iff, mem_equivPair_tail_iff, equivPair_head, or_assoc]
  by_cases hij : i = j
  · subst i
    simp only [not_true, ne_eq, false_and, exists_prop, true_and, false_or]
    by_cases hw : ⟨j, m₁⟩ ∈ w.toList.tail
    · simp [hw, show m₁ ≠ 1 from w.ne_one _ (List.mem_of_mem_tail hw)]
    · simp only [hw, false_or, Option.mem_def, ne_eq, and_congr_right_iff]
      intro hm1
      split_ifs with h
      · rcases h with ⟨hnil, rfl⟩
        simp only [List.head?_eq_head _ hnil, Option.some.injEq, ne_eq]
        constructor
        · rintro rfl
          exact Or.inl ⟨_, rfl, rfl⟩
        · rintro (⟨_, h, rfl⟩ | hm')
          · simp [Sigma.ext_iff] at h
            subst h
            rfl
          · simp only [fstIdx, Option.map_eq_some', Sigma.exists,
              exists_and_right, exists_eq_right, not_exists, ne_eq] at hm'
            

Proof state:
case pos.intro.mpr.inr
ι : Type u_1
M : ι → Type u_2
inst✝³ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝² : Monoid N
inst✝¹ : (i : ι) → DecidableEq (M i)
inst✝ : DecidableEq ι
w : Word M
hnil : ¬w.toList = []
m₂ m₁ : M (List.head w.toList hnil).fst
hw : { fst := (List.head w.toList hnil).fst, snd := m₁ } ∉ List.tail w.toList
hm1 : ¬m₁ = 1
hm' :
  (∀ (x : M (List.head w.toList hnil).fst),
      ¬List.head? w.toList = some { fst := (List.head w.toList hnil).fst, snd := x }) ∧
    m₁ = m₂
⊢ m₁ = m₂ * (List.head w.toList (_ : ¬w.toList = [])).snd

Next tactic:
exact (hm'.1 (w.toList.head hnil).2 (by rw [List.head?_eq_head])).elim
theorem mem_smul_iff {i j : ι} {m₁ : M i} {m₂ : M j} {w : Word M} :
    ⟨_, m₁⟩ ∈ (of m₂ • w).toList ↔
      (¬i = j ∧ ⟨i, m₁⟩ ∈ w.toList)
      ∨ (m₁ ≠ 1 ∧ ∃ (hij : i = j),(⟨i, m₁⟩ ∈ w.toList.tail) ∨
        (∃ m', ⟨j, m'⟩ ∈ w.toList.head? ∧ m₁ = hij ▸ (m₂ * m')) ∨
        (w.fstIdx ≠ some j ∧ m₁ = hij ▸ m₂)) := by
  rw [of_smul_def, mem_rcons_iff, mem_equivPair_tail_iff, equivPair_head, or_assoc]
  by_cases hij : i = j
  · subst i
    simp only [not_true, ne_eq, false_and, exists_prop, true_and, false_or]
    by_cases hw : ⟨j, m₁⟩ ∈ w.toList.tail
    · simp [hw, show m₁ ≠ 1 from w.ne_one _ (List.mem_of_mem_tail hw)]
    · simp only [hw, false_or, Option.mem_def, ne_eq, and_congr_right_iff]
      intro hm1
      split_ifs with h
      · rcases h with ⟨hnil, rfl⟩
        simp only [List.head?_eq_head _ hnil, Option.some.injEq, ne_eq]
        constructor
        · rintro rfl
          exact Or.inl ⟨_, rfl, rfl⟩
        · rintro (⟨_, h, rfl⟩ | hm')
          · simp [Sigma.ext_iff] at h
            subst h
            rfl
          · simp only [fstIdx, Option.map_eq_some', Sigma.exists,
              exists_and_right, exists_eq_right, not_exists, ne_eq] at hm'
            exact (hm'.1 (w.toList.head hnil).2 (by 

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝³ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝² : Monoid N
inst✝¹ : (i : ι) → DecidableEq (M i)
inst✝ : DecidableEq ι
w : Word M
hnil : ¬w.toList = []
m₂ m₁ : M (List.head w.toList hnil).fst
hw : { fst := (List.head w.toList hnil).fst, snd := m₁ } ∉ List.tail w.toList
hm1 : ¬m₁ = 1
hm' :
  (∀ (x : M (List.head w.toList hnil).fst),
      ¬List.head? w.toList = some { fst := (List.head w.toList hnil).fst, snd := x }) ∧
    m₁ = m₂
⊢ List.head? w.toList = some { fst := (List.head w.toList hnil).fst, snd := (List.head w.toList hnil).snd }

Next tactic:
rw [List.head?_eq_head]
theorem mem_smul_iff {i j : ι} {m₁ : M i} {m₂ : M j} {w : Word M} :
    ⟨_, m₁⟩ ∈ (of m₂ • w).toList ↔
      (¬i = j ∧ ⟨i, m₁⟩ ∈ w.toList)
      ∨ (m₁ ≠ 1 ∧ ∃ (hij : i = j),(⟨i, m₁⟩ ∈ w.toList.tail) ∨
        (∃ m', ⟨j, m'⟩ ∈ w.toList.head? ∧ m₁ = hij ▸ (m₂ * m')) ∨
        (w.fstIdx ≠ some j ∧ m₁ = hij ▸ m₂)) := by
  rw [of_smul_def, mem_rcons_iff, mem_equivPair_tail_iff, equivPair_head, or_assoc]
  by_cases hij : i = j
  · subst i
    simp only [not_true, ne_eq, false_and, exists_prop, true_and, false_or]
    by_cases hw : ⟨j, m₁⟩ ∈ w.toList.tail
    · simp [hw, show m₁ ≠ 1 from w.ne_one _ (List.mem_of_mem_tail hw)]
    · simp only [hw, false_or, Option.mem_def, ne_eq, and_congr_right_iff]
      intro hm1
      split_ifs with h
      · rcases h with ⟨hnil, rfl⟩
        simp only [List.head?_eq_head _ hnil, Option.some.injEq, ne_eq]
        constructor
        · rintro rfl
          exact Or.inl ⟨_, rfl, rfl⟩
        · rintro (⟨_, h, rfl⟩ | hm')
          · simp [Sigma.ext_iff] at h
            subst h
            rfl
          · simp only [fstIdx, Option.map_eq_some', Sigma.exists,
              exists_and_right, exists_eq_right, not_exists, ne_eq] at hm'
            exact (hm'.1 (w.toList.head hnil).2 (by rw [List.head?_eq_head])).elim
      · 

Proof state:
case neg
ι : Type u_1
M : ι → Type u_2
inst✝³ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝² : Monoid N
inst✝¹ : (i : ι) → DecidableEq (M i)
inst✝ : DecidableEq ι
j : ι
m₂ : M j
w : Word M
m₁ : M j
hw : { fst := j, snd := m₁ } ∉ List.tail w.toList
hm1 : ¬m₁ = 1
h : ¬∃ (h : ¬w.toList = []), (List.head w.toList h).fst = j
⊢ m₁ = m₂ * 1 ↔ (∃ m', List.head? w.toList = some { fst := j, snd := m' } ∧ m₁ = m₂ * m') ∨ ¬fstIdx w = some j ∧ m₁ = m₂

Next tactic:
revert h
theorem mem_smul_iff {i j : ι} {m₁ : M i} {m₂ : M j} {w : Word M} :
    ⟨_, m₁⟩ ∈ (of m₂ • w).toList ↔
      (¬i = j ∧ ⟨i, m₁⟩ ∈ w.toList)
      ∨ (m₁ ≠ 1 ∧ ∃ (hij : i = j),(⟨i, m₁⟩ ∈ w.toList.tail) ∨
        (∃ m', ⟨j, m'⟩ ∈ w.toList.head? ∧ m₁ = hij ▸ (m₂ * m')) ∨
        (w.fstIdx ≠ some j ∧ m₁ = hij ▸ m₂)) := by
  rw [of_smul_def, mem_rcons_iff, mem_equivPair_tail_iff, equivPair_head, or_assoc]
  by_cases hij : i = j
  · subst i
    simp only [not_true, ne_eq, false_and, exists_prop, true_and, false_or]
    by_cases hw : ⟨j, m₁⟩ ∈ w.toList.tail
    · simp [hw, show m₁ ≠ 1 from w.ne_one _ (List.mem_of_mem_tail hw)]
    · simp only [hw, false_or, Option.mem_def, ne_eq, and_congr_right_iff]
      intro hm1
      split_ifs with h
      · rcases h with ⟨hnil, rfl⟩
        simp only [List.head?_eq_head _ hnil, Option.some.injEq, ne_eq]
        constructor
        · rintro rfl
          exact Or.inl ⟨_, rfl, rfl⟩
        · rintro (⟨_, h, rfl⟩ | hm')
          · simp [Sigma.ext_iff] at h
            subst h
            rfl
          · simp only [fstIdx, Option.map_eq_some', Sigma.exists,
              exists_and_right, exists_eq_right, not_exists, ne_eq] at hm'
            exact (hm'.1 (w.toList.head hnil).2 (by rw [List.head?_eq_head])).elim
      · revert h
        

Proof state:
case neg
ι : Type u_1
M : ι → Type u_2
inst✝³ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝² : Monoid N
inst✝¹ : (i : ι) → DecidableEq (M i)
inst✝ : DecidableEq ι
j : ι
m₂ : M j
w : Word M
m₁ : M j
hw : { fst := j, snd := m₁ } ∉ List.tail w.toList
hm1 : ¬m₁ = 1
⊢ (¬∃ (h : ¬w.toList = []), (List.head w.toList h).fst = j) →
    (m₁ = m₂ * 1 ↔
      (∃ m', List.head? w.toList = some { fst := j, snd := m' } ∧ m₁ = m₂ * m') ∨ ¬fstIdx w = some j ∧ m₁ = m₂)

Next tactic:
rw [fstIdx]
theorem mem_smul_iff {i j : ι} {m₁ : M i} {m₂ : M j} {w : Word M} :
    ⟨_, m₁⟩ ∈ (of m₂ • w).toList ↔
      (¬i = j ∧ ⟨i, m₁⟩ ∈ w.toList)
      ∨ (m₁ ≠ 1 ∧ ∃ (hij : i = j),(⟨i, m₁⟩ ∈ w.toList.tail) ∨
        (∃ m', ⟨j, m'⟩ ∈ w.toList.head? ∧ m₁ = hij ▸ (m₂ * m')) ∨
        (w.fstIdx ≠ some j ∧ m₁ = hij ▸ m₂)) := by
  rw [of_smul_def, mem_rcons_iff, mem_equivPair_tail_iff, equivPair_head, or_assoc]
  by_cases hij : i = j
  · subst i
    simp only [not_true, ne_eq, false_and, exists_prop, true_and, false_or]
    by_cases hw : ⟨j, m₁⟩ ∈ w.toList.tail
    · simp [hw, show m₁ ≠ 1 from w.ne_one _ (List.mem_of_mem_tail hw)]
    · simp only [hw, false_or, Option.mem_def, ne_eq, and_congr_right_iff]
      intro hm1
      split_ifs with h
      · rcases h with ⟨hnil, rfl⟩
        simp only [List.head?_eq_head _ hnil, Option.some.injEq, ne_eq]
        constructor
        · rintro rfl
          exact Or.inl ⟨_, rfl, rfl⟩
        · rintro (⟨_, h, rfl⟩ | hm')
          · simp [Sigma.ext_iff] at h
            subst h
            rfl
          · simp only [fstIdx, Option.map_eq_some', Sigma.exists,
              exists_and_right, exists_eq_right, not_exists, ne_eq] at hm'
            exact (hm'.1 (w.toList.head hnil).2 (by rw [List.head?_eq_head])).elim
      · revert h
        rw [fstIdx]
        

Proof state:
case neg
ι : Type u_1
M : ι → Type u_2
inst✝³ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝² : Monoid N
inst✝¹ : (i : ι) → DecidableEq (M i)
inst✝ : DecidableEq ι
j : ι
m₂ : M j
w : Word M
m₁ : M j
hw : { fst := j, snd := m₁ } ∉ List.tail w.toList
hm1 : ¬m₁ = 1
⊢ (¬∃ (h : ¬w.toList = []), (List.head w.toList h).fst = j) →
    (m₁ = m₂ * 1 ↔
      (∃ m', List.head? w.toList = some { fst := j, snd := m' } ∧ m₁ = m₂ * m') ∨
        ¬Option.map Sigma.fst (List.head? w.toList) = some j ∧ m₁ = m₂)

Next tactic:
cases w.toList
theorem mem_smul_iff {i j : ι} {m₁ : M i} {m₂ : M j} {w : Word M} :
    ⟨_, m₁⟩ ∈ (of m₂ • w).toList ↔
      (¬i = j ∧ ⟨i, m₁⟩ ∈ w.toList)
      ∨ (m₁ ≠ 1 ∧ ∃ (hij : i = j),(⟨i, m₁⟩ ∈ w.toList.tail) ∨
        (∃ m', ⟨j, m'⟩ ∈ w.toList.head? ∧ m₁ = hij ▸ (m₂ * m')) ∨
        (w.fstIdx ≠ some j ∧ m₁ = hij ▸ m₂)) := by
  rw [of_smul_def, mem_rcons_iff, mem_equivPair_tail_iff, equivPair_head, or_assoc]
  by_cases hij : i = j
  · subst i
    simp only [not_true, ne_eq, false_and, exists_prop, true_and, false_or]
    by_cases hw : ⟨j, m₁⟩ ∈ w.toList.tail
    · simp [hw, show m₁ ≠ 1 from w.ne_one _ (List.mem_of_mem_tail hw)]
    · simp only [hw, false_or, Option.mem_def, ne_eq, and_congr_right_iff]
      intro hm1
      split_ifs with h
      · rcases h with ⟨hnil, rfl⟩
        simp only [List.head?_eq_head _ hnil, Option.some.injEq, ne_eq]
        constructor
        · rintro rfl
          exact Or.inl ⟨_, rfl, rfl⟩
        · rintro (⟨_, h, rfl⟩ | hm')
          · simp [Sigma.ext_iff] at h
            subst h
            rfl
          · simp only [fstIdx, Option.map_eq_some', Sigma.exists,
              exists_and_right, exists_eq_right, not_exists, ne_eq] at hm'
            exact (hm'.1 (w.toList.head hnil).2 (by rw [List.head?_eq_head])).elim
      · revert h
        rw [fstIdx]
        cases w.toList
        · 

Proof state:
case neg.nil
ι : Type u_1
M : ι → Type u_2
inst✝³ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝² : Monoid N
inst✝¹ : (i : ι) → DecidableEq (M i)
inst✝ : DecidableEq ι
j : ι
m₂ : M j
w : Word M
m₁ : M j
hw : { fst := j, snd := m₁ } ∉ List.tail w.toList
hm1 : ¬m₁ = 1
⊢ (¬∃ (h : ¬[] = []), (List.head [] h).fst = j) →
    (m₁ = m₂ * 1 ↔
      (∃ m', List.head? [] = some { fst := j, snd := m' } ∧ m₁ = m₂ * m') ∨
        ¬Option.map Sigma.fst (List.head? []) = some j ∧ m₁ = m₂)

Next tactic:
simp
theorem mem_smul_iff {i j : ι} {m₁ : M i} {m₂ : M j} {w : Word M} :
    ⟨_, m₁⟩ ∈ (of m₂ • w).toList ↔
      (¬i = j ∧ ⟨i, m₁⟩ ∈ w.toList)
      ∨ (m₁ ≠ 1 ∧ ∃ (hij : i = j),(⟨i, m₁⟩ ∈ w.toList.tail) ∨
        (∃ m', ⟨j, m'⟩ ∈ w.toList.head? ∧ m₁ = hij ▸ (m₂ * m')) ∨
        (w.fstIdx ≠ some j ∧ m₁ = hij ▸ m₂)) := by
  rw [of_smul_def, mem_rcons_iff, mem_equivPair_tail_iff, equivPair_head, or_assoc]
  by_cases hij : i = j
  · subst i
    simp only [not_true, ne_eq, false_and, exists_prop, true_and, false_or]
    by_cases hw : ⟨j, m₁⟩ ∈ w.toList.tail
    · simp [hw, show m₁ ≠ 1 from w.ne_one _ (List.mem_of_mem_tail hw)]
    · simp only [hw, false_or, Option.mem_def, ne_eq, and_congr_right_iff]
      intro hm1
      split_ifs with h
      · rcases h with ⟨hnil, rfl⟩
        simp only [List.head?_eq_head _ hnil, Option.some.injEq, ne_eq]
        constructor
        · rintro rfl
          exact Or.inl ⟨_, rfl, rfl⟩
        · rintro (⟨_, h, rfl⟩ | hm')
          · simp [Sigma.ext_iff] at h
            subst h
            rfl
          · simp only [fstIdx, Option.map_eq_some', Sigma.exists,
              exists_and_right, exists_eq_right, not_exists, ne_eq] at hm'
            exact (hm'.1 (w.toList.head hnil).2 (by rw [List.head?_eq_head])).elim
      · revert h
        rw [fstIdx]
        cases w.toList
        · simp
        · 

Proof state:
case neg.cons
ι : Type u_1
M : ι → Type u_2
inst✝³ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝² : Monoid N
inst✝¹ : (i : ι) → DecidableEq (M i)
inst✝ : DecidableEq ι
j : ι
m₂ : M j
w : Word M
m₁ : M j
hw : { fst := j, snd := m₁ } ∉ List.tail w.toList
hm1 : ¬m₁ = 1
head✝ : (i : ι) × M i
tail✝ : List ((i : ι) × M i)
⊢ (¬∃ (h : ¬head✝ :: tail✝ = []), (List.head (head✝ :: tail✝) h).fst = j) →
    (m₁ = m₂ * 1 ↔
      (∃ m', List.head? (head✝ :: tail✝) = some { fst := j, snd := m' } ∧ m₁ = m₂ * m') ∨
        ¬Option.map Sigma.fst (List.head? (head✝ :: tail✝)) = some j ∧ m₁ = m₂)

Next tactic:
simp (config := {contextual := true}) [Sigma.ext_iff]
theorem mem_smul_iff {i j : ι} {m₁ : M i} {m₂ : M j} {w : Word M} :
    ⟨_, m₁⟩ ∈ (of m₂ • w).toList ↔
      (¬i = j ∧ ⟨i, m₁⟩ ∈ w.toList)
      ∨ (m₁ ≠ 1 ∧ ∃ (hij : i = j),(⟨i, m₁⟩ ∈ w.toList.tail) ∨
        (∃ m', ⟨j, m'⟩ ∈ w.toList.head? ∧ m₁ = hij ▸ (m₂ * m')) ∨
        (w.fstIdx ≠ some j ∧ m₁ = hij ▸ m₂)) := by
  rw [of_smul_def, mem_rcons_iff, mem_equivPair_tail_iff, equivPair_head, or_assoc]
  by_cases hij : i = j
  · subst i
    simp only [not_true, ne_eq, false_and, exists_prop, true_and, false_or]
    by_cases hw : ⟨j, m₁⟩ ∈ w.toList.tail
    · simp [hw, show m₁ ≠ 1 from w.ne_one _ (List.mem_of_mem_tail hw)]
    · simp only [hw, false_or, Option.mem_def, ne_eq, and_congr_right_iff]
      intro hm1
      split_ifs with h
      · rcases h with ⟨hnil, rfl⟩
        simp only [List.head?_eq_head _ hnil, Option.some.injEq, ne_eq]
        constructor
        · rintro rfl
          exact Or.inl ⟨_, rfl, rfl⟩
        · rintro (⟨_, h, rfl⟩ | hm')
          · simp [Sigma.ext_iff] at h
            subst h
            rfl
          · simp only [fstIdx, Option.map_eq_some', Sigma.exists,
              exists_and_right, exists_eq_right, not_exists, ne_eq] at hm'
            exact (hm'.1 (w.toList.head hnil).2 (by rw [List.head?_eq_head])).elim
      · revert h
        rw [fstIdx]
        cases w.toList
        · simp
        · simp (config := {contextual := true}) [Sigma.ext_iff]
  · 

Proof state:
case neg
ι : Type u_1
M : ι → Type u_2
inst✝³ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝² : Monoid N
inst✝¹ : (i : ι) → DecidableEq (M i)
inst✝ : DecidableEq ι
i j : ι
m₁ : M i
m₂ : M j
w : Word M
hij : ¬i = j
⊢ ({ fst := i, snd := m₁ } ∈ List.tail w.toList ∨
      (i ≠ j ∧ ∃ (h : w.toList ≠ []), List.head w.toList h = { fst := i, snd := m₁ }) ∨
        m₁ ≠ 1 ∧
          ∃ (h : j = i),
            m₁ =
              h ▸
                (let src := (equivPair j) w;
                  {
                    head :=
                      m₂ *
                        if h : ∃ (h : w.toList ≠ []), (List.head w.toList h).fst = j then
                          (_ : (List.head w.toList (_ : w.toList ≠ [])).fst = j) ▸
                            (List.head w.toList (_ : w.toList ≠ [])).snd
                        else 1,
                    tail := src.tail, fstIdx_ne := (_ : fstIdx src.tail ≠ some j) }).head) ↔
    ¬i = j ∧ { fst := i, snd := m₁ } ∈ w.toList ∨
      m₁ ≠ 1 ∧
        ∃ (hij : i = j),
          { fst := i, snd := m₁ } ∈ List.tail w.toList ∨
            (∃ m', { fst := j, snd := m' } ∈ List.head? w.toList ∧ m₁ = (_ : j = i) ▸ (m₂ * m')) ∨
              fstIdx w ≠ some j ∧ m₁ = (_ : j = i) ▸ m₂

Next tactic:
rcases w with ⟨_ | _, _, _⟩
theorem mem_smul_iff_of_ne {i j : ι} (hij : i ≠ j) {m₁ : M i} {m₂ : M j} {w : Word M} :
    ⟨_, m₁⟩ ∈ (of m₂ • w).toList ↔ ⟨i, m₁⟩ ∈ w.toList := by
  

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝³ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝² : Monoid N
inst✝¹ : (i : ι) → DecidableEq (M i)
inst✝ : DecidableEq ι
i j : ι
hij : i ≠ j
m₁ : M i
m₂ : M j
w : Word M
⊢ { fst := i, snd := m₁ } ∈ (of m₂ • w).toList ↔ { fst := i, snd := m₁ } ∈ w.toList

Next tactic:
simp [mem_smul_iff, *]
theorem cons_eq_smul {i} {m : M i} {ls h1 h2} :
    cons m ls h1 h2 = of m • ls := by
  

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝³ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝² : Monoid N
inst✝¹ : (i : ι) → DecidableEq (M i)
inst✝ : DecidableEq ι
i : ι
m : M i
ls : Word M
h1 : fstIdx ls ≠ some i
h2 : m ≠ 1
⊢ cons m ls h1 h2 = of m • ls

Next tactic:
rw [of_smul_def, equivPair_eq_of_fstIdx_ne _]
theorem cons_eq_smul {i} {m : M i} {ls h1 h2} :
    cons m ls h1 h2 = of m • ls := by
  rw [of_smul_def, equivPair_eq_of_fstIdx_ne _]
  · 

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝³ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝² : Monoid N
inst✝¹ : (i : ι) → DecidableEq (M i)
inst✝ : DecidableEq ι
i : ι
m : M i
ls : Word M
h1 : fstIdx ls ≠ some i
h2 : m ≠ 1
⊢ cons m ls h1 h2 =
    rcons
      (let src := { head := 1, tail := ls, fstIdx_ne := ?m.652573 };
      { head := m * { head := 1, tail := ls, fstIdx_ne := ?m.652573 }.head, tail := src.tail,
        fstIdx_ne := (_ : fstIdx src.tail ≠ some i) })

Next tactic:
simp [cons, rcons, h2]
theorem cons_eq_smul {i} {m : M i} {ls h1 h2} :
    cons m ls h1 h2 = of m • ls := by
  rw [of_smul_def, equivPair_eq_of_fstIdx_ne _]
  · simp [cons, rcons, h2]
  · 

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝³ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝² : Monoid N
inst✝¹ : (i : ι) → DecidableEq (M i)
inst✝ : DecidableEq ι
i : ι
m : M i
ls : Word M
h1 : fstIdx ls ≠ some i
h2 : m ≠ 1
⊢ fstIdx ls ≠ some i

Next tactic:
exact h1
theorem rcons_eq_smul {i} (p : Pair M i) :
    rcons p = of p.head • p.tail := by
  

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝³ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝² : Monoid N
inst✝¹ : (i : ι) → DecidableEq (M i)
inst✝ : DecidableEq ι
i : ι
p : Pair M i
⊢ rcons p = of p.head • p.tail

Next tactic:
simp [of_smul_def]
@[simp]
theorem equivPair_head_smul_equivPair_tail {i : ι} (w : Word M) :
    of (equivPair i w).head • (equivPair i w).tail = w := by
  

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝³ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝² : Monoid N
inst✝¹ : (i : ι) → DecidableEq (M i)
inst✝ : DecidableEq ι
i : ι
w : Word M
⊢ of ((equivPair i) w).head • ((equivPair i) w).tail = w

Next tactic:
rw [← rcons_eq_smul, ← equivPair_symm, Equiv.symm_apply_apply]
theorem smul_induction {C : Word M → Prop} (h_empty : C empty)
    (h_smul : ∀ (i) (m : M i) (w), C w → C (of m • w)) (w : Word M) : C w := by
  

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝³ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝² : Monoid N
inst✝¹ : (i : ι) → DecidableEq (M i)
inst✝ : DecidableEq ι
C : Word M → Prop
h_empty : C empty
h_smul : ∀ (i : ι) (m : M i) (w : Word M), C w → C (of m • w)
w : Word M
⊢ C w

Next tactic:
induction w using consRecOn with
  | h_empty => exact h_empty
  | h_cons _ _ _ _ _ ih =>
    rw [cons_eq_smul]
    exact h_smul _ _ _ ih
theorem smul_induction {C : Word M → Prop} (h_empty : C empty)
    (h_smul : ∀ (i) (m : M i) (w), C w → C (of m • w)) (w : Word M) : C w := by
  induction w using consRecOn with
  

Proof state:
case h_empty
ι : Type u_1
M : ι → Type u_2
inst✝³ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝² : Monoid N
inst✝¹ : (i : ι) → DecidableEq (M i)
inst✝ : DecidableEq ι
C : Word M → Prop
h_empty : C empty
h_smul : ∀ (i : ι) (m : M i) (w : Word M), C w → C (of m • w)
⊢ C empty

Next tactic:
| h_empty => exact h_empty
theorem smul_induction {C : Word M → Prop} (h_empty : C empty)
    (h_smul : ∀ (i) (m : M i) (w), C w → C (of m • w)) (w : Word M) : C w := by
  induction w using consRecOn with
  | h_empty => 

Proof state:
case h_empty
ι : Type u_1
M : ι → Type u_2
inst✝³ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝² : Monoid N
inst✝¹ : (i : ι) → DecidableEq (M i)
inst✝ : DecidableEq ι
C : Word M → Prop
h_empty : C empty
h_smul : ∀ (i : ι) (m : M i) (w : Word M), C w → C (of m • w)
⊢ C empty

Next tactic:
exact h_empty
theorem smul_induction {C : Word M → Prop} (h_empty : C empty)
    (h_smul : ∀ (i) (m : M i) (w), C w → C (of m • w)) (w : Word M) : C w := by
  induction w using consRecOn with
  | h_empty => exact h_empty
  

Proof state:
case h_cons
ι : Type u_1
M : ι → Type u_2
inst✝³ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝² : Monoid N
inst✝¹ : (i : ι) → DecidableEq (M i)
inst✝ : DecidableEq ι
C : Word M → Prop
h_empty : C empty
h_smul : ∀ (i : ι) (m : M i) (w : Word M), C w → C (of m • w)
i✝ : ι
m✝ : M i✝
w✝ : Word M
h1✝ : fstIdx w✝ ≠ some i✝
h2✝ : m✝ ≠ 1
ih : C w✝
⊢ C (cons m✝ w✝ h1✝ h2✝)

Next tactic:
| h_cons _ _ _ _ _ ih =>
    rw [cons_eq_smul]
    exact h_smul _ _ _ ih
theorem smul_induction {C : Word M → Prop} (h_empty : C empty)
    (h_smul : ∀ (i) (m : M i) (w), C w → C (of m • w)) (w : Word M) : C w := by
  induction w using consRecOn with
  | h_empty => exact h_empty
  | h_cons _ _ _ _ _ ih =>
    

Proof state:
case h_cons
ι : Type u_1
M : ι → Type u_2
inst✝³ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝² : Monoid N
inst✝¹ : (i : ι) → DecidableEq (M i)
inst✝ : DecidableEq ι
C : Word M → Prop
h_empty : C empty
h_smul : ∀ (i : ι) (m : M i) (w : Word M), C w → C (of m • w)
i✝ : ι
m✝ : M i✝
w✝ : Word M
h1✝ : fstIdx w✝ ≠ some i✝
h2✝ : m✝ ≠ 1
ih : C w✝
⊢ C (cons m✝ w✝ h1✝ h2✝)

Next tactic:
rw [cons_eq_smul]
theorem smul_induction {C : Word M → Prop} (h_empty : C empty)
    (h_smul : ∀ (i) (m : M i) (w), C w → C (of m • w)) (w : Word M) : C w := by
  induction w using consRecOn with
  | h_empty => exact h_empty
  | h_cons _ _ _ _ _ ih =>
    rw [cons_eq_smul]
    

Proof state:
case h_cons
ι : Type u_1
M : ι → Type u_2
inst✝³ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝² : Monoid N
inst✝¹ : (i : ι) → DecidableEq (M i)
inst✝ : DecidableEq ι
C : Word M → Prop
h_empty : C empty
h_smul : ∀ (i : ι) (m : M i) (w : Word M), C w → C (of m • w)
i✝ : ι
m✝ : M i✝
w✝ : Word M
h1✝ : fstIdx w✝ ≠ some i✝
h2✝ : m✝ ≠ 1
ih : C w✝
⊢ C (of m✝ • w✝)

Next tactic:
exact h_smul _ _ _ ih
@[simp]
theorem prod_smul (m) : ∀ w : Word M, prod (m • w) = m * prod w := by
  

Proof state:
ι : Type u_1
M : ι → Type u_2
inst✝³ : (i : ι) → Monoid (M i)
N : Type u_3
inst✝² : Monoid N
inst✝¹ : (i : ι) → DecidableEq (M i)
inst✝ : DecidableEq ι
m : CoprodI M
⊢ ∀ (w : Word M), prod (m • w) = m * prod w

Next tactic:
induction m using CoprodI.induction_on with
  | h_one =>
    intro
    rw [one_smul, one_mul]
  | h_of _ =>
    intros
    rw [of_smul_def, prod_rcons, of.map_mul, mul_assoc, ← prod_rcons, ← equivPair_symm,
      Equiv.symm_apply_apply]
  | h_mul x y hx hy =>
    intro w
    rw [mul_smul, hx, hy, mul_assoc]