l3lab/ntp-mathlib huggingface dataset:
theorem get?_mem {s : WSeq α} {a n} : some a ∈ get? s n → a ∈ s := by
  revert s; induction' n with n IH <;> intro s h
  · -- Porting note: This line is required to infer metavariables in
    --               `Computation.exists_of_mem_map`.
    dsimp only [get?, head] at h
    rcases Computation.exists_of_mem_map h with ⟨o, h1, h2⟩
    

Proof state:
case zero.intro.intro
α : Type u
β : Type v
γ : Type w
a : α
s : WSeq α
h : some a ∈ Computation.map (fun x => Prod.fst <$> x) (destruct (drop s Nat.zero))
o : Option (α × WSeq α)
h1 : o ∈ destruct (drop s Nat.zero)
h2 : Prod.fst <$> o = some a
⊢ a ∈ s

Next tactic:
cases' o with o
theorem get?_mem {s : WSeq α} {a n} : some a ∈ get? s n → a ∈ s := by
  revert s; induction' n with n IH <;> intro s h
  · -- Porting note: This line is required to infer metavariables in
    --               `Computation.exists_of_mem_map`.
    dsimp only [get?, head] at h
    rcases Computation.exists_of_mem_map h with ⟨o, h1, h2⟩
    cases' o with o
    · 

Proof state:
case zero.intro.intro.none
α : Type u
β : Type v
γ : Type w
a : α
s : WSeq α
h : some a ∈ Computation.map (fun x => Prod.fst <$> x) (destruct (drop s Nat.zero))
h1 : none ∈ destruct (drop s Nat.zero)
h2 : Prod.fst <$> none = some a
⊢ a ∈ s

Next tactic:
injection h2
theorem get?_mem {s : WSeq α} {a n} : some a ∈ get? s n → a ∈ s := by
  revert s; induction' n with n IH <;> intro s h
  · -- Porting note: This line is required to infer metavariables in
    --               `Computation.exists_of_mem_map`.
    dsimp only [get?, head] at h
    rcases Computation.exists_of_mem_map h with ⟨o, h1, h2⟩
    cases' o with o
    · injection h2
    

Proof state:
case zero.intro.intro.some
α : Type u
β : Type v
γ : Type w
a : α
s : WSeq α
h : some a ∈ Computation.map (fun x => Prod.fst <$> x) (destruct (drop s Nat.zero))
o : α × WSeq α
h1 : some o ∈ destruct (drop s Nat.zero)
h2 : Prod.fst <$> some o = some a
⊢ a ∈ s

Next tactic:
injection h2 with h'
theorem get?_mem {s : WSeq α} {a n} : some a ∈ get? s n → a ∈ s := by
  revert s; induction' n with n IH <;> intro s h
  · -- Porting note: This line is required to infer metavariables in
    --               `Computation.exists_of_mem_map`.
    dsimp only [get?, head] at h
    rcases Computation.exists_of_mem_map h with ⟨o, h1, h2⟩
    cases' o with o
    · injection h2
    injection h2 with h'
    

Proof state:
case zero.intro.intro.some
α : Type u
β : Type v
γ : Type w
a : α
s : WSeq α
h : some a ∈ Computation.map (fun x => Prod.fst <$> x) (destruct (drop s Nat.zero))
o : α × WSeq α
h1 : some o ∈ destruct (drop s Nat.zero)
h' : o.1 = a
⊢ a ∈ s

Next tactic:
cases' o with a' s'
theorem get?_mem {s : WSeq α} {a n} : some a ∈ get? s n → a ∈ s := by
  revert s; induction' n with n IH <;> intro s h
  · -- Porting note: This line is required to infer metavariables in
    --               `Computation.exists_of_mem_map`.
    dsimp only [get?, head] at h
    rcases Computation.exists_of_mem_map h with ⟨o, h1, h2⟩
    cases' o with o
    · injection h2
    injection h2 with h'
    cases' o with a' s'
    

