l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem toList_cons (a : α) (s) : toList (cons a s) = (List.cons a <$> toList s).think :=
  destruct_eq_think <| by unfold toList; simp; rw [toList'_map]; simp; 

Proof state:
α : Type u
β : Type v
γ : Type w
a : α
s : WSeq α
⊢ (fun x => a :: x) <$> toList s =
    List.cons a <$>
      Computation.corec
        (fun x =>
          match Seq.destruct x.2 with
          | none => Sum.inl (List.reverse x.1)
          | some (none, s') => Sum.inr (x.1, s')
          | some (some a, s') => Sum.inr (a :: x.1, s'))
        ([], s)

Next tactic:
rfl
theorem toList_ofList (l : List α) : l ∈ toList (ofList l) := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
l : List α
⊢ l ∈ toList ↑l

Next tactic:
induction' l with a l IH
theorem toList_ofList (l : List α) : l ∈ toList (ofList l) := by
  induction' l with a l IH <;> 

Proof state:
case nil
α : Type u
β : Type v
γ : Type w
⊢ [] ∈ toList ↑[]

Next tactic:
simp [ret_mem]
theorem toList_ofList (l : List α) : l ∈ toList (ofList l) := by
  induction' l with a l IH <;> 

Proof state:
case cons
α : Type u
β : Type v
γ : Type w
a : α
l : List α
IH : l ∈ toList ↑l
⊢ a :: l ∈ toList ↑(a :: l)

Next tactic:
simp [ret_mem]
theorem toList_ofList (l : List α) : l ∈ toList (ofList l) := by
  induction' l with a l IH <;> simp [ret_mem]; 

Proof state:
case cons
α : Type u
β : Type v
γ : Type w
a : α
l : List α
IH : l ∈ toList ↑l
⊢ a :: l ∈ Computation.think (List.cons a <$> toList ↑l)

Next tactic:
exact think_mem (Computation.mem_map _ IH)
@[simp]
theorem destruct_ofSeq (s : Seq α) :
    destruct (ofSeq s) = Computation.pure (s.head.map fun a => (a, ofSeq s.tail)) :=
  destruct_eq_pure <| by
    

Proof state:
α : Type u
β : Type v
γ : Type w
s : Seq α
⊢ Computation.destruct (destruct ↑s) = Sum.inl (Option.map (fun a => (a, ↑(Seq.tail s))) (Seq.head s))

Next tactic:
simp only [destruct, Seq.destruct, Option.map_eq_map, ofSeq, Computation.corec_eq, rmap,
      Seq.head]
@[simp]
theorem destruct_ofSeq (s : Seq α) :
    destruct (ofSeq s) = Computation.pure (s.head.map fun a => (a, ofSeq s.tail)) :=
  destruct_eq_pure <| by
    simp only [destruct, Seq.destruct, Option.map_eq_map, ofSeq, Computation.corec_eq, rmap,
      Seq.head]
    

Proof state:
α : Type u
β : Type v
γ : Type w
s : Seq α
⊢ (match
      match Option.map (fun a' => (a', Seq.tail (some <$> s))) (Seq.get? (some <$> s) 0) with
      | none => Sum.inl none
      | some (none, s') => Sum.inr s'
      | some (some a, s') => Sum.inl (some (a, s')) with
    | Sum.inl a => Sum.inl a
    | Sum.inr b =>
      Sum.inr
        (Computation.corec
          (fun s =>
            match Option.map (fun a' => (a', Seq.tail s)) (Seq.get? s 0) with
            | none => Sum.inl none
            | some (none, s') => Sum.inr s'
            | some (some a, s') => Sum.inl (some (a, s')))
          b)) =
    Sum.inl (Option.map (fun a => (a, some <$> Seq.tail s)) (Seq.get? s 0))

