l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) :
    (listDecode (l.bind fun φ => φ.2.listEncode)).1 = l.headI := by
  suffices h : ∀ (φ : Σn, L.BoundedFormula α n) (l),
      (listDecode (listEncode φ.2 ++ l)).1 = φ ∧ (listDecode (listEncode φ.2 ++ l)).2.1 = l
  · induction' l with φ l _
    · rw [List.nil_bind]
      simp [listDecode]
    · rw [cons_bind, (h φ _).1, headI_cons]
  · rintro ⟨n, φ⟩
    induction' φ with _ _ _ _ φ_n φ_l φ_R ts _ _ _ ih1 ih2 _ _ ih <;> intro l
    · rw [listEncode, singleton_append, listDecode]
      simp only [eq_self_iff_true, heq_iff_eq, and_self_iff]
    · rw [listEncode, cons_append, cons_append, listDecode, dif_pos]
      · simp only [eq_mp_eq_cast, cast_eq, eq_self_iff_true, heq_iff_eq, and_self_iff, nil_append]
      · simp only [eq_self_iff_true, heq_iff_eq, and_self_iff]
    · rw [listEncode, cons_append, cons_append, singleton_append, cons_append, listDecode]
      · have h : ∀ i : Fin φ_l, ((List.map Sum.getLeft? (List.map (fun i : Fin φ_l =>
          Sum.inl (⟨(⟨φ_n, rel φ_R ts⟩ : Σn, L.BoundedFormula α n).fst, ts i⟩ :
            Σn, L.Term (Sum α (Fin n)))) (finRange φ_l) ++ l)).get? ↑i).join = 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 ((n : ℕ) × BoundedFormula L α n)
n φ_n φ_l : ℕ
φ_R : Relations L φ_l
ts : Fin φ_l → Term L (α ⊕ Fin φ_n)
l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)
⊢ ∀ (i : Fin φ_l),
    Option.join
        (get?
          (List.map Sum.getLeft?
            (List.map (fun i => Sum.inl { fst := { fst := φ_n, snd := rel φ_R ts }.fst, snd := ts i }) (finRange φ_l) ++
              l))
          ↑i) =
      some { fst := φ_n, snd := ts i }

Next tactic:
intro i
@[simp]
theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) :
    (listDecode (l.bind fun φ => φ.2.listEncode)).1 = l.headI := by
  suffices h : ∀ (φ : Σn, L.BoundedFormula α n) (l),
      (listDecode (listEncode φ.2 ++ l)).1 = φ ∧ (listDecode (listEncode φ.2 ++ l)).2.1 = l
  · induction' l with φ l _
    · rw [List.nil_bind]
      simp [listDecode]
    · rw [cons_bind, (h φ _).1, headI_cons]
  · rintro ⟨n, φ⟩
    induction' φ with _ _ _ _ φ_n φ_l φ_R ts _ _ _ ih1 ih2 _ _ ih <;> intro l
    · rw [listEncode, singleton_append, listDecode]
      simp only [eq_self_iff_true, heq_iff_eq, and_self_iff]
    · rw [listEncode, cons_append, cons_append, listDecode, dif_pos]
      · simp only [eq_mp_eq_cast, cast_eq, eq_self_iff_true, heq_iff_eq, and_self_iff, nil_append]
      · simp only [eq_self_iff_true, heq_iff_eq, and_self_iff]
    · rw [listEncode, cons_append, cons_append, singleton_append, cons_append, listDecode]
      · have h : ∀ i : Fin φ_l, ((List.map Sum.getLeft? (List.map (fun i : Fin φ_l =>
          Sum.inl (⟨(⟨φ_n, rel φ_R ts⟩ : Σn, L.BoundedFormula α n).fst, ts i⟩ :
            Σn, L.Term (Sum α (Fin n)))) (finRange φ_l) ++ l)).get? ↑i).join = 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 ((n : ℕ) × BoundedFormula L α n)