Proof state:
case zero.intro.intro.some.mk
α : Type u
β : Type v
γ : Type w
a : α
s : WSeq α
h : some a ∈ Computation.map (fun x => Prod.fst <$> x) (destruct (drop s Nat.zero))
a' : α
s' : WSeq α
h1 : some (a', s') ∈ destruct (drop s Nat.zero)
h' : (a', s').1 = a
⊢ a ∈ s

Next tactic:
exact (eq_or_mem_iff_mem h1).2 (Or.inl h'.symm)
theorem get?_mem {s : WSeq α} {a n} : some a ∈ get? s n → a ∈ s := by
  revert s; induction' n with n IH <;> intro s h
  · -- Porting note: This line is required to infer metavariables in
    --               `Computation.exists_of_mem_map`.
    dsimp only [get?, head] at h
    rcases Computation.exists_of_mem_map h with ⟨o, h1, h2⟩
    cases' o with o
    · injection h2
    injection h2 with h'
    cases' o with a' s'
    exact (eq_or_mem_iff_mem h1).2 (Or.inl h'.symm)
  · 

Proof state:
case succ
α : Type u
β : Type v
γ : Type w
a : α
n : ℕ
IH : ∀ {s : WSeq α}, some a ∈ get? s n → a ∈ s
s : WSeq α
h : some a ∈ get? s (Nat.succ n)
⊢ a ∈ s

Next tactic:
have := @IH (tail s)
theorem get?_mem {s : WSeq α} {a n} : some a ∈ get? s n → a ∈ s := by
  revert s; induction' n with n IH <;> intro s h
  · -- Porting note: This line is required to infer metavariables in
    --               `Computation.exists_of_mem_map`.
    dsimp only [get?, head] at h
    rcases Computation.exists_of_mem_map h with ⟨o, h1, h2⟩
    cases' o with o
    · injection h2
    injection h2 with h'
    cases' o with a' s'
    exact (eq_or_mem_iff_mem h1).2 (Or.inl h'.symm)
  · have := @IH (tail s)
    

Proof state:
case succ
α : Type u
β : Type v
γ : Type w
a : α
n : ℕ
IH : ∀ {s : WSeq α}, some a ∈ get? s n → a ∈ s
s : WSeq α
h : some a ∈ get? s (Nat.succ n)
this : some a ∈ get? (tail s) n → a ∈ tail s
⊢ a ∈ s

Next tactic:
rw [get?_tail] at this
theorem get?_mem {s : WSeq α} {a n} : some a ∈ get? s n → a ∈ s := by
  revert s; induction' n with n IH <;> intro s h
  · -- Porting note: This line is required to infer metavariables in
    --               `Computation.exists_of_mem_map`.
    dsimp only [get?, head] at h
    rcases Computation.exists_of_mem_map h with ⟨o, h1, h2⟩
    cases' o with o
    · injection h2
    injection h2 with h'
    cases' o with a' s'
    exact (eq_or_mem_iff_mem h1).2 (Or.inl h'.symm)
  · have := @IH (tail s)
    rw [get?_tail] at this
    

Proof state:
case succ
α : Type u
β : Type v
γ : Type w
a : α
n : ℕ
IH : ∀ {s : WSeq α}, some a ∈ get? s n → a ∈ s
s : WSeq α
h : some a ∈ get? s (Nat.succ n)
this : some a ∈ get? s (n + 1) → a ∈ tail s
⊢ a ∈ s

Next tactic:
exact mem_of_mem_tail (this h)
theorem exists_get?_of_mem {s : WSeq α} {a} (h : a ∈ s) : ∃ n, some a ∈ get? s n := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α
h : a ∈ s
⊢ ∃ n, some a ∈ get? s n

Next tactic:
apply mem_rec_on h
theorem exists_get?_of_mem {s : WSeq α} {a} (h : a ∈ s) : ∃ n, some a ∈ get? s n := by
  apply mem_rec_on h
  · 

Proof state:
case h1
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α
h : a ∈ s
⊢ ∀ (b : α) (s' : WSeq α), (a = b ∨ ∃ n, some a ∈ get? s' n) → ∃ n, some a ∈ get? (cons b s') n

Next tactic:
intro a' s' h
theorem exists_get?_of_mem {s : WSeq α} {a} (h : a ∈ s) : ∃ n, some a ∈ get? s n := by
  apply mem_rec_on h
  · intro a' s' h
    

Proof state:
case h1
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α
h✝ : a ∈ s
a' : α
s' : WSeq α
h : a = a' ∨ ∃ n, some a ∈ get? s' n
⊢ ∃ n, some a ∈ get? (cons a' s') n

Next tactic:
cases' h with h h
theorem exists_get?_of_mem {s : WSeq α} {a} (h : a ∈ s) : ∃ n, some a ∈ get? s n := by
  apply mem_rec_on h
  · intro a' s' h
    cases' h with h h
    · 

Proof state:
case h1.inl
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α
h✝ : a ∈ s
a' : α
s' : WSeq α
h : a = a'
⊢ ∃ n, some a ∈ get? (cons a' s') n

Next tactic:
exists 0
theorem exists_get?_of_mem {s : WSeq α} {a} (h : a ∈ s) : ∃ n, some a ∈ get? s n := by
  apply mem_rec_on h
  · intro a' s' h
    cases' h with h h
    · exists 0
      

Proof state:
case h1.inl
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α
h✝ : a ∈ s
a' : α
s' : WSeq α
h : a = a'
⊢ some a ∈ get? (cons a' s') 0

Next tactic:
simp only [get?, drop, head_cons]
theorem exists_get?_of_mem {s : WSeq α} {a} (h : a ∈ s) : ∃ n, some a ∈ get? s n := by
  apply mem_rec_on h
  · intro a' s' h
    cases' h with h h
    · exists 0
      simp only [get?, drop, head_cons]
      

Proof state:
case h1.inl
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α
h✝ : a ∈ s
a' : α
s' : WSeq α
h : a = a'
⊢ some a ∈ Computation.pure (some a')

Next tactic:
rw [h]
theorem exists_get?_of_mem {s : WSeq α} {a} (h : a ∈ s) : ∃ n, some a ∈ get? s n := by
  apply mem_rec_on h
  · intro a' s' h
    cases' h with h h
    · exists 0
      simp only [get?, drop, head_cons]
      rw [h]
      

Proof state:
case h1.inl
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α
h✝ : a ∈ s
a' : α
s' : WSeq α
h : a = a'
⊢ some a' ∈ Computation.pure (some a')

Next tactic:
apply ret_mem
theorem exists_get?_of_mem {s : WSeq α} {a} (h : a ∈ s) : ∃ n, some a ∈ get? s n := by
  apply mem_rec_on h
  · intro a' s' h
    cases' h with h h
    · exists 0
      simp only [get?, drop, head_cons]
      rw [h]
      apply ret_mem
    · 

Proof state:
case h1.inr
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α
h✝ : a ∈ s
a' : α
s' : WSeq α
h : ∃ n, some a ∈ get? s' n
⊢ ∃ n, some a ∈ get? (cons a' s') n

Next tactic:
cases' h with n h
theorem exists_get?_of_mem {s : WSeq α} {a} (h : a ∈ s) : ∃ n, some a ∈ get? s n := by
  apply mem_rec_on h
  · intro a' s' h
    cases' h with h h
    · exists 0
      simp only [get?, drop, head_cons]
      rw [h]
      apply ret_mem
    · cases' h with n h
      

Proof state:
case h1.inr.intro
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α
h✝ : a ∈ s
a' : α
s' : WSeq α
n : ℕ
h : some a ∈ get? s' n
⊢ ∃ n, some a ∈ get? (cons a' s') n

Next tactic:
exists n + 1
theorem exists_get?_of_mem {s : WSeq α} {a} (h : a ∈ s) : ∃ n, some a ∈ get? s n := by
  apply mem_rec_on h
  · intro a' s' h
    cases' h with h h
    · exists 0
      simp only [get?, drop, head_cons]
      rw [h]
      apply ret_mem
    · cases' h with n h
      exists n + 1
      -- Porting note: Was `simp [get?]`.
      

Proof state:
case h1.inr.intro
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α
h✝ : a ∈ s
a' : α
s' : WSeq α
n : ℕ
h : some a ∈ get? s' n
⊢ some a ∈ get? (cons a' s') (n + 1)

Next tactic:
simpa [get?]
theorem exists_get?_of_mem {s : WSeq α} {a} (h : a ∈ s) : ∃ n, some a ∈ get? s n := by
  apply mem_rec_on h
  · intro a' s' h
    cases' h with h h
    · exists 0
      simp only [get?, drop, head_cons]
      rw [h]
      apply ret_mem
    · cases' h with n h
      exists n + 1
      -- Porting note: Was `simp [get?]`.
      simpa [get?]
  · 

Proof state:
case h2
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α
h : a ∈ s
⊢ ∀ (s : WSeq α), (∃ n, some a ∈ get? s n) → ∃ n, some a ∈ get? (think s) n

Next tactic:
intro s' h
theorem exists_get?_of_mem {s : WSeq α} {a} (h : a ∈ s) : ∃ n, some a ∈ get? s n := by
  apply mem_rec_on h
  · intro a' s' h
    cases' h with h h
    · exists 0
      simp only [get?, drop, head_cons]
      rw [h]
      apply ret_mem
    · cases' h with n h
      exists n + 1
      -- Porting note: Was `simp [get?]`.
      simpa [get?]
  · intro s' h
    

Proof state:
case h2
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α
h✝ : a ∈ s
s' : WSeq α
h : ∃ n, some a ∈ get? s' n
⊢ ∃ n, some a ∈ get? (think s') n

Next tactic:
cases' h with n h
theorem exists_get?_of_mem {s : WSeq α} {a} (h : a ∈ s) : ∃ n, some a ∈ get? s n := by
  apply mem_rec_on h
  · intro a' s' h
    cases' h with h h
    · exists 0
      simp only [get?, drop, head_cons]
      rw [h]
      apply ret_mem
    · cases' h with n h
      exists n + 1
      -- Porting note: Was `simp [get?]`.
      simpa [get?]
  · intro s' h
    cases' h with n h
    

Proof state:
case h2.intro
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α
h✝ : a ∈ s
s' : WSeq α
n : ℕ
h : some a ∈ get? s' n
⊢ ∃ n, some a ∈ get? (think s') n

Next tactic:
exists n
theorem exists_get?_of_mem {s : WSeq α} {a} (h : a ∈ s) : ∃ n, some a ∈ get? s n := by
  apply mem_rec_on h
  · intro a' s' h
    cases' h with h h
    · exists 0
      simp only [get?, drop, head_cons]
      rw [h]
      apply ret_mem
    · cases' h with n h
      exists n + 1
      -- Porting note: Was `simp [get?]`.
      simpa [get?]
  · intro s' h
    cases' h with n h
    exists n
    

Proof state:
case h2.intro
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α
h✝ : a ∈ s
s' : WSeq α
n : ℕ
h : some a ∈ get? s' n
⊢ some a ∈ get? (think s') n

Next tactic:
simp only [get?, dropn_think, head_think]
theorem exists_get?_of_mem {s : WSeq α} {a} (h : a ∈ s) : ∃ n, some a ∈ get? s n := by
  apply mem_rec_on h
  · intro a' s' h
    cases' h with h h
    · exists 0
      simp only [get?, drop, head_cons]
      rw [h]
      apply ret_mem
    · cases' h with n h
      exists n + 1
      -- Porting note: Was `simp [get?]`.
      simpa [get?]
  · intro s' h
    cases' h with n h
    exists n
    simp only [get?, dropn_think, head_think]
    

Proof state:
case h2.intro
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α
h✝ : a ∈ s
s' : WSeq α
n : ℕ
h : some a ∈ get? s' n
⊢ some a ∈ Computation.think (head (drop s' n))

Next tactic:
apply think_mem h
theorem exists_dropn_of_mem {s : WSeq α} {a} (h : a ∈ s) :
    ∃ n s', some (a, s') ∈ destruct (drop s n) :=
  let ⟨n, h⟩ := exists_get?_of_mem h
  ⟨n, by
    

Proof state:
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α
h✝ : a ∈ s
n : ℕ
h : some a ∈ get? s n
⊢ ∃ s', some (a, s') ∈ destruct (drop s n)

Next tactic:
rcases (head_terminates_iff _).1 ⟨⟨_, h⟩⟩ with ⟨⟨o, om⟩⟩
theorem exists_dropn_of_mem {s : WSeq α} {a} (h : a ∈ s) :
    ∃ n s', some (a, s') ∈ destruct (drop s n) :=
  let ⟨n, h⟩ := exists_get?_of_mem h
  ⟨n, by
    rcases (head_terminates_iff _).1 ⟨⟨_, h⟩⟩ with ⟨⟨o, om⟩⟩
    

Proof state:
case mk.intro
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α
h✝ : a ∈ s
n : ℕ
h : some a ∈ get? s n
o : Option (α × WSeq α)
om : o ∈ destruct (drop s n)
⊢ ∃ s', some (a, s') ∈ destruct (drop s n)

Next tactic:
have := Computation.mem_unique (Computation.mem_map _ om) h
theorem exists_dropn_of_mem {s : WSeq α} {a} (h : a ∈ s) :
    ∃ n s', some (a, s') ∈ destruct (drop s n) :=
  let ⟨n, h⟩ := exists_get?_of_mem h
  ⟨n, by
    rcases (head_terminates_iff _).1 ⟨⟨_, h⟩⟩ with ⟨⟨o, om⟩⟩
    have := Computation.mem_unique (Computation.mem_map _ om) h
    

Proof state:
case mk.intro
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α
h✝ : a ∈ s
n : ℕ
h : some a ∈ get? s n
o : Option (α × WSeq α)
om : o ∈ destruct (drop s n)
this : Prod.fst <$> o = some a
⊢ ∃ s', some (a, s') ∈ destruct (drop s n)

Next tactic:
cases' o with o
theorem exists_dropn_of_mem {s : WSeq α} {a} (h : a ∈ s) :
    ∃ n s', some (a, s') ∈ destruct (drop s n) :=
  let ⟨n, h⟩ := exists_get?_of_mem h
  ⟨n, by
    rcases (head_terminates_iff _).1 ⟨⟨_, h⟩⟩ with ⟨⟨o, om⟩⟩
    have := Computation.mem_unique (Computation.mem_map _ om) h
    cases' o with o
    · 

Proof state:
case mk.intro.none
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α
h✝ : a ∈ s
n : ℕ
h : some a ∈ get? s n
om : none ∈ destruct (drop s n)
this : Prod.fst <$> none = some a
⊢ ∃ s', some (a, s') ∈ destruct (drop s n)

Next tactic:
injection this
theorem exists_dropn_of_mem {s : WSeq α} {a} (h : a ∈ s) :
    ∃ n s', some (a, s') ∈ destruct (drop s n) :=
  let ⟨n, h⟩ := exists_get?_of_mem h
  ⟨n, by
    rcases (head_terminates_iff _).1 ⟨⟨_, h⟩⟩ with ⟨⟨o, om⟩⟩
    have := Computation.mem_unique (Computation.mem_map _ om) h
    cases' o with o
    · injection this
    

Proof state:
case mk.intro.some
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α
h✝ : a ∈ s
n : ℕ
h : some a ∈ get? s n
o : α × WSeq α
om : some o ∈ destruct (drop s n)
this : Prod.fst <$> some o = some a
⊢ ∃ s', some (a, s') ∈ destruct (drop s n)