Next tactic:
rw [show Seq.get? (some <$> s) 0 = some <$> Seq.get? s 0 by apply Seq.map_get?]
@[simp]
theorem destruct_ofSeq (s : Seq α) :
    destruct (ofSeq s) = Computation.pure (s.head.map fun a => (a, ofSeq s.tail)) :=
  destruct_eq_pure <| by
    simp only [destruct, Seq.destruct, Option.map_eq_map, ofSeq, Computation.corec_eq, rmap,
      Seq.head]
    rw [show Seq.get? (some <$> s) 0 = some <$> Seq.get? s 0 by 

Proof state:
α : Type u
β : Type v
γ : Type w
s : Seq α
⊢ Seq.get? (some <$> s) 0 = some <$> Seq.get? s 0

Next tactic:
apply Seq.map_get?
@[simp]
theorem destruct_ofSeq (s : Seq α) :
    destruct (ofSeq s) = Computation.pure (s.head.map fun a => (a, ofSeq s.tail)) :=
  destruct_eq_pure <| by
    simp only [destruct, Seq.destruct, Option.map_eq_map, ofSeq, Computation.corec_eq, rmap,
      Seq.head]
    rw [show Seq.get? (some <$> s) 0 = some <$> Seq.get? s 0 by apply Seq.map_get?]
    

Proof state:
α : Type u
β : Type v
γ : Type w
s : Seq α
⊢ (match
      match Option.map (fun a' => (a', Seq.tail (some <$> s))) (some <$> Seq.get? s 0) with
      | none => Sum.inl none
      | some (none, s') => Sum.inr s'
      | some (some a, s') => Sum.inl (some (a, s')) with
    | Sum.inl a => Sum.inl a
    | Sum.inr b =>
      Sum.inr
        (Computation.corec
          (fun s =>
            match Option.map (fun a' => (a', Seq.tail s)) (Seq.get? s 0) with
            | none => Sum.inl none
            | some (none, s') => Sum.inr s'
            | some (some a, s') => Sum.inl (some (a, s')))
          b)) =
    Sum.inl (Option.map (fun a => (a, some <$> Seq.tail s)) (Seq.get? s 0))

Next tactic:
cases' Seq.get? s 0 with a
@[simp]
theorem destruct_ofSeq (s : Seq α) :
    destruct (ofSeq s) = Computation.pure (s.head.map fun a => (a, ofSeq s.tail)) :=
  destruct_eq_pure <| by
    simp only [destruct, Seq.destruct, Option.map_eq_map, ofSeq, Computation.corec_eq, rmap,
      Seq.head]
    rw [show Seq.get? (some <$> s) 0 = some <$> Seq.get? s 0 by apply Seq.map_get?]
    cases' Seq.get? s 0 with a
    · 

Proof state:
case none
α : Type u
β : Type v
γ : Type w
s : Seq α
⊢ (match
      match Option.map (fun a' => (a', Seq.tail (some <$> s))) (some <$> none) with
      | none => Sum.inl none
      | some (none, s') => Sum.inr s'
      | some (some a, s') => Sum.inl (some (a, s')) with
    | Sum.inl a => Sum.inl a
    | Sum.inr b =>
      Sum.inr
        (Computation.corec
          (fun s =>
            match Option.map (fun a' => (a', Seq.tail s)) (Seq.get? s 0) with
            | none => Sum.inl none
            | some (none, s') => Sum.inr s'
            | some (some a, s') => Sum.inl (some (a, s')))
          b)) =
    Sum.inl (Option.map (fun a => (a, some <$> Seq.tail s)) none)

Next tactic:
rfl
@[simp]
theorem destruct_ofSeq (s : Seq α) :
    destruct (ofSeq s) = Computation.pure (s.head.map fun a => (a, ofSeq s.tail)) :=
  destruct_eq_pure <| by
    simp only [destruct, Seq.destruct, Option.map_eq_map, ofSeq, Computation.corec_eq, rmap,
      Seq.head]
    rw [show Seq.get? (some <$> s) 0 = some <$> Seq.get? s 0 by apply Seq.map_get?]
    cases' Seq.get? s 0 with a
    · rfl
    

Proof state:
case some
α : Type u
β : Type v
γ : Type w
s : Seq α
a : α
⊢ (match
      match Option.map (fun a' => (a', Seq.tail (some <$> s))) (some <$> some a) with
      | none => Sum.inl none
      | some (none, s') => Sum.inr s'
      | some (some a, s') => Sum.inl (some (a, s')) with
    | Sum.inl a => Sum.inl a
    | Sum.inr b =>
      Sum.inr
        (Computation.corec
          (fun s =>
            match Option.map (fun a' => (a', Seq.tail s)) (Seq.get? s 0) with
            | none => Sum.inl none
            | some (none, s') => Sum.inr s'
            | some (some a, s') => Sum.inl (some (a, s')))
          b)) =
    Sum.inl (Option.map (fun a => (a, some <$> Seq.tail s)) (some a))