n φ_n φ_l : ℕ
φ_R : Relations L φ_l
ts : Fin φ_l → Term L (α ⊕ Fin φ_n)
l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)
i : Fin φ_l
⊢ Option.join
      (get?
        (List.map Sum.getLeft?
          (List.map (fun i => Sum.inl { fst := { fst := φ_n, snd := rel φ_R ts }.fst, snd := ts i }) (finRange φ_l) ++
            l))
        ↑i) =
    some { fst := φ_n, snd := ts i }

Next tactic:
simp only [Option.join, map_append, map_map, Option.bind_eq_some, id.def, exists_eq_right,
            get?_eq_some, length_append, length_map, length_finRange]
@[simp]
theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) :
    (listDecode (l.bind fun φ => φ.2.listEncode)).1 = l.headI := by
  suffices h : ∀ (φ : Σn, L.BoundedFormula α n) (l),
      (listDecode (listEncode φ.2 ++ l)).1 = φ ∧ (listDecode (listEncode φ.2 ++ l)).2.1 = l
  · induction' l with φ l _
    · rw [List.nil_bind]
      simp [listDecode]
    · rw [cons_bind, (h φ _).1, headI_cons]
  · rintro ⟨n, φ⟩
    induction' φ with _ _ _ _ φ_n φ_l φ_R ts _ _ _ ih1 ih2 _ _ ih <;> intro l
    · rw [listEncode, singleton_append, listDecode]
      simp only [eq_self_iff_true, heq_iff_eq, and_self_iff]
    · rw [listEncode, cons_append, cons_append, listDecode, dif_pos]
      · simp only [eq_mp_eq_cast, cast_eq, eq_self_iff_true, heq_iff_eq, and_self_iff, nil_append]
      · simp only [eq_self_iff_true, heq_iff_eq, and_self_iff]
    · rw [listEncode, cons_append, cons_append, singleton_append, cons_append, listDecode]
      · have h : ∀ i : Fin φ_l, ((List.map Sum.getLeft? (List.map (fun i : Fin φ_l =>
          Sum.inl (⟨(⟨φ_n, rel φ_R ts⟩ : Σn, L.BoundedFormula α n).fst, ts i⟩ :
            Σn, L.Term (Sum α (Fin n)))) (finRange φ_l) ++ l)).get? ↑i).join = some ⟨_, ts i⟩ := by
          intro i
          simp only [Option.join, map_append, map_map, Option.bind_eq_some, id.def, exists_eq_right,
            get?_eq_some, length_append, length_map, length_finRange]
          

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 ((n : ℕ) × BoundedFormula L α n)
n φ_n φ_l : ℕ
φ_R : Relations L φ_l
ts : Fin φ_l → Term L (α ⊕ Fin φ_n)
l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)
i : Fin φ_l
⊢ ∃ (h : ↑i < φ_l + length l),
    List.get
        (List.map (Sum.getLeft? ∘ fun i => Sum.inl { fst := φ_n, snd := ts i }) (finRange φ_l) ++
          List.map Sum.getLeft? l)
        { val := ↑i,
          isLt :=
            (_ :
              ↑i <
                length
                  (List.map (Sum.getLeft? ∘ fun i => Sum.inl { fst := φ_n, snd := ts i }) (finRange φ_l) ++
                    List.map Sum.getLeft? l)) } =
      some { fst := φ_n, snd := ts i }