Next tactic:
injection this with i
theorem exists_dropn_of_mem {s : WSeq α} {a} (h : a ∈ s) :
    ∃ n s', some (a, s') ∈ destruct (drop s n) :=
  let ⟨n, h⟩ := exists_get?_of_mem h
  ⟨n, by
    rcases (head_terminates_iff _).1 ⟨⟨_, h⟩⟩ with ⟨⟨o, om⟩⟩
    have := Computation.mem_unique (Computation.mem_map _ om) h
    cases' o with o
    · injection this
    injection this with i
    

Proof state:
case mk.intro.some
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α
h✝ : a ∈ s
n : ℕ
h : some a ∈ get? s n
o : α × WSeq α
om : some o ∈ destruct (drop s n)
i : o.1 = a
⊢ ∃ s', some (a, s') ∈ destruct (drop s n)

Next tactic:
cases' o with a' s'
theorem exists_dropn_of_mem {s : WSeq α} {a} (h : a ∈ s) :
    ∃ n s', some (a, s') ∈ destruct (drop s n) :=
  let ⟨n, h⟩ := exists_get?_of_mem h
  ⟨n, by
    rcases (head_terminates_iff _).1 ⟨⟨_, h⟩⟩ with ⟨⟨o, om⟩⟩
    have := Computation.mem_unique (Computation.mem_map _ om) h
    cases' o with o
    · injection this
    injection this with i
    cases' o with a' s'
    

