l3lab/ntp-mathlib huggingface dataset:
theorem listDecode_encode_list (l : List (L.Term α)) :
    listDecode (l.bind listEncode) = l.map Option.some := by
  suffices h : ∀ (t : L.Term α) (l : List (Sum α (Σi, L.Functions i))),
      listDecode (t.listEncode ++ l) = some t::listDecode l
  · induction' l with t l lih
    · rfl
    · rw [cons_bind, h t (l.bind listEncode), lih, List.map]
  · intro t
    induction' t with a n f ts ih <;> intro l
    · rw [listEncode, singleton_append, listDecode]
    · rw [listEncode, cons_append, listDecode]
      have h : listDecode (((finRange n).bind fun i : Fin n => (ts i).listEncode) ++ l) =
          (finRange n).map (Option.some ∘ ts) ++ listDecode l := by
        induction' finRange n with i l' l'ih
        · rfl
        · rw [cons_bind, List.append_assoc, ih, map_cons, l'ih, cons_append, Function.comp]
      have h' : ∀ i : Fin n,
          (listDecode (((finRange n).bind fun i : Fin n => (ts i).listEncode) ++ l)).get? ↑i =
            some (some (ts i)) := by
        

Proof state:
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l✝ : List (Term L α)
n : ℕ
f : Functions L n
ts : Fin n → Term L α
ih :
  ∀ (a : Fin n) (l : List (α ⊕ (i : ℕ) × Functions L i)),
    listDecode (listEncode (ts a) ++ l) = some (ts a) :: listDecode l
l : List (α ⊕ (i : ℕ) × Functions L i)
h :
  listDecode ((List.bind (finRange n) fun i => listEncode (ts i)) ++ l) =
    List.map (some ∘ ts) (finRange n) ++ listDecode l
⊢ ∀ (i : Fin n), get? (listDecode ((List.bind (finRange n) fun i => listEncode (ts i)) ++ l)) ↑i = some (some (ts i))

Next tactic:
intro i
theorem listDecode_encode_list (l : List (L.Term α)) :
    listDecode (l.bind listEncode) = l.map Option.some := by
  suffices h : ∀ (t : L.Term α) (l : List (Sum α (Σi, L.Functions i))),
      listDecode (t.listEncode ++ l) = some t::listDecode l
  · induction' l with t l lih
    · rfl
    · rw [cons_bind, h t (l.bind listEncode), lih, List.map]
  · intro t
    induction' t with a n f ts ih <;> intro l
    · rw [listEncode, singleton_append, listDecode]
    · rw [listEncode, cons_append, listDecode]
      have h : listDecode (((finRange n).bind fun i : Fin n => (ts i).listEncode) ++ l) =
          (finRange n).map (Option.some ∘ ts) ++ listDecode l := by
        induction' finRange n with i l' l'ih
        · rfl
        · rw [cons_bind, List.append_assoc, ih, map_cons, l'ih, cons_append, Function.comp]
      have h' : ∀ i : Fin n,
          (listDecode (((finRange n).bind fun i : Fin n => (ts i).listEncode) ++ l)).get? ↑i =
            some (some (ts i)) := by
        intro i
        

Proof state:
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l✝ : List (Term L α)
n : ℕ
f : Functions L n
ts : Fin n → Term L α
ih :
  ∀ (a : Fin n) (l : List (α ⊕ (i : ℕ) × Functions L i)),
    listDecode (listEncode (ts a) ++ l) = some (ts a) :: listDecode l
l : List (α ⊕ (i : ℕ) × Functions L i)
h :
  listDecode ((List.bind (finRange n) fun i => listEncode (ts i)) ++ l) =
    List.map (some ∘ ts) (finRange n) ++ listDecode l
i : Fin n
⊢ get? (listDecode ((List.bind (finRange n) fun i => listEncode (ts i)) ++ l)) ↑i = some (some (ts i))

Next tactic:
rw [h, get?_append, get?_map]
theorem listDecode_encode_list (l : List (L.Term α)) :
    listDecode (l.bind listEncode) = l.map Option.some := by
  suffices h : ∀ (t : L.Term α) (l : List (Sum α (Σi, L.Functions i))),
      listDecode (t.listEncode ++ l) = some t::listDecode l
  · induction' l with t l lih
    · rfl
    · rw [cons_bind, h t (l.bind listEncode), lih, List.map]
  · intro t
    induction' t with a n f ts ih <;> intro l
    · rw [listEncode, singleton_append, listDecode]
    · rw [listEncode, cons_append, listDecode]
      have h : listDecode (((finRange n).bind fun i : Fin n => (ts i).listEncode) ++ l) =
          (finRange n).map (Option.some ∘ ts) ++ listDecode l := by
        induction' finRange n with i l' l'ih
        · rfl
        · rw [cons_bind, List.append_assoc, ih, map_cons, l'ih, cons_append, Function.comp]
      have h' : ∀ i : Fin n,
          (listDecode (((finRange n).bind fun i : Fin n => (ts i).listEncode) ++ l)).get? ↑i =
            some (some (ts i)) := by
        intro i
        rw [h, get?_append, get?_map]
        · 

Proof state:
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l✝ : List (Term L α)
n : ℕ
f : Functions L n
ts : Fin n → Term L α
ih :
  ∀ (a : Fin n) (l : List (α ⊕ (i : ℕ) × Functions L i)),
    listDecode (listEncode (ts a) ++ l) = some (ts a) :: listDecode l
l : List (α ⊕ (i : ℕ) × Functions L i)
h :
  listDecode ((List.bind (finRange n) fun i => listEncode (ts i)) ++ l) =
    List.map (some ∘ ts) (finRange n) ++ listDecode l
i : Fin n
⊢ Option.map (some ∘ ts) (get? (finRange n) ↑i) = some (some (ts i))

Next tactic:
simp only [Option.map_eq_some', Function.comp_apply, get?_eq_some]
theorem listDecode_encode_list (l : List (L.Term α)) :
    listDecode (l.bind listEncode) = l.map Option.some := by
  suffices h : ∀ (t : L.Term α) (l : List (Sum α (Σi, L.Functions i))),
      listDecode (t.listEncode ++ l) = some t::listDecode l
  · induction' l with t l lih
    · rfl
    · rw [cons_bind, h t (l.bind listEncode), lih, List.map]
  · intro t
    induction' t with a n f ts ih <;> intro l
    · rw [listEncode, singleton_append, listDecode]
    · rw [listEncode, cons_append, listDecode]
      have h : listDecode (((finRange n).bind fun i : Fin n => (ts i).listEncode) ++ l) =
          (finRange n).map (Option.some ∘ ts) ++ listDecode l := by
        induction' finRange n with i l' l'ih
        · rfl
        · rw [cons_bind, List.append_assoc, ih, map_cons, l'ih, cons_append, Function.comp]
      have h' : ∀ i : Fin n,
          (listDecode (((finRange n).bind fun i : Fin n => (ts i).listEncode) ++ l)).get? ↑i =
            some (some (ts i)) := by
        intro i
        rw [h, get?_append, get?_map]
        · simp only [Option.map_eq_some', Function.comp_apply, get?_eq_some]
          

Proof state:
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l✝ : List (Term L α)
n : ℕ
f : Functions L n
ts : Fin n → Term L α
ih :
  ∀ (a : Fin n) (l : List (α ⊕ (i : ℕ) × Functions L i)),
    listDecode (listEncode (ts a) ++ l) = some (ts a) :: listDecode l
l : List (α ⊕ (i : ℕ) × Functions L i)
h :
  listDecode ((List.bind (finRange n) fun i => listEncode (ts i)) ++ l) =
    List.map (some ∘ ts) (finRange n) ++ listDecode l
i : Fin n
⊢ ∃ a,
    (∃ (h : ↑i < length (finRange n)), List.get (finRange n) { val := ↑i, isLt := h } = a) ∧ some (ts a) = some (ts i)

Next tactic:
refine' ⟨i, ⟨lt_of_lt_of_le i.2 (ge_of_eq (length_finRange _)), _⟩, rfl⟩
theorem listDecode_encode_list (l : List (L.Term α)) :
    listDecode (l.bind listEncode) = l.map Option.some := by
  suffices h : ∀ (t : L.Term α) (l : List (Sum α (Σi, L.Functions i))),
      listDecode (t.listEncode ++ l) = some t::listDecode l
  · induction' l with t l lih
    · rfl
    · rw [cons_bind, h t (l.bind listEncode), lih, List.map]
  · intro t
    induction' t with a n f ts ih <;> intro l
    · rw [listEncode, singleton_append, listDecode]
    · rw [listEncode, cons_append, listDecode]
      have h : listDecode (((finRange n).bind fun i : Fin n => (ts i).listEncode) ++ l) =
          (finRange n).map (Option.some ∘ ts) ++ listDecode l := by
        induction' finRange n with i l' l'ih
        · rfl
        · rw [cons_bind, List.append_assoc, ih, map_cons, l'ih, cons_append, Function.comp]
      have h' : ∀ i : Fin n,
          (listDecode (((finRange n).bind fun i : Fin n => (ts i).listEncode) ++ l)).get? ↑i =
            some (some (ts i)) := by
        intro i
        rw [h, get?_append, get?_map]
        · simp only [Option.map_eq_some', Function.comp_apply, get?_eq_some]
          refine' ⟨i, ⟨lt_of_lt_of_le i.2 (ge_of_eq (length_finRange _)), _⟩, rfl⟩
          

Proof state:
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l✝ : List (Term L α)
n : ℕ
f : Functions L n
ts : Fin n → Term L α
ih :
  ∀ (a : Fin n) (l : List (α ⊕ (i : ℕ) × Functions L i)),
    listDecode (listEncode (ts a) ++ l) = some (ts a) :: listDecode l
l : List (α ⊕ (i : ℕ) × Functions L i)
h :
  listDecode ((List.bind (finRange n) fun i => listEncode (ts i)) ++ l) =
    List.map (some ∘ ts) (finRange n) ++ listDecode l
i : Fin n
⊢ List.get (finRange n) { val := ↑i, isLt := (_ : ↑i < length (finRange n)) } = i

Next tactic:
rw [get_finRange, Fin.eta]
theorem listDecode_encode_list (l : List (L.Term α)) :
    listDecode (l.bind listEncode) = l.map Option.some := by
  suffices h : ∀ (t : L.Term α) (l : List (Sum α (Σi, L.Functions i))),
      listDecode (t.listEncode ++ l) = some t::listDecode l
  · induction' l with t l lih
    · rfl
    · rw [cons_bind, h t (l.bind listEncode), lih, List.map]
  · intro t
    induction' t with a n f ts ih <;> intro l
    · rw [listEncode, singleton_append, listDecode]
    · rw [listEncode, cons_append, listDecode]
      have h : listDecode (((finRange n).bind fun i : Fin n => (ts i).listEncode) ++ l) =
          (finRange n).map (Option.some ∘ ts) ++ listDecode l := by
        induction' finRange n with i l' l'ih
        · rfl
        · rw [cons_bind, List.append_assoc, ih, map_cons, l'ih, cons_append, Function.comp]
      have h' : ∀ i : Fin n,
          (listDecode (((finRange n).bind fun i : Fin n => (ts i).listEncode) ++ l)).get? ↑i =
            some (some (ts i)) := by
        intro i
        rw [h, get?_append, get?_map]
        · simp only [Option.map_eq_some', Function.comp_apply, get?_eq_some]
          refine' ⟨i, ⟨lt_of_lt_of_le i.2 (ge_of_eq (length_finRange _)), _⟩, rfl⟩
          rw [get_finRange, Fin.eta]
        · 

Proof state:
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l✝ : List (Term L α)
n : ℕ
f : Functions L n
ts : Fin n → Term L α
ih :
  ∀ (a : Fin n) (l : List (α ⊕ (i : ℕ) × Functions L i)),
    listDecode (listEncode (ts a) ++ l) = some (ts a) :: listDecode l
l : List (α ⊕ (i : ℕ) × Functions L i)
h :
  listDecode ((List.bind (finRange n) fun i => listEncode (ts i)) ++ l) =
    List.map (some ∘ ts) (finRange n) ++ listDecode l
i : Fin n
⊢ ↑i < length (List.map (some ∘ ts) (finRange n))

Next tactic:
refine' lt_of_lt_of_le i.2 _
theorem listDecode_encode_list (l : List (L.Term α)) :
    listDecode (l.bind listEncode) = l.map Option.some := by
  suffices h : ∀ (t : L.Term α) (l : List (Sum α (Σi, L.Functions i))),
      listDecode (t.listEncode ++ l) = some t::listDecode l
  · induction' l with t l lih
    · rfl
    · rw [cons_bind, h t (l.bind listEncode), lih, List.map]
  · intro t
    induction' t with a n f ts ih <;> intro l
    · rw [listEncode, singleton_append, listDecode]
    · rw [listEncode, cons_append, listDecode]
      have h : listDecode (((finRange n).bind fun i : Fin n => (ts i).listEncode) ++ l) =
          (finRange n).map (Option.some ∘ ts) ++ listDecode l := by
        induction' finRange n with i l' l'ih
        · rfl
        · rw [cons_bind, List.append_assoc, ih, map_cons, l'ih, cons_append, Function.comp]
      have h' : ∀ i : Fin n,
          (listDecode (((finRange n).bind fun i : Fin n => (ts i).listEncode) ++ l)).get? ↑i =
            some (some (ts i)) := by
        intro i
        rw [h, get?_append, get?_map]
        · simp only [Option.map_eq_some', Function.comp_apply, get?_eq_some]
          refine' ⟨i, ⟨lt_of_lt_of_le i.2 (ge_of_eq (length_finRange _)), _⟩, rfl⟩
          rw [get_finRange, Fin.eta]
        · refine' lt_of_lt_of_le i.2 _
          

Proof state:
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l✝ : List (Term L α)
n : ℕ
f : Functions L n
ts : Fin n → Term L α
ih :
  ∀ (a : Fin n) (l : List (α ⊕ (i : ℕ) × Functions L i)),
    listDecode (listEncode (ts a) ++ l) = some (ts a) :: listDecode l
l : List (α ⊕ (i : ℕ) × Functions L i)
h :
  listDecode ((List.bind (finRange n) fun i => listEncode (ts i)) ++ l) =
    List.map (some ∘ ts) (finRange n) ++ listDecode l
i : Fin n
⊢ n ≤ length (List.map (some ∘ ts) (finRange n))

Next tactic:
simp
theorem listDecode_encode_list (l : List (L.Term α)) :
    listDecode (l.bind listEncode) = l.map Option.some := by
  suffices h : ∀ (t : L.Term α) (l : List (Sum α (Σi, L.Functions i))),
      listDecode (t.listEncode ++ l) = some t::listDecode l
  · induction' l with t l lih
    · rfl
    · rw [cons_bind, h t (l.bind listEncode), lih, List.map]
  · intro t
    induction' t with a n f ts ih <;> intro l
    · rw [listEncode, singleton_append, listDecode]
    · rw [listEncode, cons_append, listDecode]
      have h : listDecode (((finRange n).bind fun i : Fin n => (ts i).listEncode) ++ l) =
          (finRange n).map (Option.some ∘ ts) ++ listDecode l := by
        induction' finRange n with i l' l'ih
        · rfl
        · rw [cons_bind, List.append_assoc, ih, map_cons, l'ih, cons_append, Function.comp]
      have h' : ∀ i : Fin n,
          (listDecode (((finRange n).bind fun i : Fin n => (ts i).listEncode) ++ l)).get? ↑i =
            some (some (ts i)) := by
        intro i
        rw [h, get?_append, get?_map]
        · simp only [Option.map_eq_some', Function.comp_apply, get?_eq_some]
          refine' ⟨i, ⟨lt_of_lt_of_le i.2 (ge_of_eq (length_finRange _)), _⟩, rfl⟩
          rw [get_finRange, Fin.eta]
        · refine' lt_of_lt_of_le i.2 _
          simp
      

Proof state:
case h.func
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l✝ : List (Term L α)
n : ℕ
f : Functions L n
ts : Fin n → Term L α
ih :
  ∀ (a : Fin n) (l : List (α ⊕ (i : ℕ) × Functions L i)),
    listDecode (listEncode (ts a) ++ l) = some (ts a) :: listDecode l
l : List (α ⊕ (i : ℕ) × Functions L i)
h :
  listDecode ((List.bind (finRange n) fun i => listEncode (ts i)) ++ l) =
    List.map (some ∘ ts) (finRange n) ++ listDecode l
h' : ∀ (i : Fin n), get? (listDecode ((List.bind (finRange n) fun i => listEncode (ts i)) ++ l)) ↑i = some (some (ts i))
⊢ (if h :
        ∀ (i : Fin n),
          Option.isSome
              (Option.join (get? (listDecode ((List.bind (finRange n) fun i => listEncode (ts i)) ++ l)) ↑i)) =
            true then
      some
          (func f fun i =>
            Option.get (Option.join (get? (listDecode ((List.bind (finRange n) fun i => listEncode (ts i)) ++ l)) ↑i))
              (_ :
                Option.isSome
                    (Option.join (get? (listDecode ((List.bind (finRange n) fun i => listEncode (ts i)) ++ l)) ↑i)) =
                  true)) ::
        drop n (listDecode ((List.bind (finRange n) fun i => listEncode (ts i)) ++ l))
    else [none]) =
    some (func f ts) :: listDecode l

Next tactic:
refine' (dif_pos fun i => Option.isSome_iff_exists.2 ⟨ts i, _⟩).trans _
theorem listDecode_encode_list (l : List (L.Term α)) :
    listDecode (l.bind listEncode) = l.map Option.some := by
  suffices h : ∀ (t : L.Term α) (l : List (Sum α (Σi, L.Functions i))),
      listDecode (t.listEncode ++ l) = some t::listDecode l
  · induction' l with t l lih
    · rfl
    · rw [cons_bind, h t (l.bind listEncode), lih, List.map]
  · intro t
    induction' t with a n f ts ih <;> intro l
    · rw [listEncode, singleton_append, listDecode]
    · rw [listEncode, cons_append, listDecode]
      have h : listDecode (((finRange n).bind fun i : Fin n => (ts i).listEncode) ++ l) =
          (finRange n).map (Option.some ∘ ts) ++ listDecode l := by
        induction' finRange n with i l' l'ih
        · rfl
        · rw [cons_bind, List.append_assoc, ih, map_cons, l'ih, cons_append, Function.comp]
      have h' : ∀ i : Fin n,
          (listDecode (((finRange n).bind fun i : Fin n => (ts i).listEncode) ++ l)).get? ↑i =
            some (some (ts i)) := by
        intro i
        rw [h, get?_append, get?_map]
        · simp only [Option.map_eq_some', Function.comp_apply, get?_eq_some]
          refine' ⟨i, ⟨lt_of_lt_of_le i.2 (ge_of_eq (length_finRange _)), _⟩, rfl⟩
          rw [get_finRange, Fin.eta]
        · refine' lt_of_lt_of_le i.2 _
          simp
      refine' (dif_pos fun i => Option.isSome_iff_exists.2 ⟨ts i, _⟩).trans _
      · 

Proof state:
case h.func.refine'_1
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l✝ : List (Term L α)
n : ℕ
f : Functions L n
ts : Fin n → Term L α
ih :
  ∀ (a : Fin n) (l : List (α ⊕ (i : ℕ) × Functions L i)),
    listDecode (listEncode (ts a) ++ l) = some (ts a) :: listDecode l
l : List (α ⊕ (i : ℕ) × Functions L i)
h :
  listDecode ((List.bind (finRange n) fun i => listEncode (ts i)) ++ l) =
    List.map (some ∘ ts) (finRange n) ++ listDecode l
h' : ∀ (i : Fin n), get? (listDecode ((List.bind (finRange n) fun i => listEncode (ts i)) ++ l)) ↑i = some (some (ts i))
i : Fin n
⊢ Option.join (get? (listDecode ((List.bind (finRange n) fun i => listEncode (ts i)) ++ l)) ↑i) = some (ts i)

Next tactic:
rw [Option.join_eq_some, h']
theorem listDecode_encode_list (l : List (L.Term α)) :
    listDecode (l.bind listEncode) = l.map Option.some := by
  suffices h : ∀ (t : L.Term α) (l : List (Sum α (Σi, L.Functions i))),
      listDecode (t.listEncode ++ l) = some t::listDecode l
  · induction' l with t l lih
    · rfl
    · rw [cons_bind, h t (l.bind listEncode), lih, List.map]
  · intro t
    induction' t with a n f ts ih <;> intro l
    · rw [listEncode, singleton_append, listDecode]
    · rw [listEncode, cons_append, listDecode]
      have h : listDecode (((finRange n).bind fun i : Fin n => (ts i).listEncode) ++ l) =
          (finRange n).map (Option.some ∘ ts) ++ listDecode l := by
        induction' finRange n with i l' l'ih
        · rfl
        · rw [cons_bind, List.append_assoc, ih, map_cons, l'ih, cons_append, Function.comp]
      have h' : ∀ i : Fin n,
          (listDecode (((finRange n).bind fun i : Fin n => (ts i).listEncode) ++ l)).get? ↑i =
            some (some (ts i)) := by
        intro i
        rw [h, get?_append, get?_map]
        · simp only [Option.map_eq_some', Function.comp_apply, get?_eq_some]
          refine' ⟨i, ⟨lt_of_lt_of_le i.2 (ge_of_eq (length_finRange _)), _⟩, rfl⟩
          rw [get_finRange, Fin.eta]
        · refine' lt_of_lt_of_le i.2 _
          simp
      refine' (dif_pos fun i => Option.isSome_iff_exists.2 ⟨ts i, _⟩).trans _
      · rw [Option.join_eq_some, h']
      

Proof state:
case h.func.refine'_2
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l✝ : List (Term L α)
n : ℕ
f : Functions L n
ts : Fin n → Term L α
ih :
  ∀ (a : Fin n) (l : List (α ⊕ (i : ℕ) × Functions L i)),
    listDecode (listEncode (ts a) ++ l) = some (ts a) :: listDecode l
l : List (α ⊕ (i : ℕ) × Functions L i)
h :
  listDecode ((List.bind (finRange n) fun i => listEncode (ts i)) ++ l) =
    List.map (some ∘ ts) (finRange n) ++ listDecode l
h' : ∀ (i : Fin n), get? (listDecode ((List.bind (finRange n) fun i => listEncode (ts i)) ++ l)) ↑i = some (some (ts i))
⊢ some
        (func f fun i =>
          Option.get (Option.join (get? (listDecode ((List.bind (finRange n) fun i => listEncode (ts i)) ++ l)) ↑i))
            (_ :
              Option.isSome
                  (Option.join (get? (listDecode ((List.bind (finRange n) fun i => listEncode (ts i)) ++ l)) ↑i)) =
                true)) ::
      drop n (listDecode ((List.bind (finRange n) fun i => listEncode (ts i)) ++ l)) =
    some (func f ts) :: listDecode l

Next tactic:
refine' congr (congr rfl (congr rfl (congr rfl (funext fun i => Option.get_of_mem _ _)))) _
theorem listDecode_encode_list (l : List (L.Term α)) :
    listDecode (l.bind listEncode) = l.map Option.some := by
  suffices h : ∀ (t : L.Term α) (l : List (Sum α (Σi, L.Functions i))),
      listDecode (t.listEncode ++ l) = some t::listDecode l
  · induction' l with t l lih
    · rfl
    · rw [cons_bind, h t (l.bind listEncode), lih, List.map]
  · intro t
    induction' t with a n f ts ih <;> intro l
    · rw [listEncode, singleton_append, listDecode]
    · rw [listEncode, cons_append, listDecode]
      have h : listDecode (((finRange n).bind fun i : Fin n => (ts i).listEncode) ++ l) =
          (finRange n).map (Option.some ∘ ts) ++ listDecode l := by
        induction' finRange n with i l' l'ih
        · rfl
        · rw [cons_bind, List.append_assoc, ih, map_cons, l'ih, cons_append, Function.comp]
      have h' : ∀ i : Fin n,
          (listDecode (((finRange n).bind fun i : Fin n => (ts i).listEncode) ++ l)).get? ↑i =
            some (some (ts i)) := by
        intro i
        rw [h, get?_append, get?_map]
        · simp only [Option.map_eq_some', Function.comp_apply, get?_eq_some]
          refine' ⟨i, ⟨lt_of_lt_of_le i.2 (ge_of_eq (length_finRange _)), _⟩, rfl⟩
          rw [get_finRange, Fin.eta]
        · refine' lt_of_lt_of_le i.2 _
          simp
      refine' (dif_pos fun i => Option.isSome_iff_exists.2 ⟨ts i, _⟩).trans _
      · rw [Option.join_eq_some, h']
      refine' congr (congr rfl (congr rfl (congr rfl (funext fun i => Option.get_of_mem _ _)))) _
      · 

Proof state:
case h.func.refine'_2.refine'_1
L : Language
M : Type w
N : Type u_1
P : Type u_2
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l✝ : List (Term L α)
n : ℕ
f : Functions L n
ts : Fin n → Term L α
ih :
  ∀ (a : Fin n) (l : List (α ⊕ (i : ℕ) × Functions L i)),
    listDecode (listEncode (ts a) ++ l) = some (ts a) :: listDecode l
l : List (α ⊕ (i : ℕ) × Functions L i)
h :
  listDecode ((List.bind (finRange n) fun i => listEncode (ts i)) ++ l) =
    List.map (some ∘ ts) (finRange n) ++ listDecode l
h' : ∀ (i : Fin n), get? (listDecode ((List.bind (finRange n) fun i => listEncode (ts i)) ++ l)) ↑i = some (some (ts i))
i : Fin n
⊢ ts i ∈ Option.join (get? (listDecode ((List.bind (finRange n) fun i => listEncode (ts i)) ++ l)) ↑i)

Next tactic:
simp [h']