Next tactic:
refine' ⟨lt_of_lt_of_le i.2 le_self_add, _⟩
@[simp]
theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) :
    (listDecode (l.bind fun φ => φ.2.listEncode)).1 = l.headI := by
  suffices h : ∀ (φ : Σn, L.BoundedFormula α n) (l),
      (listDecode (listEncode φ.2 ++ l)).1 = φ ∧ (listDecode (listEncode φ.2 ++ l)).2.1 = l
  · induction' l with φ l _
    · rw [List.nil_bind]
      simp [listDecode]
    · rw [cons_bind, (h φ _).1, headI_cons]
  · rintro ⟨n, φ⟩
    induction' φ with _ _ _ _ φ_n φ_l φ_R ts _ _ _ ih1 ih2 _ _ ih <;> intro l
    · rw [listEncode, singleton_append, listDecode]
      simp only [eq_self_iff_true, heq_iff_eq, and_self_iff]
    · rw [listEncode, cons_append, cons_append, listDecode, dif_pos]
      · simp only [eq_mp_eq_cast, cast_eq, eq_self_iff_true, heq_iff_eq, and_self_iff, nil_append]
      · simp only [eq_self_iff_true, heq_iff_eq, and_self_iff]
    · rw [listEncode, cons_append, cons_append, singleton_append, cons_append, listDecode]
      · have h : ∀ i : Fin φ_l, ((List.map Sum.getLeft? (List.map (fun i : Fin φ_l =>
          Sum.inl (⟨(⟨φ_n, rel φ_R ts⟩ : Σn, L.BoundedFormula α n).fst, ts i⟩ :
            Σn, L.Term (Sum α (Fin n)))) (finRange φ_l) ++ l)).get? ↑i).join = some ⟨_, ts i⟩ := by
          intro i
          simp only [Option.join, map_append, map_map, Option.bind_eq_some, id.def, exists_eq_right,
            get?_eq_some, length_append, length_map, length_finRange]
          refine' ⟨lt_of_lt_of_le i.2 le_self_add, _⟩
          

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 ((n : ℕ) × BoundedFormula L α n)
n φ_n φ_l : ℕ
φ_R : Relations L φ_l
ts : Fin φ_l → Term L (α ⊕ Fin φ_n)
l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)
i : Fin φ_l
⊢ List.get
      (List.map (Sum.getLeft? ∘ fun i => Sum.inl { fst := φ_n, snd := ts i }) (finRange φ_l) ++ List.map Sum.getLeft? l)
      { val := ↑i,
        isLt :=
          (_ :
            ↑i <
              length
                (List.map (Sum.getLeft? ∘ fun i => Sum.inl { fst := φ_n, snd := ts i }) (finRange φ_l) ++
                  List.map Sum.getLeft? l)) } =
    some { fst := φ_n, snd := ts i }

Next tactic:
rw [get_append, get_map]
@[simp]
theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) :
    (listDecode (l.bind fun φ => φ.2.listEncode)).1 = l.headI := by
  suffices h : ∀ (φ : Σn, L.BoundedFormula α n) (l),
      (listDecode (listEncode φ.2 ++ l)).1 = φ ∧ (listDecode (listEncode φ.2 ++ l)).2.1 = l
  · induction' l with φ l _
    · rw [List.nil_bind]
      simp [listDecode]
    · rw [cons_bind, (h φ _).1, headI_cons]
  · rintro ⟨n, φ⟩
    induction' φ with _ _ _ _ φ_n φ_l φ_R ts _ _ _ ih1 ih2 _ _ ih <;> intro l
    · rw [listEncode, singleton_append, listDecode]
      simp only [eq_self_iff_true, heq_iff_eq, and_self_iff]
    · rw [listEncode, cons_append, cons_append, listDecode, dif_pos]
      · simp only [eq_mp_eq_cast, cast_eq, eq_self_iff_true, heq_iff_eq, and_self_iff, nil_append]
      · simp only [eq_self_iff_true, heq_iff_eq, and_self_iff]
    · rw [listEncode, cons_append, cons_append, singleton_append, cons_append, listDecode]
      · have h : ∀ i : Fin φ_l, ((List.map Sum.getLeft? (List.map (fun i : Fin φ_l =>
          Sum.inl (⟨(⟨φ_n, rel φ_R ts⟩ : Σn, L.BoundedFormula α n).fst, ts i⟩ :
            Σn, L.Term (Sum α (Fin n)))) (finRange φ_l) ++ l)).get? ↑i).join = some ⟨_, ts i⟩ := by
          intro i
          simp only [Option.join, map_append, map_map, Option.bind_eq_some, id.def, exists_eq_right,
            get?_eq_some, length_append, length_map, length_finRange]
          refine' ⟨lt_of_lt_of_le i.2 le_self_add, _⟩
          rw [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 ((n : ℕ) × BoundedFormula L α n)
n φ_n φ_l : ℕ
φ_R : Relations L φ_l
ts : Fin φ_l → Term L (α ⊕ Fin φ_n)
l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)
i : Fin φ_l
⊢ (Sum.getLeft? ∘ fun i => Sum.inl { fst := φ_n, snd := ts i })
      (List.get (finRange φ_l)
        { val := ↑{ val := ↑i, isLt := ?h }, isLt := (_ : ↑{ val := ↑i, isLt := ?h } < length (finRange φ_l)) }) =
    some { fst := φ_n, snd := ts i }