Proof state:
case mk.intro.some.mk
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α
h✝ : a ∈ s
n : ℕ
h : some a ∈ get? s n
a' : α
s' : WSeq α
om : some (a', s') ∈ destruct (drop s n)
i : (a', s').1 = a
⊢ ∃ s', some (a, s') ∈ destruct (drop s n)

Next tactic:
dsimp at i
theorem exists_dropn_of_mem {s : WSeq α} {a} (h : a ∈ s) :
    ∃ n s', some (a, s') ∈ destruct (drop s n) :=
  let ⟨n, h⟩ := exists_get?_of_mem h
  ⟨n, by
    rcases (head_terminates_iff _).1 ⟨⟨_, h⟩⟩ with ⟨⟨o, om⟩⟩
    have := Computation.mem_unique (Computation.mem_map _ om) h
    cases' o with o
    · injection this
    injection this with i
    cases' o with a' s'
    dsimp at i
    

Proof state:
case mk.intro.some.mk
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α
h✝ : a ∈ s
n : ℕ
h : some a ∈ get? s n
a' : α
s' : WSeq α
om : some (a', s') ∈ destruct (drop s n)
i : a' = a
⊢ ∃ s', some (a, s') ∈ destruct (drop s n)

Next tactic:
rw [i] at om
theorem exists_dropn_of_mem {s : WSeq α} {a} (h : a ∈ s) :
    ∃ n s', some (a, s') ∈ destruct (drop s n) :=
  let ⟨n, h⟩ := exists_get?_of_mem h
  ⟨n, by
    rcases (head_terminates_iff _).1 ⟨⟨_, h⟩⟩ with ⟨⟨o, om⟩⟩
    have := Computation.mem_unique (Computation.mem_map _ om) h
    cases' o with o
    · injection this
    injection this with i
    cases' o with a' s'
    dsimp at i
    rw [i] at om
    