Next tactic:
dsimp only [(· <$> ·)]
@[simp]
theorem destruct_ofSeq (s : Seq α) :
    destruct (ofSeq s) = Computation.pure (s.head.map fun a => (a, ofSeq s.tail)) :=
  destruct_eq_pure <| by
    simp only [destruct, Seq.destruct, Option.map_eq_map, ofSeq, Computation.corec_eq, rmap,
      Seq.head]
    rw [show Seq.get? (some <$> s) 0 = some <$> Seq.get? s 0 by apply Seq.map_get?]
    cases' Seq.get? s 0 with a
    · rfl
    dsimp only [(· <$> ·)]
    

Proof state:
case some
α : Type u
β : Type v
γ : Type w
s : Seq α
a : α
⊢ (match
      match Option.map (fun a' => (a', Seq.tail (Seq.map some s))) (Option.map some (some a)) with
      | none => Sum.inl none
      | some (none, s') => Sum.inr s'
      | some (some a, s') => Sum.inl (some (a, s')) with
    | Sum.inl a => Sum.inl a
    | Sum.inr b =>
      Sum.inr
        (Computation.corec
          (fun s =>
            match Option.map (fun a' => (a', Seq.tail s)) (Seq.get? s 0) with
            | none => Sum.inl none
            | some (none, s') => Sum.inr s'
            | some (some a, s') => Sum.inl (some (a, s')))
          b)) =
    Sum.inl (Option.map (fun a => (a, Seq.map some (Seq.tail s))) (some a))

Next tactic:
simp [destruct]
@[simp]
theorem head_ofSeq (s : Seq α) : head (ofSeq s) = Computation.pure s.head := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
s : Seq α
⊢ head ↑s = Computation.pure (Seq.head s)

Next tactic:
simp [head]
@[simp]
theorem head_ofSeq (s : Seq α) : head (ofSeq s) = Computation.pure s.head := by
  simp [head]; 

Proof state:
α : Type u
β : Type v
γ : Type w
s : Seq α
⊢ Computation.pure (Option.map (Prod.fst ∘ fun a => (a, ↑(Seq.tail s))) (Seq.head s)) = Computation.pure (Seq.head s)

Next tactic:
cases Seq.head s
@[simp]
theorem head_ofSeq (s : Seq α) : head (ofSeq s) = Computation.pure s.head := by
  simp [head]; cases Seq.head s <;> 

Proof state:
case none
α : Type u
β : Type v
γ : Type w
s : Seq α
⊢ Computation.pure (Option.map (Prod.fst ∘ fun a => (a, ↑(Seq.tail s))) none) = Computation.pure none

Next tactic:
rfl
@[simp]
theorem head_ofSeq (s : Seq α) : head (ofSeq s) = Computation.pure s.head := by
  simp [head]; cases Seq.head s <;> 

Proof state:
case some
α : Type u
β : Type v
γ : Type w
s : Seq α
val✝ : α
⊢ Computation.pure (Option.map (Prod.fst ∘ fun a => (a, ↑(Seq.tail s))) (some val✝)) = Computation.pure (some val✝)

Next tactic:
rfl
@[simp]
theorem tail_ofSeq (s : Seq α) : tail (ofSeq s) = ofSeq s.tail := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
s : Seq α
⊢ tail ↑s = ↑(Seq.tail s)

Next tactic:
simp [tail]
@[simp]
theorem tail_ofSeq (s : Seq α) : tail (ofSeq s) = ofSeq s.tail := by
  simp [tail]; 

Proof state:
α : Type u
β : Type v
γ : Type w
s : Seq α
⊢ Option.rec nil Prod.snd (Option.map (fun a => (a, ↑(Seq.tail s))) (Seq.head s)) = ↑(Seq.tail s)

Next tactic:
induction' s using Seq.recOn with x s
@[simp]
theorem tail_ofSeq (s : Seq α) : tail (ofSeq s) = ofSeq s.tail := by
  simp [tail]; induction' s using Seq.recOn with x s <;> 

Proof state:
case h1
α : Type u
β : Type v
γ : Type w
⊢ Option.rec nil Prod.snd (Option.map (fun a => (a, ↑(Seq.tail Seq.nil))) (Seq.head Seq.nil)) = ↑(Seq.tail Seq.nil)

Next tactic:
simp [ofSeq]
@[simp]
theorem tail_ofSeq (s : Seq α) : tail (ofSeq s) = ofSeq s.tail := by
  simp [tail]; induction' s using Seq.recOn with x s <;> 