Next tactic:
simp only [Sum.getLeft?, get_finRange, Fin.eta, Function.comp_apply, eq_self_iff_true,
              heq_iff_eq, and_self_iff]
@[simp]
theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) :
    (listDecode (l.bind fun φ => φ.2.listEncode)).1 = l.headI := by
  suffices h : ∀ (φ : Σn, L.BoundedFormula α n) (l),
      (listDecode (listEncode φ.2 ++ l)).1 = φ ∧ (listDecode (listEncode φ.2 ++ l)).2.1 = l
  · induction' l with φ l _
    · rw [List.nil_bind]
      simp [listDecode]
    · rw [cons_bind, (h φ _).1, headI_cons]
  · rintro ⟨n, φ⟩
    induction' φ with _ _ _ _ φ_n φ_l φ_R ts _ _ _ ih1 ih2 _ _ ih <;> intro l
    · rw [listEncode, singleton_append, listDecode]
      simp only [eq_self_iff_true, heq_iff_eq, and_self_iff]
    · rw [listEncode, cons_append, cons_append, listDecode, dif_pos]
      · simp only [eq_mp_eq_cast, cast_eq, eq_self_iff_true, heq_iff_eq, and_self_iff, nil_append]
      · simp only [eq_self_iff_true, heq_iff_eq, and_self_iff]
    · rw [listEncode, cons_append, cons_append, singleton_append, cons_append, listDecode]
      · have h : ∀ i : Fin φ_l, ((List.map Sum.getLeft? (List.map (fun i : Fin φ_l =>
          Sum.inl (⟨(⟨φ_n, rel φ_R ts⟩ : Σn, L.BoundedFormula α n).fst, ts i⟩ :
            Σn, L.Term (Sum α (Fin n)))) (finRange φ_l) ++ l)).get? ↑i).join = some ⟨_, ts i⟩ := by
          intro i
          simp only [Option.join, map_append, map_map, Option.bind_eq_some, id.def, exists_eq_right,
            get?_eq_some, length_append, length_map, length_finRange]
          refine' ⟨lt_of_lt_of_le i.2 le_self_add, _⟩
          rw [get_append, get_map]
          · simp only [Sum.getLeft?, get_finRange, Fin.eta, Function.comp_apply, eq_self_iff_true,
              heq_iff_eq, and_self_iff]
          · 

Proof state:
case h
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 ((n : ℕ) × BoundedFormula L α n)
n φ_n φ_l : ℕ
φ_R : Relations L φ_l
ts : Fin φ_l → Term L (α ⊕ Fin φ_n)
l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)
i : Fin φ_l
⊢ ↑i < length (List.map (Sum.getLeft? ∘ fun i => Sum.inl { fst := φ_n, snd := ts i }) (finRange φ_l))