Proof state:
case mk.intro.some.mk
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α
h✝ : a ∈ s
n : ℕ
h : some a ∈ get? s n
a' : α
s' : WSeq α
om : some (a, s') ∈ destruct (drop s n)
i : a' = a
⊢ ∃ s', some (a, s') ∈ destruct (drop s n)

Next tactic:
exact ⟨_, om⟩
theorem liftRel_dropn_destruct {R : α → β → Prop} {s t} (H : LiftRel R s t) :
    ∀ n, Computation.LiftRel (LiftRelO R (LiftRel R)) (destruct (drop s n)) (destruct (drop t n))
  | 0 => liftRel_destruct H
  | n + 1 => by
    

Proof state:
α : Type u
β : Type v
γ : Type w
R : α → β → Prop
s : WSeq α
t : WSeq β
H : LiftRel R s t
n : ℕ
⊢ Computation.LiftRel (LiftRelO R (LiftRel R)) (destruct (drop s (n + 1))) (destruct (drop t (n + 1)))

Next tactic:
simp only [LiftRelO, drop, Nat.add_eq, add_zero, destruct_tail, tail.aux]
theorem liftRel_dropn_destruct {R : α → β → Prop} {s t} (H : LiftRel R s t) :
    ∀ n, Computation.LiftRel (LiftRelO R (LiftRel R)) (destruct (drop s n)) (destruct (drop t n))
  | 0 => liftRel_destruct H
  | n + 1 => by
    simp only [LiftRelO, drop, Nat.add_eq, add_zero, destruct_tail, tail.aux]
    

