-- Mathlib/GroupTheory/CoprodI.lean
theorem of_word (w : Word M) (h : w ≠ empty) : ∃ (i j : _) (w' : NeWord M i j), w'.toWord = w

Proof state:
case intro.intro.intro
ι : Type u_1
M : ι → Type u_2
inst✝ : (i : ι) → Monoid (M i)
w✝ : Word M
h✝ : w✝ ≠ empty
i j : ι
w : NeWord M i j
h : w.toWord.toList = w✝.toList
⊢ ∃ i j w', w'.toWord = w✝

Tactic:
refine ⟨i, j, w, ?_⟩

Result:
case intro.intro.intro
ι : Type u_1
M : ι → Type u_2
inst✝ : (i : ι) → Monoid (M i)
w✝ : Word M
h✝ : w✝ ≠ empty
i j : ι
w : NeWord M i j
h : w.toWord.toList = w✝.toList
⊢ w.toWord = w✝

Proof state:
case mk.cons.cons.intro.intro.intro
ι : Type u_1
M : ι → Type u_2
inst✝ : (i : ι) → Monoid (M i)
x y : (i : ι) × M i
l : List ((i : ι) × M i)
hnot1✝ : ∀ l_1 ∈ x :: y :: l, l_1.snd ≠ 1
hnot1 : x.snd ≠ 1 ∧ ∀ x ∈ y :: l, x.snd ≠ 1
hchain✝ : List.Chain' (fun l l' => l.fst ≠ l'.fst) (x :: y :: l)
hchain : x.fst ≠ y.fst ∧ List.Chain' (fun l l' => l.fst ≠ l'.fst) (y :: l)
h : { toList := x :: y :: l, ne_one := hnot1✝, chain_ne := hchain✝ } ≠ empty
i j : ι
w' : NeWord M i j
hw' : w'.toList = y :: l
⊢ ∃ i j w', w'.toWord.toList = { toList := x :: y :: l, ne_one := hnot1✝, chain_ne := hchain✝ }.toList

Tactic:
obtain rfl : y = ⟨i, w'.head⟩ := by simpa [hw'] using w'.toList_head?