Next tactic:
simp only [length_map, length_finRange, is_lt]
@[simp]
theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) :
    (listDecode (l.bind fun φ => φ.2.listEncode)).1 = l.headI := by
  suffices h : ∀ (φ : Σn, L.BoundedFormula α n) (l),
      (listDecode (listEncode φ.2 ++ l)).1 = φ ∧ (listDecode (listEncode φ.2 ++ l)).2.1 = l
  · induction' l with φ l _
    · rw [List.nil_bind]
      simp [listDecode]
    · rw [cons_bind, (h φ _).1, headI_cons]
  · rintro ⟨n, φ⟩
    induction' φ with _ _ _ _ φ_n φ_l φ_R ts _ _ _ ih1 ih2 _ _ ih <;> intro l
    · rw [listEncode, singleton_append, listDecode]
      simp only [eq_self_iff_true, heq_iff_eq, and_self_iff]
    · rw [listEncode, cons_append, cons_append, listDecode, dif_pos]
      · simp only [eq_mp_eq_cast, cast_eq, eq_self_iff_true, heq_iff_eq, and_self_iff, nil_append]
      · simp only [eq_self_iff_true, heq_iff_eq, and_self_iff]
    · rw [listEncode, cons_append, cons_append, singleton_append, cons_append, listDecode]
      · have h : ∀ i : Fin φ_l, ((List.map Sum.getLeft? (List.map (fun i : Fin φ_l =>
          Sum.inl (⟨(⟨φ_n, rel φ_R ts⟩ : Σn, L.BoundedFormula α n).fst, ts i⟩ :
            Σn, L.Term (Sum α (Fin n)))) (finRange φ_l) ++ l)).get? ↑i).join = some ⟨_, ts i⟩ := by
          intro i
          simp only [Option.join, map_append, map_map, Option.bind_eq_some, id.def, exists_eq_right,
            get?_eq_some, length_append, length_map, length_finRange]
          refine' ⟨lt_of_lt_of_le i.2 le_self_add, _⟩
          rw [get_append, get_map]
          · simp only [Sum.getLeft?, get_finRange, Fin.eta, Function.comp_apply, eq_self_iff_true,
              heq_iff_eq, and_self_iff]
          · simp only [length_map, length_finRange, is_lt]
        rw [dif_pos]
        swap
        · 

Proof state:
case h.mk.rel.hc
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 ((n : ℕ) × BoundedFormula L α n)
n φ_n φ_l : ℕ
φ_R : Relations L φ_l
ts : Fin φ_l → Term L (α ⊕ Fin φ_n)
l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)
h :
  ∀ (i : Fin φ_l),
    Option.join
        (get?
          (List.map Sum.getLeft?
            (List.map (fun i => Sum.inl { fst := { fst := φ_n, snd := rel φ_R ts }.fst, snd := ts i }) (finRange φ_l) ++
              l))
          ↑i) =
      some { fst := φ_n, snd := ts i }
⊢ ∀ (i : Fin φ_l),
    Option.isSome
        (Option.join
          (get?
            (List.map Sum.getLeft?
              (List.map (fun i => Sum.inl { fst := { fst := φ_n, snd := rel φ_R ts }.fst, snd := ts i })
                  (finRange φ_l) ++
                l))
            ↑i)) =
      true

Next tactic:
exact fun i => Option.isSome_iff_exists.2 ⟨⟨_, ts i⟩, h i⟩
@[simp]
theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) :
    (listDecode (l.bind fun φ => φ.2.listEncode)).1 = l.headI := by
  suffices h : ∀ (φ : Σn, L.BoundedFormula α n) (l),
      (listDecode (listEncode φ.2 ++ l)).1 = φ ∧ (listDecode (listEncode φ.2 ++ l)).2.1 = l
  · induction' l with φ l _
    · rw [List.nil_bind]
      simp [listDecode]
    · rw [cons_bind, (h φ _).1, headI_cons]
  · rintro ⟨n, φ⟩
    induction' φ with _ _ _ _ φ_n φ_l φ_R ts _ _ _ ih1 ih2 _ _ ih <;> intro l
    · rw [listEncode, singleton_append, listDecode]
      simp only [eq_self_iff_true, heq_iff_eq, and_self_iff]
    · rw [listEncode, cons_append, cons_append, listDecode, dif_pos]
      · simp only [eq_mp_eq_cast, cast_eq, eq_self_iff_true, heq_iff_eq, and_self_iff, nil_append]
      · simp only [eq_self_iff_true, heq_iff_eq, and_self_iff]
    · rw [listEncode, cons_append, cons_append, singleton_append, cons_append, listDecode]
      · have h : ∀ i : Fin φ_l, ((List.map Sum.getLeft? (List.map (fun i : Fin φ_l =>
          Sum.inl (⟨(⟨φ_n, rel φ_R ts⟩ : Σn, L.BoundedFormula α n).fst, ts i⟩ :
            Σn, L.Term (Sum α (Fin n)))) (finRange φ_l) ++ l)).get? ↑i).join = some ⟨_, ts i⟩ := by
          intro i
          simp only [Option.join, map_append, map_map, Option.bind_eq_some, id.def, exists_eq_right,
            get?_eq_some, length_append, length_map, length_finRange]
          refine' ⟨lt_of_lt_of_le i.2 le_self_add, _⟩
          rw [get_append, get_map]
          · simp only [Sum.getLeft?, get_finRange, Fin.eta, Function.comp_apply, eq_self_iff_true,
              heq_iff_eq, and_self_iff]
          · simp only [length_map, length_finRange, is_lt]
        rw [dif_pos]
        swap
        · exact fun i => Option.isSome_iff_exists.2 ⟨⟨_, ts i⟩, h i⟩
        rw [dif_pos]
        swap
        · intro i
          obtain ⟨h1, h2⟩ := Option.eq_some_iff_get_eq.1 (h i)
          rw [h2]
        simp only [Sigma.mk.inj_iff, heq_eq_eq, rel.injEq, true_and]
        refine' ⟨funext fun i => _, _⟩
        · obtain ⟨h1, h2⟩ := Option.eq_some_iff_get_eq.1 (h i)
          rw [eq_mp_eq_cast, cast_eq_iff_heq]
          exact (Sigma.ext_iff.1 ((Sigma.eta (Option.get _ h1)).trans h2)).2
        