Proof state:
α : Type u
β : Type v
γ : Type w
R : α → β → Prop
s : WSeq α
t : WSeq β
H : LiftRel R s t
n : ℕ
⊢ Computation.LiftRel (LiftRelO R (LiftRel R)) (destruct (drop s n) >>= tail.aux) (destruct (drop t n) >>= tail.aux)

Next tactic:
apply liftRel_bind
theorem liftRel_dropn_destruct {R : α → β → Prop} {s t} (H : LiftRel R s t) :
    ∀ n, Computation.LiftRel (LiftRelO R (LiftRel R)) (destruct (drop s n)) (destruct (drop t n))
  | 0 => liftRel_destruct H
  | n + 1 => by
    simp only [LiftRelO, drop, Nat.add_eq, add_zero, destruct_tail, tail.aux]
    apply liftRel_bind
    

Proof state:
case h1
α : Type u
β : Type v
γ : Type w
R : α → β → Prop
s : WSeq α
t : WSeq β
H : LiftRel R s t
n : ℕ
⊢ Computation.LiftRel ?R (destruct (drop s n)) (destruct (drop t n))
case h2
α : Type u
β : Type v
γ : Type w
R : α → β → Prop
s : WSeq α
t : WSeq β
H : LiftRel R s t
n : ℕ
⊢ ∀ {a : Option (α × WSeq α)} {b : Option (β × WSeq β)},
    ?R a b → Computation.LiftRel (LiftRelO R (LiftRel R)) (tail.aux a) (tail.aux b)