Result:
case mk.cons.cons.intro.intro.intro
ι : Type u_1
M : ι → Type u_2
inst✝ : (i : ι) → Monoid (M i)
x : (i : ι) × M i
l : List ((i : ι) × M i)
i j : ι
w' : NeWord M i j
hnot1✝ : ∀ l_1 ∈ x :: ⟨i, w'.head⟩ :: l, l_1.snd ≠ 1
hnot1 : x.snd ≠ 1 ∧ ∀ x ∈ ⟨i, w'.head⟩ :: l, x.snd ≠ 1
hchain✝ : List.Chain' (fun l l' => l.fst ≠ l'.fst) (x :: ⟨i, w'.head⟩ :: l)
hchain : x.fst ≠ ⟨i, w'.head⟩.fst ∧ List.Chain' (fun l l' => l.fst ≠ l'.fst) (⟨i, w'.head⟩ :: l)
h : { toList := x :: ⟨i, w'.head⟩ :: l, ne_one := hnot1✝, chain_ne := hchain✝ } ≠ empty
hw' : w'.toList = ⟨i, w'.head⟩ :: l
⊢ ∃ i_1 j_1 w'_1,
    w'_1.toWord.toList = { toList := x :: ⟨i, w'.head⟩ :: l, ne_one := hnot1✝, chain_ne := hchain✝ }.toList

Proof state:
case mk.cons.nil
ι : Type u_1
M : ι → Type u_2
inst✝ : (i : ι) → Monoid (M i)
x : (i : ι) × M i
hi :
  ∀ (hnot1 : ∀ l ∈ [], l.snd ≠ 1) (hchain : List.Chain' (fun l l' => l.fst ≠ l'.fst) []),
    { toList := [], ne_one := hnot1, chain_ne := hchain } ≠ empty →
      ∃ i j w', w'.toWord.toList = { toList := [], ne_one := hnot1, chain_ne := hchain }.toList
hnot1✝ : ∀ l ∈ [x], l.snd ≠ 1
hnot1 : x.snd ≠ 1 ∧ ∀ x ∈ [], x.snd ≠ 1
hchain : List.Chain' (fun l l' => l.fst ≠ l'.fst) [x]
h : { toList := [x], ne_one := hnot1✝, chain_ne := hchain } ≠ empty
⊢ (singleton x.snd ⋯).toWord.toList = { toList := [x], ne_one := hnot1✝, chain_ne := hchain }.toList

Tactic:
simp [toWord]

Result:
no goals

Proof state:
case mk.nil
ι : Type u_1
M : ι → Type u_2
inst✝ : (i : ι) → Monoid (M i)
hnot1 : ∀ l ∈ [], l.snd ≠ 1
hchain : List.Chain' (fun l l' => l.fst ≠ l'.fst) []
h : { toList := [], ne_one := hnot1, chain_ne := hchain } ≠ empty
⊢ ∃ i j w', w'.toWord.toList = { toList := [], ne_one := hnot1, chain_ne := hchain }.toList

Tactic:
contradiction

Result:
no goals

Proof state:
case intro.intro.intro
ι : Type u_1
M : ι → Type u_2
inst✝ : (i : ι) → Monoid (M i)
w✝ : Word M
h✝ : w✝ ≠ empty
i j : ι
w : NeWord M i j
h : w.toWord.toList = w✝.toList
⊢ w.toWord = w✝

Tactic:
ext

Result:
case intro.intro.intro.toList.h.a
ι : Type u_1
M : ι → Type u_2
inst✝ : (i : ι) → Monoid (M i)
w✝ : Word M
h✝ : w✝ ≠ empty
i j : ι
w : NeWord M i j
h : w.toWord.toList = w✝.toList
i✝ : ℕ
a✝ : (i : ι) × M i
⊢ a✝ ∈ w.toWord.toList[i✝]? ↔ a✝ ∈ w✝.toList[i✝]?

Proof state:
case mk.cons.cons
ι : Type u_1
M : ι → Type u_2
inst✝ : (i : ι) → Monoid (M i)
x y : (i : ι) × M i
l : List ((i : ι) × M i)
hnot1✝ : ∀ l_1 ∈ x :: y :: l, l_1.snd ≠ 1
hnot1 : x.snd ≠ 1 ∧ ∀ x ∈ y :: l, x.snd ≠ 1
hchain✝ : List.Chain' (fun l l' => l.fst ≠ l'.fst) (x :: y :: l)
hchain : x.fst ≠ y.fst ∧ List.Chain' (fun l l' => l.fst ≠ l'.fst) (y :: l)
h : { toList := x :: y :: l, ne_one := hnot1✝, chain_ne := hchain✝ } ≠ empty
hi : ∃ i j w', w'.toWord.toList = { toList := y :: l, ne_one := ⋯, chain_ne := ⋯ }.toList
⊢ ∃ i j w', w'.toWord.toList = { toList := x :: y :: l, ne_one := hnot1✝, chain_ne := hchain✝ }.toList

Tactic:
obtain ⟨i, j, w', hw' : w'.toList = y::l⟩ := hi

Result:
case mk.cons.cons.intro.intro.intro
ι : Type u_1
M : ι → Type u_2
inst✝ : (i : ι) → Monoid (M i)
x y : (i : ι) × M i
l : List ((i : ι) × M i)
hnot1✝ : ∀ l_1 ∈ x :: y :: l, l_1.snd ≠ 1
hnot1 : x.snd ≠ 1 ∧ ∀ x ∈ y :: l, x.snd ≠ 1
hchain✝ : List.Chain' (fun l l' => l.fst ≠ l'.fst) (x :: y :: l)
hchain : x.fst ≠ y.fst ∧ List.Chain' (fun l l' => l.fst ≠ l'.fst) (y :: l)
h : { toList := x :: y :: l, ne_one := hnot1✝, chain_ne := hchain✝ } ≠ empty
i j : ι
w' : NeWord M i j
hw' : w'.toList = y :: l
⊢ ∃ i j w', w'.toWord.toList = { toList := x :: y :: l, ne_one := hnot1✝, chain_ne := hchain✝ }.toList