l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem destruct_flatten (c : Computation (WSeq α)) : destruct (flatten c) = c >>= destruct := by
  refine'
    Computation.eq_of_bisim
      (fun c1 c2 => c1 = c2 ∨ ∃ c, c1 = destruct (flatten c) ∧ c2 = Computation.bind c destruct) _
      (Or.inr ⟨c, rfl, rfl⟩)
  intro c1 c2 h
  exact
    match c1, c2, h with
    | c, _, Or.inl rfl => by cases c.destruct <;> simp
    | _, _, Or.inr ⟨c, rfl, rfl⟩ => by
      induction' c using Computation.recOn with a c' <;> simp
      · cases (destruct a).destruct <;> 

Proof state:
case h1.inl
α : Type u
β : Type v
γ : Type w
c : Computation (WSeq α)
c1 c2 : Computation (Option (α × WSeq α))
h : c1 = c2 ∨ ∃ c, c1 = destruct (flatten c) ∧ c2 = Computation.bind c destruct
a : WSeq α
val✝ : Option (α × WSeq α)
⊢ match Sum.inl val✝, Sum.inl val✝ with
  | Sum.inl a, Sum.inl a' => a = a'
  | Sum.inr s, Sum.inr s' => s = s' ∨ ∃ c, s = destruct (flatten c) ∧ s' = Computation.bind c destruct
  | x, x_1 => False

Next tactic:
simp
@[simp]
theorem destruct_flatten (c : Computation (WSeq α)) : destruct (flatten c) = c >>= destruct := by
  refine'
    Computation.eq_of_bisim
      (fun c1 c2 => c1 = c2 ∨ ∃ c, c1 = destruct (flatten c) ∧ c2 = Computation.bind c destruct) _
      (Or.inr ⟨c, rfl, rfl⟩)
  intro c1 c2 h
  exact
    match c1, c2, h with
    | c, _, Or.inl rfl => by cases c.destruct <;> simp
    | _, _, Or.inr ⟨c, rfl, rfl⟩ => by
      induction' c using Computation.recOn with a c' <;> simp
      · cases (destruct a).destruct <;> 

Proof state:
case h1.inr
α : Type u
β : Type v
γ : Type w
c : Computation (WSeq α)
c1 c2 : Computation (Option (α × WSeq α))
h : c1 = c2 ∨ ∃ c, c1 = destruct (flatten c) ∧ c2 = Computation.bind c destruct
a : WSeq α
val✝ : Computation (Option (α × WSeq α))
⊢ match Sum.inr val✝, Sum.inr val✝ with
  | Sum.inl a, Sum.inl a' => a = a'
  | Sum.inr s, Sum.inr s' => s = s' ∨ ∃ c, s = destruct (flatten c) ∧ s' = Computation.bind c destruct
  | x, x_1 => False

Next tactic:
simp
@[simp]
theorem destruct_flatten (c : Computation (WSeq α)) : destruct (flatten c) = c >>= destruct := by
  refine'
    Computation.eq_of_bisim
      (fun c1 c2 => c1 = c2 ∨ ∃ c, c1 = destruct (flatten c) ∧ c2 = Computation.bind c destruct) _
      (Or.inr ⟨c, rfl, rfl⟩)
  intro c1 c2 h
  exact
    match c1, c2, h with
    | c, _, Or.inl rfl => by cases c.destruct <;> simp
    | _, _, Or.inr ⟨c, rfl, rfl⟩ => by
      induction' c using Computation.recOn with a c' <;> simp
      · cases (destruct a).destruct <;> simp
      · 