Proof state:
case h2
α : Type u
β : Type v
γ : Type w
x : α
s : Seq α
⊢ Option.rec nil Prod.snd (Option.map (fun a => (a, ↑(Seq.tail (Seq.cons x s)))) (Seq.head (Seq.cons x s))) =
    ↑(Seq.tail (Seq.cons x s))

Next tactic:
simp [ofSeq]
@[simp]
theorem tail_ofSeq (s : Seq α) : tail (ofSeq s) = ofSeq s.tail := by
  simp [tail]; induction' s using Seq.recOn with x s <;> simp [ofSeq]
  · 

Proof state:
case h1
α : Type u
β : Type v
γ : Type w
⊢ nil = some <$> Seq.nil

Next tactic:
rfl
@[simp]
theorem dropn_ofSeq (s : Seq α) : ∀ n, drop (ofSeq s) n = ofSeq (s.drop n)
  | 0 => rfl
  | n + 1 => by
    

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

Next tactic:
simp only [drop, Nat.add_eq, add_zero, Seq.drop]
@[simp]
theorem dropn_ofSeq (s : Seq α) : ∀ n, drop (ofSeq s) n = ofSeq (s.drop n)
  | 0 => rfl
  | n + 1 => by
    simp only [drop, Nat.add_eq, add_zero, Seq.drop]
    

Proof state:
α : Type u
β : Type v
γ : Type w
s : Seq α
n : ℕ
⊢ tail (drop (↑s) n) = ↑(Seq.tail (Seq.drop s n))

Next tactic:
rw [dropn_ofSeq s n, tail_ofSeq]
theorem get?_ofSeq (s : Seq α) (n) : get? (ofSeq s) n = Computation.pure (Seq.get? s n) := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
s : Seq α
n : ℕ
⊢ get? (↑s) n = Computation.pure (Seq.get? s n)

Next tactic:
dsimp [get?]
theorem get?_ofSeq (s : Seq α) (n) : get? (ofSeq s) n = Computation.pure (Seq.get? s n) := by
  dsimp [get?]; 

Proof state:
α : Type u
β : Type v
γ : Type w
s : Seq α
n : ℕ
⊢ head (drop (↑s) n) = Computation.pure (Seq.get? s n)

Next tactic:
rw [dropn_ofSeq, head_ofSeq, Seq.head_dropn]
instance productive_ofSeq (s : Seq α) : Productive (ofSeq s) :=
  ⟨fun n => by 

Proof state:
α : Type u
β : Type v
γ : Type w
s : Seq α
n : ℕ
⊢ Terminates (get? (↑s) n)

Next tactic:
rw [get?_ofSeq]
instance productive_ofSeq (s : Seq α) : Productive (ofSeq s) :=
  ⟨fun n => by rw [get?_ofSeq]; 

Proof state:
α : Type u
β : Type v
γ : Type w
s : Seq α
n : ℕ
⊢ Terminates (Computation.pure (Seq.get? s n))

Next tactic:
infer_instance
theorem toSeq_ofSeq (s : Seq α) : toSeq (ofSeq s) = s := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
s : Seq α
⊢ toSeq ↑s = s

Next tactic:
apply Subtype.eq
theorem toSeq_ofSeq (s : Seq α) : toSeq (ofSeq s) = s := by
  apply Subtype.eq; 

Proof state:
case a
α : Type u
β : Type v
γ : Type w
s : Seq α
⊢ ↑(toSeq ↑s) = ↑s

Next tactic:
funext n
theorem toSeq_ofSeq (s : Seq α) : toSeq (ofSeq s) = s := by
  apply Subtype.eq; funext n
  

Proof state:
case a.h
α : Type u
β : Type v
γ : Type w
s : Seq α
n : ℕ
⊢ ↑(toSeq ↑s) n = ↑s n

Next tactic:
dsimp [toSeq]
theorem toSeq_ofSeq (s : Seq α) : toSeq (ofSeq s) = s := by
  apply Subtype.eq; funext n
  dsimp [toSeq]; 

Proof state:
case a.h
α : Type u
β : Type v
γ : Type w
s : Seq α
n : ℕ
⊢ Computation.get (get? (↑s) n) = ↑s n

Next tactic:
apply get_eq_of_mem
theorem toSeq_ofSeq (s : Seq α) : toSeq (ofSeq s) = s := by
  apply Subtype.eq; funext n
  dsimp [toSeq]; apply get_eq_of_mem
  

Proof state:
case a.h.a
α : Type u
β : Type v
γ : Type w
s : Seq α
n : ℕ
⊢ ↑s n ∈ get? (↑s) n