Proof state:
case h.mk.rel.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 ((n : ℕ) × BoundedFormula L α n)
n φ_n φ_l : ℕ
φ_R : Relations L φ_l
ts : Fin φ_l → Term L (α ⊕ Fin φ_n)
l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)
h :
  ∀ (i : Fin φ_l),
    Option.join
        (get?
          (List.map Sum.getLeft?
            (List.map (fun i => Sum.inl { fst := { fst := φ_n, snd := rel φ_R ts }.fst, snd := ts i }) (finRange φ_l) ++
              l))
          ↑i) =
      some { fst := φ_n, snd := ts i }
⊢ drop φ_l (List.map (fun i => Sum.inl { fst := φ_n, snd := ts i }) (finRange φ_l) ++ l) = l

Next tactic:
rw [List.drop_append_eq_append_drop, length_map, length_finRange, Nat.sub_self, drop,
          drop_eq_nil_of_le, nil_append]
@[simp]
theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) :
    (listDecode (l.bind fun φ => φ.2.listEncode)).1 = l.headI := by
  suffices h : ∀ (φ : Σn, L.BoundedFormula α n) (l),
      (listDecode (listEncode φ.2 ++ l)).1 = φ ∧ (listDecode (listEncode φ.2 ++ l)).2.1 = l
  · induction' l with φ l _
    · rw [List.nil_bind]
      simp [listDecode]
    · rw [cons_bind, (h φ _).1, headI_cons]
  · rintro ⟨n, φ⟩
    induction' φ with _ _ _ _ φ_n φ_l φ_R ts _ _ _ ih1 ih2 _ _ ih <;> intro l
    · rw [listEncode, singleton_append, listDecode]
      simp only [eq_self_iff_true, heq_iff_eq, and_self_iff]
    · rw [listEncode, cons_append, cons_append, listDecode, dif_pos]
      · simp only [eq_mp_eq_cast, cast_eq, eq_self_iff_true, heq_iff_eq, and_self_iff, nil_append]
      · simp only [eq_self_iff_true, heq_iff_eq, and_self_iff]
    · rw [listEncode, cons_append, cons_append, singleton_append, cons_append, listDecode]
      · have h : ∀ i : Fin φ_l, ((List.map Sum.getLeft? (List.map (fun i : Fin φ_l =>
          Sum.inl (⟨(⟨φ_n, rel φ_R ts⟩ : Σn, L.BoundedFormula α n).fst, ts i⟩ :
            Σn, L.Term (Sum α (Fin n)))) (finRange φ_l) ++ l)).get? ↑i).join = some ⟨_, ts i⟩ := by
          intro i
          simp only [Option.join, map_append, map_map, Option.bind_eq_some, id.def, exists_eq_right,
            get?_eq_some, length_append, length_map, length_finRange]
          refine' ⟨lt_of_lt_of_le i.2 le_self_add, _⟩
          rw [get_append, get_map]
          · simp only [Sum.getLeft?, get_finRange, Fin.eta, Function.comp_apply, eq_self_iff_true,
              heq_iff_eq, and_self_iff]
          · simp only [length_map, length_finRange, is_lt]
        rw [dif_pos]
        swap
        · exact fun i => Option.isSome_iff_exists.2 ⟨⟨_, ts i⟩, h i⟩
        rw [dif_pos]
        swap
        · intro i
          obtain ⟨h1, h2⟩ := Option.eq_some_iff_get_eq.1 (h i)
          rw [h2]
        simp only [Sigma.mk.inj_iff, heq_eq_eq, rel.injEq, true_and]
        refine' ⟨funext fun i => _, _⟩
        · obtain ⟨h1, h2⟩ := Option.eq_some_iff_get_eq.1 (h i)
          rw [eq_mp_eq_cast, cast_eq_iff_heq]
          exact (Sigma.ext_iff.1 ((Sigma.eta (Option.get _ h1)).trans h2)).2
        rw [List.drop_append_eq_append_drop, length_map, length_finRange, Nat.sub_self, drop,
          drop_eq_nil_of_le, nil_append]
        