case R
α : Type u
β : Type v
γ : Type w
R : α → β → Prop
s : WSeq α
t : WSeq β
H : LiftRel R s t
n : ℕ
⊢ Option (α × WSeq α) → Option (β × WSeq β) → Prop

Next tactic:
apply liftRel_dropn_destruct H n
theorem liftRel_dropn_destruct {R : α → β → Prop} {s t} (H : LiftRel R s t) :
    ∀ n, Computation.LiftRel (LiftRelO R (LiftRel R)) (destruct (drop s n)) (destruct (drop t n))
  | 0 => liftRel_destruct H
  | n + 1 => by
    simp only [LiftRelO, drop, Nat.add_eq, add_zero, destruct_tail, tail.aux]
    apply liftRel_bind
    apply liftRel_dropn_destruct H n
    

Proof state:
case h2
α : Type u
β : Type v
γ : Type w
R : α → β → Prop
s : WSeq α
t : WSeq β
H : LiftRel R s t
n : ℕ
⊢ ∀ {a : Option (α × WSeq α)} {b : Option (β × WSeq β)},
    LiftRelO R (LiftRel R) a b → Computation.LiftRel (LiftRelO R (LiftRel R)) (tail.aux a) (tail.aux b)

Next tactic:
exact fun {a b} o =>
      match a, b, o with
      | none, none, _ => by
        -- Porting note: These 2 theorems should be excluded.
        simp [-liftRel_pure_left, -liftRel_pure_right]
      | some (a, s), some (b, t), ⟨_, h2⟩ => by simp [tail.aux]; apply liftRel_destruct h2
theorem liftRel_dropn_destruct {R : α → β → Prop} {s t} (H : LiftRel R s t) :
    ∀ n, Computation.LiftRel (LiftRelO R (LiftRel R)) (destruct (drop s n)) (destruct (drop t n))
  | 0 => liftRel_destruct H
  | n + 1 => by
    simp only [LiftRelO, drop, Nat.add_eq, add_zero, destruct_tail, tail.aux]
    apply liftRel_bind
    apply liftRel_dropn_destruct H n
    exact fun {a b} o =>
      match a, b, o with
      | none, none, _ => by
        -- Porting note: These 2 theorems should be excluded.
        

Proof state:
α : Type u
β : Type v
γ : Type w
R : α → β → Prop
s : WSeq α
t : WSeq β
H : LiftRel R s t
n : ℕ
a : Option (α × WSeq α)
b : Option (β × WSeq β)
o : LiftRelO R (LiftRel R) a b
x✝ : LiftRelO R (LiftRel R) none none
⊢ Computation.LiftRel (LiftRelO R (LiftRel R)) (tail.aux none) (tail.aux none)