Next tactic:
rw [get?_ofSeq]
theorem toSeq_ofSeq (s : Seq α) : toSeq (ofSeq s) = s := by
  apply Subtype.eq; funext n
  dsimp [toSeq]; apply get_eq_of_mem
  rw [get?_ofSeq]; 

Proof state:
case a.h.a
α : Type u
β : Type v
γ : Type w
s : Seq α
n : ℕ
⊢ ↑s n ∈ Computation.pure (Seq.get? s n)

Next tactic:
apply ret_mem
@[simp]
theorem map_id (s : WSeq α) : map id s = s := by 

Proof state:
α : Type u
β : Type v
γ : Type w
s : WSeq α
⊢ map id s = s

Next tactic:
simp [map]
@[simp]
theorem map_ret (f : α → β) (a) : map f (ret a) = ret (f a) := by 

Proof state:
α : Type u
β : Type v
γ : Type w
f : α → β
a : α
⊢ map f (ret a) = ret (f a)

Next tactic:
simp [ret]
theorem map_comp (f : α → β) (g : β → γ) (s : WSeq α) : map (g ∘ f) s = map g (map f s) := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
f : α → β
g : β → γ
s : WSeq α
⊢ map (g ∘ f) s = map g (map f s)

Next tactic:
dsimp [map]
theorem map_comp (f : α → β) (g : β → γ) (s : WSeq α) : map (g ∘ f) s = map g (map f s) := by
  dsimp [map]; 

Proof state:
α : Type u
β : Type v
γ : Type w
f : α → β
g : β → γ
s : WSeq α
⊢ Seq.map (Option.map (g ∘ f)) s = Seq.map (Option.map g) (Seq.map (Option.map f) s)

Next tactic:
rw [← Seq.map_comp]
theorem map_comp (f : α → β) (g : β → γ) (s : WSeq α) : map (g ∘ f) s = map g (map f s) := by
  dsimp [map]; rw [← Seq.map_comp]
  

Proof state:
α : Type u
β : Type v
γ : Type w
f : α → β
g : β → γ
s : WSeq α
⊢ Seq.map (Option.map (g ∘ f)) s = Seq.map (Option.map g ∘ Option.map f) s

Next tactic:
apply congr_fun
theorem map_comp (f : α → β) (g : β → γ) (s : WSeq α) : map (g ∘ f) s = map g (map f s) := by
  dsimp [map]; rw [← Seq.map_comp]
  apply congr_fun; 

Proof state:
case h
α : Type u
β : Type v
γ : Type w
f : α → β
g : β → γ
s : WSeq α
⊢ Seq.map (Option.map (g ∘ f)) = fun s => Seq.map (Option.map g ∘ Option.map f) s

Next tactic:
apply congr_arg
theorem map_comp (f : α → β) (g : β → γ) (s : WSeq α) : map (g ∘ f) s = map g (map f s) := by
  dsimp [map]; rw [← Seq.map_comp]
  apply congr_fun; apply congr_arg
  

Proof state:
case h.h
α : Type u
β : Type v
γ : Type w
f : α → β
g : β → γ
s : WSeq α
⊢ Option.map (g ∘ f) = Option.map g ∘ Option.map f

Next tactic:
ext ⟨⟩
theorem map_comp (f : α → β) (g : β → γ) (s : WSeq α) : map (g ∘ f) s = map g (map f s) := by
  dsimp [map]; rw [← Seq.map_comp]
  apply congr_fun; apply congr_arg
  ext ⟨⟩ <;> 

Proof state:
case h.h.h.none.a
α : Type u
β : Type v
γ : Type w
f : α → β
g : β → γ
s : WSeq α
a✝ : γ
⊢ a✝ ∈ Option.map (g ∘ f) none ↔ a✝ ∈ (Option.map g ∘ Option.map f) none

Next tactic:
rfl
theorem map_comp (f : α → β) (g : β → γ) (s : WSeq α) : map (g ∘ f) s = map g (map f s) := by
  dsimp [map]; rw [← Seq.map_comp]
  apply congr_fun; apply congr_arg
  ext ⟨⟩ <;> 

Proof state:
case h.h.h.some.a
α : Type u
β : Type v
γ : Type w
f : α → β
g : β → γ
s : WSeq α
val✝ : α
a✝ : γ
⊢ a✝ ∈ Option.map (g ∘ f) (some val✝) ↔ a✝ ∈ (Option.map g ∘ Option.map f) (some val✝)

