Theorem: FirstOrder.Language.Term.listDecode_encode_list
File: Mathlib/ModelTheory/Encoding.lean

tactic: suffices h : ∀ (t : L.Term α) (l : List (Sum α (Σi, L.Functions i))),
    listDecode (t.listEncode ++ l) = some t::listDecode l
state_before: L : Language
M : Type w
N : Type ?u.2133
P : Type ?u.2136
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l : List (Term L α)
⊢ listDecode (List.bind l listEncode) = List.map some l

tactic: induction' l with t l lih
state_before: L : Language
M : Type w
N : Type ?u.2133
P : Type ?u.2136
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l : List (Term L α)
h : ∀ (t : Term L α) (l : List (α ⊕ (i : ℕ) × Functions L i)), listDecode (listEncode t ++ l) = some t :: listDecode l
⊢ listDecode (List.bind l listEncode) = List.map some l

tactic: rfl
state_before: case nil
L : Language
M : Type w
N : Type ?u.2133
P : Type ?u.2136
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
h : ∀ (t : Term L α) (l : List (α ⊕ (i : ℕ) × Functions L i)), listDecode (listEncode t ++ l) = some t :: listDecode l
⊢ listDecode (List.bind [] listEncode) = List.map some []

tactic: rw [cons_bind, h t (l.bind listEncode), lih, List.map]
state_before: case cons
L : Language
M : Type w
N : Type ?u.2133
P : Type ?u.2136
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
h : ∀ (t : Term L α) (l : List (α ⊕ (i : ℕ) × Functions L i)), listDecode (listEncode t ++ l) = some t :: listDecode l
t : Term L α
l : List (Term L α)
lih : listDecode (List.bind l listEncode) = List.map some l
⊢ listDecode (List.bind (t :: l) listEncode) = List.map some (t :: l)

tactic: intro t
state_before: case h
L : Language
M : Type w
N : Type ?u.2133
P : Type ?u.2136
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l : List (Term L α)
⊢ ∀ (t : Term L α) (l : List (α ⊕ (i : ℕ) × Functions L i)), listDecode (listEncode t ++ l) = some t :: listDecode l

tactic: induction' t with a n f ts ih <;> intro l
state_before: case h
L : Language
M : Type w
N : Type ?u.2133
P : Type ?u.2136
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l : List (Term L α)
t : Term L α
⊢ ∀ (l : List (α ⊕ (i : ℕ) × Functions L i)), listDecode (listEncode t ++ l) = some t :: listDecode l

tactic: rw [listEncode, singleton_append, listDecode]
state_before: case h.var
L : Language
M : Type w
N : Type ?u.2133
P : Type ?u.2136
inst✝² : Structure L M
inst✝¹ : Structure L N
inst✝ : Structure L P
α : Type u'
β : Type v'
l✝ : List (Term L α)
a : α
l : List (α ⊕ (i : ℕ) × Functions L i)
⊢ listDecode (listEncode (var a) ++ l) = some (var a) :: listDecode l

tactic: rw [listEncode, cons_append, listDecode]
state_before: case h.func
L : Language
M : Type w
N : Type ?u.2133
P : Type ?u.2136
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)
⊢ listDecode (listEncode (func f ts) ++ l) = some (func f ts) :: listDecode l

tactic: refine' (dif_pos fun i => Option.isSome_iff_exists.2 ⟨ts i, _⟩).trans _
state_before: case h.func
L : Language
M : Type w
N : Type ?u.2133
P : Type ?u.2136
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

tactic: refine' congr (congr rfl (congr rfl (congr rfl (funext fun i => Option.get_of_mem _ _)))) _
state_before: case h.func.refine'_2
L : Language
M : Type w
N : Type ?u.2133
P : Type ?u.2136
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

tactic: induction' finRange n with i l' l'ih
state_before: L : Language
M : Type w
N : Type ?u.2133
P : Type ?u.2136
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)
⊢ listDecode ((List.bind (finRange n) fun i => listEncode (ts i)) ++ l) =
    List.map (some ∘ ts) (finRange n) ++ listDecode l

tactic: rfl
state_before: case nil
L : Language
M : Type w
N : Type ?u.2133
P : Type ?u.2136
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)
⊢ listDecode ((List.bind [] fun i => listEncode (ts i)) ++ l) = List.map (some ∘ ts) [] ++ listDecode l

tactic: rw [cons_bind, List.append_assoc, ih, map_cons, l'ih, cons_append, Function.comp]
state_before: case cons
L : Language
M : Type w
N : Type ?u.2133
P : Type ?u.2136
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)
i : Fin n
l' : List (Fin n)
l'ih : listDecode ((List.bind l' fun i => listEncode (ts i)) ++ l) = List.map (some ∘ ts) l' ++ listDecode l
⊢ listDecode ((List.bind (i :: l') fun i => listEncode (ts i)) ++ l) = List.map (some ∘ ts) (i :: l') ++ listDecode l

tactic: intro i
state_before: L : Language
M : Type w
N : Type ?u.2133
P : Type ?u.2136
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))

tactic: rw [h, get?_append, get?_map]
state_before: L : Language
M : Type w
N : Type ?u.2133
P : Type ?u.2136
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))

tactic: simp only [Option.map_eq_some', Function.comp_apply, get?_eq_some]
state_before: L : Language
M : Type w
N : Type ?u.2133
P : Type ?u.2136
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))

tactic: refine' ⟨i, ⟨lt_of_lt_of_le i.2 (ge_of_eq (length_finRange _)), _⟩, rfl⟩
state_before: L : Language
M : Type w
N : Type ?u.2133
P : Type ?u.2136
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, List.get (finRange n) { val := ↑i, isLt := h } = a) ∧ some (ts a) = some (ts i)

tactic: rw [get_finRange, Fin.eta]
state_before: L : Language
M : Type w
N : Type ?u.2133
P : Type ?u.2136
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

tactic: refine' lt_of_lt_of_le i.2 _
state_before: L : Language
M : Type w
N : Type ?u.2133
P : Type ?u.2136
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))

tactic: simp
state_before: L : Language
M : Type w
N : Type ?u.2133
P : Type ?u.2136
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))

tactic: rw [Option.join_eq_some, h']
state_before: case h.func.refine'_1
L : Language
M : Type w
N : Type ?u.2133
P : Type ?u.2136
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)

tactic: simp [h']
state_before: case h.func.refine'_2.refine'_1
L : Language
M : Type w
N : Type ?u.2133
P : Type ?u.2136
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)

tactic: rw [h, drop_left']
state_before: case h.func.refine'_2.refine'_2
L : Language
M : Type w
N : Type ?u.2133
P : Type ?u.2136
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))
⊢ drop n (listDecode ((List.bind (finRange n) fun i => listEncode (ts i)) ++ l)) = listDecode l

tactic: rw [length_map, length_finRange]
state_before: case h.func.refine'_2.refine'_2
L : Language
M : Type w
N : Type ?u.2133
P : Type ?u.2136
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))
⊢ length (List.map (some ∘ ts) (finRange n)) = n