Proof state:
case h2
α : Type u
β : Type v
γ : Type w
c : Computation (WSeq α)
c1 c2 : Computation (Option (α × WSeq α))
h : c1 = c2 ∨ ∃ c, c1 = destruct (flatten c) ∧ c2 = Computation.bind c destruct
c' : Computation (WSeq α)
⊢ destruct (flatten c') = Computation.bind c' destruct ∨
    ∃ c, destruct (flatten c') = destruct (flatten c) ∧ Computation.bind c' destruct = Computation.bind c destruct

Next tactic:
exact Or.inr ⟨c', rfl, rfl⟩
@[simp]
theorem tail_nil : tail (nil : WSeq α) = nil := by 

Proof state:
α : Type u
β : Type v
γ : Type w
⊢ tail nil = nil

Next tactic:
simp [tail]
@[simp]
theorem tail_cons (a : α) (s) : tail (cons a s) = s := by 

Proof state:
α : Type u
β : Type v
γ : Type w
a : α
s : WSeq α
⊢ tail (cons a s) = s

Next tactic:
simp [tail]
@[simp]
theorem tail_think (s : WSeq α) : tail (think s) = (tail s).think := by 

Proof state:
α : Type u
β : Type v
γ : Type w
s : WSeq α
⊢ tail (think s) = think (tail s)

Next tactic:
simp [tail]
@[simp]
theorem dropn_nil (n) : drop (nil : WSeq α) n = nil := by 

Proof state:
α : Type u
β : Type v
γ : Type w
n : ℕ
⊢ drop nil n = nil

Next tactic:
induction n
@[simp]
theorem dropn_nil (n) : drop (nil : WSeq α) n = nil := by induction n <;> 

Proof state:
case zero
α : Type u
β : Type v
γ : Type w
⊢ drop nil Nat.zero = nil

Next tactic:
simp [*, drop]
@[simp]
theorem dropn_nil (n) : drop (nil : WSeq α) n = nil := by induction n <;> 

Proof state:
case succ
α : Type u
β : Type v
γ : Type w
n✝ : ℕ
n_ih✝ : drop nil n✝ = nil
⊢ drop nil (Nat.succ n✝) = nil

Next tactic:
simp [*, drop]
@[simp]
theorem dropn_cons (a : α) (s) (n) : drop (cons a s) (n + 1) = drop s n := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
a : α
s : WSeq α
n : ℕ
⊢ drop (cons a s) (n + 1) = drop s n

Next tactic:
induction n with
  | zero => simp [drop]
  | succ n n_ih =>
    -- Porting note: Was `simp [*, drop]`.
    simp [drop, ← n_ih]
@[simp]
theorem dropn_cons (a : α) (s) (n) : drop (cons a s) (n + 1) = drop s n := by
  induction n with
  

Proof state:
case zero
α : Type u
β : Type v
γ : Type w
a : α
s : WSeq α
⊢ drop (cons a s) (Nat.zero + 1) = drop s Nat.zero

Next tactic:
| zero => simp [drop]
@[simp]
theorem dropn_cons (a : α) (s) (n) : drop (cons a s) (n + 1) = drop s n := by
  induction n with
  | zero => 

Proof state:
case zero
α : Type u
β : Type v
γ : Type w
a : α
s : WSeq α
⊢ drop (cons a s) (Nat.zero + 1) = drop s Nat.zero

Next tactic:
simp [drop]
@[simp]
theorem dropn_cons (a : α) (s) (n) : drop (cons a s) (n + 1) = drop s n := by
  induction n with
  | zero => simp [drop]
  

Proof state:
case succ
α : Type u
β : Type v
γ : Type w
a : α
s : WSeq α
n : ℕ
n_ih : drop (cons a s) (n + 1) = drop s n
⊢ drop (cons a s) (Nat.succ n + 1) = drop s (Nat.succ n)

Next tactic:
| succ n n_ih =>
    -- Porting note: Was `simp [*, drop]`.
    simp [drop, ← n_ih]
@[simp]
theorem dropn_cons (a : α) (s) (n) : drop (cons a s) (n + 1) = drop s n := by
  induction n with
  | zero => simp [drop]
  | succ n n_ih =>
    -- Porting note: Was `simp [*, drop]`.
    

Proof state:
case succ
α : Type u
β : Type v
γ : Type w
a : α
s : WSeq α
n : ℕ
n_ih : drop (cons a s) (n + 1) = drop s n
⊢ drop (cons a s) (Nat.succ n + 1) = drop s (Nat.succ n)

Next tactic:
simp [drop, ← n_ih]
@[simp]
theorem dropn_think (s : WSeq α) (n) : drop (think s) n = (drop s n).think := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
s : WSeq α
n : ℕ
⊢ drop (think s) n = think (drop s n)

Next tactic:
induction n
@[simp]
theorem dropn_think (s : WSeq α) (n) : drop (think s) n = (drop s n).think := by
  induction n <;> 

Proof state:
case zero
α : Type u
β : Type v
γ : Type w
s : WSeq α
⊢ drop (think s) Nat.zero = think (drop s Nat.zero)

Next tactic:
simp [*, drop]
@[simp]
theorem dropn_think (s : WSeq α) (n) : drop (think s) n = (drop s n).think := by
  induction n <;> 

Proof state:
case succ
α : Type u
β : Type v
γ : Type w
s : WSeq α
n✝ : ℕ
n_ih✝ : drop (think s) n✝ = think (drop s n✝)
⊢ drop (think s) (Nat.succ n✝) = think (drop s (Nat.succ n✝))

Next tactic:
simp [*, drop]
theorem dropn_tail (s : WSeq α) (n) : drop (tail s) n = drop s (n + 1) := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
s : WSeq α
n : ℕ
⊢ drop (tail s) n = drop s (n + 1)

Next tactic:
rw [add_comm]
theorem dropn_tail (s : WSeq α) (n) : drop (tail s) n = drop s (n + 1) := by
  rw [add_comm]
  

Proof state:
α : Type u
β : Type v
γ : Type w
s : WSeq α
n : ℕ
⊢ drop (tail s) n = drop s (1 + n)

Next tactic:
symm
theorem dropn_tail (s : WSeq α) (n) : drop (tail s) n = drop s (n + 1) := by
  rw [add_comm]
  symm
  

Proof state:
α : Type u
β : Type v
γ : Type w
s : WSeq α
n : ℕ
⊢ drop s (1 + n) = drop (tail s) n

Next tactic:
apply dropn_add
@[simp]
theorem join_think (S : WSeq (WSeq α)) : join (think S) = think (join S) := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
S : WSeq (WSeq α)
⊢ join (think S) = think (join S)

Next tactic:
simp only [join, think]
@[simp]
theorem join_think (S : WSeq (WSeq α)) : join (think S) = think (join S) := by
  simp only [join, think]
  

Proof state:
α : Type u
β : Type v
γ : Type w
S : WSeq (WSeq α)
⊢ Seq.join
      ((fun o =>
          match o with
          | none => Seq1.ret none
          | some s => (none, s)) <$>
        Seq.cons none S) =
    Seq.cons none
      (Seq.join
        ((fun o =>
            match o with
            | none => Seq1.ret none
            | some s => (none, s)) <$>
          S))

Next tactic:
dsimp only [(· <$> ·)]
@[simp]
theorem join_think (S : WSeq (WSeq α)) : join (think S) = think (join S) := by
  simp only [join, think]
  dsimp only [(· <$> ·)]
  

Proof state:
α : Type u
β : Type v
γ : Type w
S : WSeq (WSeq α)
⊢ Seq.join
      (Seq.map
        (fun o =>
          match o with
          | none => Seq1.ret none
          | some s => (none, s))
        (Seq.cons none S)) =
    Seq.cons none
      (Seq.join
        (Seq.map
          (fun o =>
            match o with
            | none => Seq1.ret none
            | some s => (none, s))
          S))

Next tactic:
simp [join, Seq1.ret]
@[simp]
theorem join_cons (s : WSeq α) (S) : join (cons s S) = think (append s (join S)) := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
s : WSeq α
S : WSeq (WSeq α)
⊢ join (cons s S) = think (append s (join S))

Next tactic:
simp only [join, think]
@[simp]
theorem join_cons (s : WSeq α) (S) : join (cons s S) = think (append s (join S)) := by
  simp only [join, think]
  

Proof state:
α : Type u
β : Type v
γ : Type w
s : WSeq α
S : WSeq (WSeq α)
⊢ Seq.join
      ((fun o =>
          match o with
          | none => Seq1.ret none
          | some s => (none, s)) <$>
        cons s S) =
    Seq.cons none
      (append s
        (Seq.join
          ((fun o =>
              match o with
              | none => Seq1.ret none
              | some s => (none, s)) <$>
            S)))

Next tactic:
dsimp only [(· <$> ·)]
@[simp]
theorem join_cons (s : WSeq α) (S) : join (cons s S) = think (append s (join S)) := by
  simp only [join, think]
  dsimp only [(· <$> ·)]
  

Proof state:
α : Type u
β : Type v
γ : Type w
s : WSeq α
S : WSeq (WSeq α)
⊢ Seq.join
      (Seq.map
        (fun o =>
          match o with
          | none => Seq1.ret none
          | some s => (none, s))
        (cons s S)) =
    Seq.cons none
      (append s
        (Seq.join
          (Seq.map
            (fun o =>
              match o with
              | none => Seq1.ret none
              | some s => (none, s))
            S)))

Next tactic:
simp [join, cons, append]
theorem destruct_tail (s : WSeq α) : destruct (tail s) = destruct s >>= tail.aux := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
s : WSeq α
⊢ destruct (tail s) = destruct s >>= tail.aux

Next tactic:
simp only [tail, destruct_flatten, tail.aux]
theorem destruct_tail (s : WSeq α) : destruct (tail s) = destruct s >>= tail.aux := by
  simp only [tail, destruct_flatten, tail.aux]; 

Proof state:
α : Type u
β : Type v
γ : Type w
s : WSeq α
⊢ (fun o => Option.rec nil Prod.snd o) <$> destruct s >>= destruct = destruct s >>= tail.aux

Next tactic:
rw [← bind_pure_comp, LawfulMonad.bind_assoc]
theorem destruct_tail (s : WSeq α) : destruct (tail s) = destruct s >>= tail.aux := by
  simp only [tail, destruct_flatten, tail.aux]; rw [← bind_pure_comp, LawfulMonad.bind_assoc]
  

Proof state:
α : Type u
β : Type v
γ : Type w
s : WSeq α
⊢ (destruct s >>= fun x => Pure.pure (Option.rec nil Prod.snd x) >>= destruct) = destruct s >>= tail.aux

Next tactic:
apply congr_arg
theorem destruct_tail (s : WSeq α) : destruct (tail s) = destruct s >>= tail.aux := by
  simp only [tail, destruct_flatten, tail.aux]; rw [← bind_pure_comp, LawfulMonad.bind_assoc]
  apply congr_arg; 

Proof state:
case h
α : Type u
β : Type v
γ : Type w
s : WSeq α
⊢ (fun x => Pure.pure (Option.rec nil Prod.snd x) >>= destruct) = tail.aux

Next tactic:
ext1 (_ | ⟨a, s⟩)
theorem destruct_tail (s : WSeq α) : destruct (tail s) = destruct s >>= tail.aux := by
  simp only [tail, destruct_flatten, tail.aux]; rw [← bind_pure_comp, LawfulMonad.bind_assoc]
  apply congr_arg; ext1 (_ | ⟨a, s⟩) <;> 

Proof state:
case h.h.none
α : Type u
β : Type v
γ : Type w
s : WSeq α
⊢ Pure.pure (Option.rec nil Prod.snd none) >>= destruct = tail.aux none

Next tactic:
apply (@pure_bind Computation _ _ _ _ _ _).trans _
theorem destruct_tail (s : WSeq α) : destruct (tail s) = destruct s >>= tail.aux := by
  simp only [tail, destruct_flatten, tail.aux]; rw [← bind_pure_comp, LawfulMonad.bind_assoc]
  apply congr_arg; ext1 (_ | ⟨a, s⟩) <;> 

Proof state:
case h.h.some.mk
α : Type u
β : Type v
γ : Type w
s✝ : WSeq α
a : α
s : WSeq α
⊢ Pure.pure (Option.rec nil Prod.snd (some (a, s))) >>= destruct = tail.aux (some (a, s))

Next tactic:
apply (@pure_bind Computation _ _ _ _ _ _).trans _
theorem destruct_tail (s : WSeq α) : destruct (tail s) = destruct s >>= tail.aux := by
  simp only [tail, destruct_flatten, tail.aux]; rw [← bind_pure_comp, LawfulMonad.bind_assoc]
  apply congr_arg; ext1 (_ | ⟨a, s⟩) <;> apply (@pure_bind Computation _ _ _ _ _ _).trans _ <;> 

Proof state:
α : Type u
β : Type v
γ : Type w
s : WSeq α
⊢ destruct (Option.rec nil Prod.snd none) = tail.aux none

Next tactic:
simp
theorem destruct_tail (s : WSeq α) : destruct (tail s) = destruct s >>= tail.aux := by
  simp only [tail, destruct_flatten, tail.aux]; rw [← bind_pure_comp, LawfulMonad.bind_assoc]
  apply congr_arg; ext1 (_ | ⟨a, s⟩) <;> apply (@pure_bind Computation _ _ _ _ _ _).trans _ <;> 

Proof state:
α : Type u
β : Type v
γ : Type w
s✝ : WSeq α
a : α
s : WSeq α
⊢ destruct (Option.rec nil Prod.snd (some (a, s))) = tail.aux (some (a, s))

Next tactic:
simp
theorem drop.aux_none : ∀ n, @drop.aux α n none = Computation.pure none
  | 0 => rfl
  | n + 1 =>
    show Computation.bind (Computation.pure none) (drop.aux n) = Computation.pure none by
      

Proof state:
α : Type u
β : Type v
γ : Type w
n : ℕ
⊢ Computation.bind (Computation.pure none) (aux n) = Computation.pure none

Next tactic:
rw [ret_bind, drop.aux_none n]
theorem destruct_dropn : ∀ (s : WSeq α) (n), destruct (drop s n) = destruct s >>= drop.aux n
  | s, 0 => (bind_pure' _).symm
  | s, n + 1 => by
    

Proof state:
α : Type u
β : Type v
γ : Type w
s : WSeq α
n : ℕ
⊢ destruct (drop s (n + 1)) = destruct s >>= drop.aux (n + 1)

Next tactic:
rw [← dropn_tail, destruct_dropn _ n, destruct_tail, LawfulMonad.bind_assoc]
theorem destruct_dropn : ∀ (s : WSeq α) (n), destruct (drop s n) = destruct s >>= drop.aux n
  | s, 0 => (bind_pure' _).symm
  | s, n + 1 => by
    rw [← dropn_tail, destruct_dropn _ n, destruct_tail, LawfulMonad.bind_assoc]
    

Proof state:
α : Type u
β : Type v
γ : Type w
s : WSeq α
n : ℕ
⊢ (destruct s >>= fun x => tail.aux x >>= drop.aux n) = destruct s >>= drop.aux (n + 1)

Next tactic:
rfl
theorem head_terminates_of_head_tail_terminates (s : WSeq α) [T : Terminates (head (tail s))] :
    Terminates (head s) :=
  (head_terminates_iff _).2 <| by
    

Proof state:
α : Type u
β : Type v
γ : Type w
s : WSeq α
T : Terminates (head (tail s))
⊢ Terminates (destruct s)

Next tactic:
rcases (head_terminates_iff _).1 T with ⟨⟨a, h⟩⟩
theorem head_terminates_of_head_tail_terminates (s : WSeq α) [T : Terminates (head (tail s))] :
    Terminates (head s) :=
  (head_terminates_iff _).2 <| by
    rcases (head_terminates_iff _).1 T with ⟨⟨a, h⟩⟩
    

Proof state:
case mk.intro
α : Type u
β : Type v
γ : Type w
s : WSeq α
T : Terminates (head (tail s))
a : Option (α × WSeq α)
h : a ∈ destruct (tail s)
⊢ Terminates (destruct s)

Next tactic:
simp? [tail] at h says simp only [tail, destruct_flatten] at h
theorem head_terminates_of_head_tail_terminates (s : WSeq α) [T : Terminates (head (tail s))] :
    Terminates (head s) :=
  (head_terminates_iff _).2 <| by
    rcases (head_terminates_iff _).1 T with ⟨⟨a, h⟩⟩
    simp? [tail] at h says 

Proof state:
case mk.intro
α : Type u
β : Type v
γ : Type w
s : WSeq α
T : Terminates (head (tail s))
a : Option (α × WSeq α)
h : a ∈ destruct (tail s)
⊢ Terminates (destruct s)

Next tactic:
simp only [tail, destruct_flatten] at h
theorem head_terminates_of_head_tail_terminates (s : WSeq α) [T : Terminates (head (tail s))] :
    Terminates (head s) :=
  (head_terminates_iff _).2 <| by
    rcases (head_terminates_iff _).1 T with ⟨⟨a, h⟩⟩
    simp? [tail] at h says simp only [tail, destruct_flatten] at h
    

Proof state:
case mk.intro
α : Type u
β : Type v
γ : Type w
s : WSeq α
T : Terminates (head (tail s))
a : Option (α × WSeq α)
h : a ∈ (fun o => Option.rec nil Prod.snd o) <$> destruct s >>= destruct
⊢ Terminates (destruct s)

Next tactic:
rcases exists_of_mem_bind h with ⟨s', h1, _⟩
theorem head_terminates_of_head_tail_terminates (s : WSeq α) [T : Terminates (head (tail s))] :
    Terminates (head s) :=
  (head_terminates_iff _).2 <| by
    rcases (head_terminates_iff _).1 T with ⟨⟨a, h⟩⟩
    simp? [tail] at h says simp only [tail, destruct_flatten] at h
    rcases exists_of_mem_bind h with ⟨s', h1, _⟩
    

Proof state:
case mk.intro.intro.intro
α : Type u
β : Type v
γ : Type w
s : WSeq α
T : Terminates (head (tail s))
a : Option (α × WSeq α)
h : a ∈ (fun o => Option.rec nil Prod.snd o) <$> destruct s >>= destruct
s' : WSeq α
h1 : s' ∈ (fun o => Option.rec nil Prod.snd o) <$> destruct s
right✝ : a ∈ destruct s'
⊢ Terminates (destruct s)

Next tactic:
unfold Functor.map at h1
theorem head_terminates_of_head_tail_terminates (s : WSeq α) [T : Terminates (head (tail s))] :
    Terminates (head s) :=
  (head_terminates_iff _).2 <| by
    rcases (head_terminates_iff _).1 T with ⟨⟨a, h⟩⟩
    simp? [tail] at h says simp only [tail, destruct_flatten] at h
    rcases exists_of_mem_bind h with ⟨s', h1, _⟩
    unfold Functor.map at h1
    

Proof state:
case mk.intro.intro.intro
α : Type u
β : Type v
γ : Type w
s : WSeq α
T : Terminates (head (tail s))
a : Option (α × WSeq α)
h : a ∈ (fun o => Option.rec nil Prod.snd o) <$> destruct s >>= destruct
s' : WSeq α
h1 : s' ∈ Applicative.toFunctor.1 (fun o => Option.rec nil Prod.snd o) (destruct s)
right✝ : a ∈ destruct s'
⊢ Terminates (destruct s)

Next tactic:
exact
      let ⟨t, h3, _⟩ := Computation.exists_of_mem_map h1
      Computation.terminates_of_mem h3
theorem destruct_some_of_destruct_tail_some {s : WSeq α} {a} (h : some a ∈ destruct (tail s)) :
    ∃ a', some a' ∈ destruct s := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α × WSeq α
h : some a ∈ destruct (tail s)
⊢ ∃ a', some a' ∈ destruct s

Next tactic:
unfold tail Functor.map at h
theorem destruct_some_of_destruct_tail_some {s : WSeq α} {a} (h : some a ∈ destruct (tail s)) :
    ∃ a', some a' ∈ destruct s := by
  unfold tail Functor.map at h; 

Proof state:
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α × WSeq α
h : some a ∈ destruct (flatten (Applicative.toFunctor.1 (fun o => Option.recOn o nil Prod.snd) (destruct s)))
⊢ ∃ a', some a' ∈ destruct s

Next tactic:
simp only [destruct_flatten] at h
theorem destruct_some_of_destruct_tail_some {s : WSeq α} {a} (h : some a ∈ destruct (tail s)) :
    ∃ a', some a' ∈ destruct s := by
  unfold tail Functor.map at h; simp only [destruct_flatten] at h
  

Proof state:
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α × WSeq α
h : some a ∈ Applicative.toFunctor.1 (fun o => Option.rec nil Prod.snd o) (destruct s) >>= destruct
⊢ ∃ a', some a' ∈ destruct s

Next tactic:
rcases exists_of_mem_bind h with ⟨t, tm, td⟩
theorem destruct_some_of_destruct_tail_some {s : WSeq α} {a} (h : some a ∈ destruct (tail s)) :
    ∃ a', some a' ∈ destruct s := by
  unfold tail Functor.map at h; simp only [destruct_flatten] at h
  rcases exists_of_mem_bind h with ⟨t, tm, td⟩; 

Proof state:
case intro.intro
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α × WSeq α
h : some a ∈ Applicative.toFunctor.1 (fun o => Option.rec nil Prod.snd o) (destruct s) >>= destruct
t : WSeq α
tm : t ∈ Applicative.toFunctor.1 (fun o => Option.rec nil Prod.snd o) (destruct s)
td : some a ∈ destruct t
⊢ ∃ a', some a' ∈ destruct s

Next tactic:
clear h
theorem destruct_some_of_destruct_tail_some {s : WSeq α} {a} (h : some a ∈ destruct (tail s)) :
    ∃ a', some a' ∈ destruct s := by
  unfold tail Functor.map at h; simp only [destruct_flatten] at h
  rcases exists_of_mem_bind h with ⟨t, tm, td⟩; clear h
  

Proof state:
case intro.intro
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α × WSeq α
t : WSeq α
tm : t ∈ Applicative.toFunctor.1 (fun o => Option.rec nil Prod.snd o) (destruct s)
td : some a ∈ destruct t
⊢ ∃ a', some a' ∈ destruct s

Next tactic:
rcases Computation.exists_of_mem_map tm with ⟨t', ht', ht2⟩
theorem destruct_some_of_destruct_tail_some {s : WSeq α} {a} (h : some a ∈ destruct (tail s)) :
    ∃ a', some a' ∈ destruct s := by
  unfold tail Functor.map at h; simp only [destruct_flatten] at h
  rcases exists_of_mem_bind h with ⟨t, tm, td⟩; clear h
  rcases Computation.exists_of_mem_map tm with ⟨t', ht', ht2⟩; 

Proof state:
case intro.intro.intro.intro
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α × WSeq α
t : WSeq α
tm : t ∈ Applicative.toFunctor.1 (fun o => Option.rec nil Prod.snd o) (destruct s)
td : some a ∈ destruct t
t' : Option (α × WSeq α)
ht' : t' ∈ destruct s
ht2 : Option.rec nil Prod.snd t' = t
⊢ ∃ a', some a' ∈ destruct s

Next tactic:
clear tm
theorem destruct_some_of_destruct_tail_some {s : WSeq α} {a} (h : some a ∈ destruct (tail s)) :
    ∃ a', some a' ∈ destruct s := by
  unfold tail Functor.map at h; simp only [destruct_flatten] at h
  rcases exists_of_mem_bind h with ⟨t, tm, td⟩; clear h
  rcases Computation.exists_of_mem_map tm with ⟨t', ht', ht2⟩; clear tm
  

Proof state:
case intro.intro.intro.intro
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α × WSeq α
t : WSeq α
td : some a ∈ destruct t
t' : Option (α × WSeq α)
ht' : t' ∈ destruct s
ht2 : Option.rec nil Prod.snd t' = t
⊢ ∃ a', some a' ∈ destruct s

Next tactic:
cases' t' with t'
theorem destruct_some_of_destruct_tail_some {s : WSeq α} {a} (h : some a ∈ destruct (tail s)) :
    ∃ a', some a' ∈ destruct s := by
  unfold tail Functor.map at h; simp only [destruct_flatten] at h
  rcases exists_of_mem_bind h with ⟨t, tm, td⟩; clear h
  rcases Computation.exists_of_mem_map tm with ⟨t', ht', ht2⟩; clear tm
  cases' t' with t' <;> 

Proof state:
case intro.intro.intro.intro.none
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α × WSeq α
t : WSeq α
td : some a ∈ destruct t
ht' : none ∈ destruct s
ht2 : Option.rec nil Prod.snd none = t
⊢ ∃ a', some a' ∈ destruct s

Next tactic:
rw [← ht2] at td
theorem destruct_some_of_destruct_tail_some {s : WSeq α} {a} (h : some a ∈ destruct (tail s)) :
    ∃ a', some a' ∈ destruct s := by
  unfold tail Functor.map at h; simp only [destruct_flatten] at h
  rcases exists_of_mem_bind h with ⟨t, tm, td⟩; clear h
  rcases Computation.exists_of_mem_map tm with ⟨t', ht', ht2⟩; clear tm
  cases' t' with t' <;> 

Proof state:
case intro.intro.intro.intro.some
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α × WSeq α
t : WSeq α
td : some a ∈ destruct t
t' : α × WSeq α
ht' : some t' ∈ destruct s
ht2 : Option.rec nil Prod.snd (some t') = t
⊢ ∃ a', some a' ∈ destruct s

Next tactic:
rw [← ht2] at td
theorem destruct_some_of_destruct_tail_some {s : WSeq α} {a} (h : some a ∈ destruct (tail s)) :
    ∃ a', some a' ∈ destruct s := by
  unfold tail Functor.map at h; simp only [destruct_flatten] at h
  rcases exists_of_mem_bind h with ⟨t, tm, td⟩; clear h
  rcases Computation.exists_of_mem_map tm with ⟨t', ht', ht2⟩; clear tm
  cases' t' with t' <;> rw [← ht2] at td <;> 

Proof state:
case intro.intro.intro.intro.none
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α × WSeq α
t : WSeq α
td : some a ∈ destruct (Option.rec nil Prod.snd none)
ht' : none ∈ destruct s
ht2 : Option.rec nil Prod.snd none = t
⊢ ∃ a', some a' ∈ destruct s

Next tactic:
simp only [destruct_nil] at td
theorem destruct_some_of_destruct_tail_some {s : WSeq α} {a} (h : some a ∈ destruct (tail s)) :
    ∃ a', some a' ∈ destruct s := by
  unfold tail Functor.map at h; simp only [destruct_flatten] at h
  rcases exists_of_mem_bind h with ⟨t, tm, td⟩; clear h
  rcases Computation.exists_of_mem_map tm with ⟨t', ht', ht2⟩; clear tm
  cases' t' with t' <;> rw [← ht2] at td <;> 

Proof state:
case intro.intro.intro.intro.some
α : Type u
β : Type v
γ : Type w
s : WSeq α
a : α × WSeq α
t : WSeq α
t' : α × WSeq α
td : some a ∈ destruct (Option.rec nil Prod.snd (some t'))
ht' : some t' ∈ destruct s
ht2 : Option.rec nil Prod.snd (some t') = t
⊢ ∃ a', some a' ∈ destruct s

Next tactic:
simp only [destruct_nil] at td