Next tactic:
rfl
theorem exists_of_mem_join {a : α} : ∀ {S : WSeq (WSeq α)}, a ∈ join S → ∃ s, s ∈ S ∧ a ∈ s := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
a : α
⊢ ∀ {S : WSeq (WSeq α)}, a ∈ join S → ∃ s, s ∈ S ∧ a ∈ s

Next tactic:
suffices
    ∀ ss : WSeq α,
      a ∈ ss → ∀ s S, append s (join S) = ss → a ∈ append s (join S) → a ∈ s ∨ ∃ s, s ∈ S ∧ a ∈ s
    from fun S h => (this _ h nil S (by simp) (by simp [h])).resolve_left (not_mem_nil _)
theorem exists_of_mem_join {a : α} : ∀ {S : WSeq (WSeq α)}, a ∈ join S → ∃ s, s ∈ S ∧ a ∈ s := by
  suffices
    ∀ ss : WSeq α,
      a ∈ ss → ∀ s S, append s (join S) = ss → a ∈ append s (join S) → a ∈ s ∨ ∃ s, s ∈ S ∧ a ∈ s
    from fun S h => (this _ h nil S (by 

Proof state:
α : Type u
β : Type v
γ : Type w
a : α
this :
  ∀ (ss : WSeq α),
    a ∈ ss →
      ∀ (s : WSeq α) (S : WSeq (WSeq α)), append s (join S) = ss → a ∈ append s (join S) → a ∈ s ∨ ∃ s, s ∈ S ∧ a ∈ s
S : WSeq (WSeq α)
h : a ∈ join S
⊢ append nil (join S) = join S

Next tactic:
simp
theorem exists_of_mem_join {a : α} : ∀ {S : WSeq (WSeq α)}, a ∈ join S → ∃ s, s ∈ S ∧ a ∈ s := by
  suffices
    ∀ ss : WSeq α,
      a ∈ ss → ∀ s S, append s (join S) = ss → a ∈ append s (join S) → a ∈ s ∨ ∃ s, s ∈ S ∧ a ∈ s
    from fun S h => (this _ h nil S (by simp) (by 

Proof state:
α : Type u
β : Type v
γ : Type w
a : α
this :
  ∀ (ss : WSeq α),
    a ∈ ss →
      ∀ (s : WSeq α) (S : WSeq (WSeq α)), append s (join S) = ss → a ∈ append s (join S) → a ∈ s ∨ ∃ s, s ∈ S ∧ a ∈ s
S : WSeq (WSeq α)
h : a ∈ join S
⊢ a ∈ append nil (join S)

Next tactic:
simp [h]
theorem exists_of_mem_join {a : α} : ∀ {S : WSeq (WSeq α)}, a ∈ join S → ∃ s, s ∈ S ∧ a ∈ s := by
  suffices
    ∀ ss : WSeq α,
      a ∈ ss → ∀ s S, append s (join S) = ss → a ∈ append s (join S) → a ∈ s ∨ ∃ s, s ∈ S ∧ a ∈ s
    from fun S h => (this _ h nil S (by simp) (by simp [h])).resolve_left (not_mem_nil _)
  

Proof state:
α : Type u
β : Type v
γ : Type w
a : α
⊢ ∀ (ss : WSeq α),
    a ∈ ss →
      ∀ (s : WSeq α) (S : WSeq (WSeq α)), append s (join S) = ss → a ∈ append s (join S) → a ∈ s ∨ ∃ s, s ∈ S ∧ a ∈ s

Next tactic:
intro ss h
theorem exists_of_mem_join {a : α} : ∀ {S : WSeq (WSeq α)}, a ∈ join S → ∃ s, s ∈ S ∧ a ∈ s := by
  suffices
    ∀ ss : WSeq α,
      a ∈ ss → ∀ s S, append s (join S) = ss → a ∈ append s (join S) → a ∈ s ∨ ∃ s, s ∈ S ∧ a ∈ s
    from fun S h => (this _ h nil S (by simp) (by simp [h])).resolve_left (not_mem_nil _)
  intro ss h; 

Proof state:
α : Type u
β : Type v
γ : Type w
a : α
ss : WSeq α
h : a ∈ ss
⊢ ∀ (s : WSeq α) (S : WSeq (WSeq α)), append s (join S) = ss → a ∈ append s (join S) → a ∈ s ∨ ∃ s, s ∈ S ∧ a ∈ s

Next tactic:
apply mem_rec_on h <;> [intro b ss o; intro ss IH]
theorem exists_of_mem_join {a : α} : ∀ {S : WSeq (WSeq α)}, a ∈ join S → ∃ s, s ∈ S ∧ a ∈ s := by
  suffices
    ∀ ss : WSeq α,
      a ∈ ss → ∀ s S, append s (join S) = ss → a ∈ append s (join S) → a ∈ s ∨ ∃ s, s ∈ S ∧ a ∈ s
    from fun S h => (this _ h nil S (by simp) (by simp [h])).resolve_left (not_mem_nil _)
  intro ss h; 

Proof state:
α : Type u
β : Type v
γ : Type w
a : α
ss : WSeq α
h : a ∈ ss
⊢ ∀ (s : WSeq α) (S : WSeq (WSeq α)), append s (join S) = ss → a ∈ append s (join S) → a ∈ s ∨ ∃ s, s ∈ S ∧ a ∈ s

Next tactic:
apply mem_rec_on h
theorem exists_of_mem_join {a : α} : ∀ {S : WSeq (WSeq α)}, a ∈ join S → ∃ s, s ∈ S ∧ a ∈ s := by
  suffices
    ∀ ss : WSeq α,
      a ∈ ss → ∀ s S, append s (join S) = ss → a ∈ append s (join S) → a ∈ s ∨ ∃ s, s ∈ S ∧ a ∈ s
    from fun S h => (this _ h nil S (by simp) (by simp [h])).resolve_left (not_mem_nil _)
  intro ss h; apply mem_rec_on h <;> [

Proof state:
case h1
α : Type u
β : Type v
γ : Type w
a : α
ss : WSeq α
h : a ∈ ss
⊢ ∀ (b : α) (s' : WSeq α),
    (a = b ∨
        ∀ (s : WSeq α) (S : WSeq (WSeq α)),
          append s (join S) = s' → a ∈ append s (join S) → a ∈ s ∨ ∃ s, s ∈ S ∧ a ∈ s) →
      ∀ (s : WSeq α) (S : WSeq (WSeq α)),
        append s (join S) = cons b s' → a ∈ append s (join S) → a ∈ s ∨ ∃ s, s ∈ S ∧ a ∈ s

Next tactic:
intro b ss o
theorem exists_of_mem_join {a : α} : ∀ {S : WSeq (WSeq α)}, a ∈ join S → ∃ s, s ∈ S ∧ a ∈ s := by
  suffices
    ∀ ss : WSeq α,
      a ∈ ss → ∀ s S, append s (join S) = ss → a ∈ append s (join S) → a ∈ s ∨ ∃ s, s ∈ S ∧ a ∈ s
    from fun S h => (this _ h nil S (by simp) (by simp [h])).resolve_left (not_mem_nil _)
  intro ss h; apply mem_rec_on h <;> [intro b ss o; 

Proof state:
case h2
α : Type u
β : Type v
γ : Type w
a : α
ss : WSeq α
h : a ∈ ss
⊢ ∀ (s : WSeq α),
    (∀ (s_1 : WSeq α) (S : WSeq (WSeq α)),
        append s_1 (join S) = s → a ∈ append s_1 (join S) → a ∈ s_1 ∨ ∃ s, s ∈ S ∧ a ∈ s) →
      ∀ (s_1 : WSeq α) (S : WSeq (WSeq α)),
        append s_1 (join S) = think s → a ∈ append s_1 (join S) → a ∈ s_1 ∨ ∃ s, s ∈ S ∧ a ∈ s

Next tactic:
intro ss IH
theorem exists_of_mem_join {a : α} : ∀ {S : WSeq (WSeq α)}, a ∈ join S → ∃ s, s ∈ S ∧ a ∈ s := by
  suffices
    ∀ ss : WSeq α,
      a ∈ ss → ∀ s S, append s (join S) = ss → a ∈ append s (join S) → a ∈ s ∨ ∃ s, s ∈ S ∧ a ∈ s
    from fun S h => (this _ h nil S (by simp) (by simp [h])).resolve_left (not_mem_nil _)
  intro ss h; apply mem_rec_on h <;> [intro b ss o; intro ss IH] <;> 

Proof state:
case h1
α : Type u
β : Type v
γ : Type w
a : α
ss✝ : WSeq α
h : a ∈ ss✝
b : α
ss : WSeq α
o :
  a = b ∨
    ∀ (s : WSeq α) (S : WSeq (WSeq α)), append s (join S) = ss → a ∈ append s (join S) → a ∈ s ∨ ∃ s, s ∈ S ∧ a ∈ s
⊢ ∀ (s : WSeq α) (S : WSeq (WSeq α)), append s (join S) = cons b ss → a ∈ append s (join S) → a ∈ s ∨ ∃ s, s ∈ S ∧ a ∈ s

Next tactic:
intro s S
theorem exists_of_mem_join {a : α} : ∀ {S : WSeq (WSeq α)}, a ∈ join S → ∃ s, s ∈ S ∧ a ∈ s := by
  suffices
    ∀ ss : WSeq α,
      a ∈ ss → ∀ s S, append s (join S) = ss → a ∈ append s (join S) → a ∈ s ∨ ∃ s, s ∈ S ∧ a ∈ s
    from fun S h => (this _ h nil S (by simp) (by simp [h])).resolve_left (not_mem_nil _)
  intro ss h; apply mem_rec_on h <;> [intro b ss o; intro ss IH] <;> 

Proof state:
case h2
α : Type u
β : Type v
γ : Type w
a : α
ss✝ : WSeq α
h : a ∈ ss✝
ss : WSeq α
IH : ∀ (s : WSeq α) (S : WSeq (WSeq α)), append s (join S) = ss → a ∈ append s (join S) → a ∈ s ∨ ∃ s, s ∈ S ∧ a ∈ s
⊢ ∀ (s : WSeq α) (S : WSeq (WSeq α)), append s (join S) = think ss → a ∈ append s (join S) → a ∈ s ∨ ∃ s, s ∈ S ∧ a ∈ s

Next tactic:
intro s S
theorem exists_of_mem_join {a : α} : ∀ {S : WSeq (WSeq α)}, a ∈ join S → ∃ s, s ∈ S ∧ a ∈ s := by
  suffices
    ∀ ss : WSeq α,
      a ∈ ss → ∀ s S, append s (join S) = ss → a ∈ append s (join S) → a ∈ s ∨ ∃ s, s ∈ S ∧ a ∈ s
    from fun S h => (this _ h nil S (by simp) (by simp [h])).resolve_left (not_mem_nil _)
  intro ss h; apply mem_rec_on h <;> [intro b ss o; intro ss IH] <;> intro s S
  · 

Proof state:
case h1
α : Type u
β : Type v
γ : Type w
a : α
ss✝ : WSeq α
h : a ∈ ss✝
b : α
ss : WSeq α
o :
  a = b ∨
    ∀ (s : WSeq α) (S : WSeq (WSeq α)), append s (join S) = ss → a ∈ append s (join S) → a ∈ s ∨ ∃ s, s ∈ S ∧ a ∈ s
s : WSeq α
S : WSeq (WSeq α)
⊢ append s (join S) = cons b ss → a ∈ append s (join S) → a ∈ s ∨ ∃ s, s ∈ S ∧ a ∈ s

Next tactic:
induction' s using WSeq.recOn with b' s s <;>
      [induction' S using WSeq.recOn with s S S; skip; skip]
theorem exists_of_mem_join {a : α} : ∀ {S : WSeq (WSeq α)}, a ∈ join S → ∃ s, s ∈ S ∧ a ∈ s := by
  suffices
    ∀ ss : WSeq α,
      a ∈ ss → ∀ s S, append s (join S) = ss → a ∈ append s (join S) → a ∈ s ∨ ∃ s, s ∈ S ∧ a ∈ s
    from fun S h => (this _ h nil S (by simp) (by simp [h])).resolve_left (not_mem_nil _)
  intro ss h; apply mem_rec_on h <;> [intro b ss o; intro ss IH] <;> intro s S
  · 

Proof state:
case h1
α : Type u
β : Type v
γ : Type w
a : α
ss✝ : WSeq α
h : a ∈ ss✝
b : α
ss : WSeq α
o :
  a = b ∨
    ∀ (s : WSeq α) (S : WSeq (WSeq α)), append s (join S) = ss → a ∈ append s (join S) → a ∈ s ∨ ∃ s, s ∈ S ∧ a ∈ s
s : WSeq α
S : WSeq (WSeq α)
⊢ append s (join S) = cons b ss → a ∈ append s (join S) → a ∈ s ∨ ∃ s, s ∈ S ∧ a ∈ s

Next tactic:
induction' s using WSeq.recOn with b' s s