Next tactic:
simp [-liftRel_pure_left, -liftRel_pure_right]
theorem liftRel_dropn_destruct {R : α → β → Prop} {s t} (H : LiftRel R s t) :
    ∀ n, Computation.LiftRel (LiftRelO R (LiftRel R)) (destruct (drop s n)) (destruct (drop t n))
  | 0 => liftRel_destruct H
  | n + 1 => by
    simp only [LiftRelO, drop, Nat.add_eq, add_zero, destruct_tail, tail.aux]
    apply liftRel_bind
    apply liftRel_dropn_destruct H n
    exact fun {a b} o =>
      match a, b, o with
      | none, none, _ => by
        -- Porting note: These 2 theorems should be excluded.
        simp [-liftRel_pure_left, -liftRel_pure_right]
      | some (a, s), some (b, t), ⟨_, h2⟩ => by 

Proof state:
α : Type u
β : Type v
γ : Type w
R : α → β → Prop
s✝ : WSeq α
t✝ : WSeq β
H : LiftRel R s✝ t✝
n : ℕ
a✝ : Option (α × WSeq α)
b✝ : Option (β × WSeq β)
o : LiftRelO R (LiftRel R) a✝ b✝
a : α
s : WSeq α
b : β
t : WSeq β
left✝ : R a b
h2 : LiftRel R s t
⊢ Computation.LiftRel (LiftRelO R (LiftRel R)) (tail.aux (some (a, s))) (tail.aux (some (b, t)))

Next tactic:
simp [tail.aux]
theorem liftRel_dropn_destruct {R : α → β → Prop} {s t} (H : LiftRel R s t) :
    ∀ n, Computation.LiftRel (LiftRelO R (LiftRel R)) (destruct (drop s n)) (destruct (drop t n))
  | 0 => liftRel_destruct H
  | n + 1 => by
    simp only [LiftRelO, drop, Nat.add_eq, add_zero, destruct_tail, tail.aux]
    apply liftRel_bind
    apply liftRel_dropn_destruct H n
    exact fun {a b} o =>
      match a, b, o with
      | none, none, _ => by
        -- Porting note: These 2 theorems should be excluded.
        simp [-liftRel_pure_left, -liftRel_pure_right]
      | some (a, s), some (b, t), ⟨_, h2⟩ => by simp [tail.aux]; 

Proof state:
α : Type u
β : Type v
γ : Type w
R : α → β → Prop
s✝ : WSeq α
t✝ : WSeq β
H : LiftRel R s✝ t✝
n : ℕ
a✝ : Option (α × WSeq α)
b✝ : Option (β × WSeq β)
o : LiftRelO R (LiftRel R) a✝ b✝
a : α
s : WSeq α
b : β
t : WSeq β
left✝ : R a b
h2 : LiftRel R s t
⊢ Computation.LiftRel (LiftRelO R (LiftRel R)) (destruct s) (destruct t)

Next tactic:
apply liftRel_destruct h2
theorem exists_of_liftRel_left {R : α → β → Prop} {s t} (H : LiftRel R s t) {a} (h : a ∈ s) :
    ∃ b, b ∈ t ∧ R a b := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
R : α → β → Prop
s : WSeq α
t : WSeq β
H : LiftRel R s t
a : α
h : a ∈ s
⊢ ∃ b, b ∈ t ∧ R a b

Next tactic:
let ⟨n, h⟩ := exists_get?_of_mem h
theorem exists_of_liftRel_left {R : α → β → Prop} {s t} (H : LiftRel R s t) {a} (h : a ∈ s) :
    ∃ b, b ∈ t ∧ R a b := by
  let ⟨n, h⟩ := exists_get?_of_mem h
  -- Porting note: This line is required to infer metavariables in
  --               `Computation.exists_of_mem_map`.
  

Proof state:
α : Type u
β : Type v
γ : Type w
R : α → β → Prop
s : WSeq α
t : WSeq β
H : LiftRel R s t
a : α
h✝ : a ∈ s
n : ℕ
h : some a ∈ get? s n
⊢ ∃ b, b ∈ t ∧ R a b

Next tactic:
dsimp only [get?, head] at h