Proof state:
case h.mk.rel.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 ((n : ℕ) × BoundedFormula L α n)
n φ_n φ_l : ℕ
φ_R : Relations L φ_l
ts : Fin φ_l → Term L (α ⊕ Fin φ_n)
l : List ((k : ℕ) × Term L (α ⊕ Fin k) ⊕ (n : ℕ) × Relations L n ⊕ ℕ)
h :
  ∀ (i : Fin φ_l),
    Option.join
        (get?
          (List.map Sum.getLeft?
            (List.map (fun i => Sum.inl { fst := { fst := φ_n, snd := rel φ_R ts }.fst, snd := ts i }) (finRange φ_l) ++
              l))
          ↑i) =
      some { fst := φ_n, snd := ts i }
⊢ length (List.map (fun i => Sum.inl { fst := φ_n, snd := ts i }) (finRange φ_l)) ≤ φ_l

Next tactic:
rw [length_map, length_finRange]
/-- An encoding of bounded formulas as lists. -/
@[simps]
protected def encoding : Encoding (Σn, L.BoundedFormula α n) where
  Γ := Sum (Σk, L.Term (Sum α (Fin k))) (Sum (Σn, L.Relations n) ℕ)
  encode φ := φ.2.listEncode
  decode l := (listDecode l).1
  decode_encode φ := 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'
φ : (n : ℕ) × BoundedFormula L α n
⊢ (fun l => some (listDecode l).1) ((fun φ => listEncode φ.snd) φ) = some φ

Next tactic:
have h := listDecode_encode_list [φ]
/-- An encoding of bounded formulas as lists. -/
@[simps]
protected def encoding : Encoding (Σn, L.BoundedFormula α n) where
  Γ := Sum (Σk, L.Term (Sum α (Fin k))) (Sum (Σn, L.Relations n) ℕ)
  encode φ := φ.2.listEncode
  decode l := (listDecode l).1
  decode_encode φ := by
    have h := listDecode_encode_list [φ]
    

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'
φ : (n : ℕ) × BoundedFormula L α n
h : (listDecode (List.bind [φ] fun φ => listEncode φ.snd)).1 = headI [φ]
⊢ (fun l => some (listDecode l).1) ((fun φ => listEncode φ.snd) φ) = some φ

Next tactic:
rw [bind_singleton] at h
/-- An encoding of bounded formulas as lists. -/
@[simps]
protected def encoding : Encoding (Σn, L.BoundedFormula α n) where
  Γ := Sum (Σk, L.Term (Sum α (Fin k))) (Sum (Σn, L.Relations n) ℕ)
  encode φ := φ.2.listEncode
  decode l := (listDecode l).1
  decode_encode φ := by
    have h := listDecode_encode_list [φ]
    rw [bind_singleton] at h
    

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'
φ : (n : ℕ) × BoundedFormula L α n
h : (listDecode (listEncode φ.snd)).1 = headI [φ]
⊢ (fun l => some (listDecode l).1) ((fun φ => listEncode φ.snd) φ) = some φ

Next tactic:
simp only