l3lab/ntp-mathlib huggingface dataset:
theorem mem_rec_on {C : Seq α → Prop} {a s} (M : a ∈ s)
    (h1 : ∀ b s', a = b ∨ C s' → C (cons b s')) : C s := by
  cases' M with k e; unfold Stream'.get at e
  induction' k with k IH generalizing s
  · have TH : s = cons a (tail s) := by
      apply destruct_eq_cons
      unfold destruct get? Functor.map
      rw [← e]
      rfl
    rw [TH]
    

Proof state:
case intro.zero
α : Type u
β : Type v
γ : Type w
C : Seq α → Prop
a : α
h1 : ∀ (b : α) (s' : Seq α), a = b ∨ C s' → C (cons b s')
s : Seq α
e : some a = ↑s Nat.zero
TH : s = cons a (tail s)
⊢ C (cons a (tail s))

Next tactic:
apply h1 _ _ (Or.inl rfl)
theorem mem_rec_on {C : Seq α → Prop} {a s} (M : a ∈ s)
    (h1 : ∀ b s', a = b ∨ C s' → C (cons b s')) : C s := by
  cases' M with k e; unfold Stream'.get at e
  induction' k with k IH generalizing s
  · have TH : s = cons a (tail s) := by
      apply destruct_eq_cons
      unfold destruct get? Functor.map
      rw [← e]
      rfl
    rw [TH]
    apply h1 _ _ (Or.inl rfl)
  -- porting note: had to reshuffle `intro`
  

Proof state:
case intro.succ
α : Type u
β : Type v
γ : Type w
C : Seq α → Prop
a : α
h1 : ∀ (b : α) (s' : Seq α), a = b ∨ C s' → C (cons b s')
k : ℕ
IH : ∀ {s : Seq α}, some a = ↑s k → C s
s : Seq α
e : some a = ↑s (Nat.succ k)
⊢ C s

Next tactic:
revert e
theorem mem_rec_on {C : Seq α → Prop} {a s} (M : a ∈ s)
    (h1 : ∀ b s', a = b ∨ C s' → C (cons b s')) : C s := by
  cases' M with k e; unfold Stream'.get at e
  induction' k with k IH generalizing s
  · have TH : s = cons a (tail s) := by
      apply destruct_eq_cons
      unfold destruct get? Functor.map
      rw [← e]
      rfl
    rw [TH]
    apply h1 _ _ (Or.inl rfl)
  -- porting note: had to reshuffle `intro`
  revert e; 

Proof state:
case intro.succ
α : Type u
β : Type v
γ : Type w
C : Seq α → Prop
a : α
h1 : ∀ (b : α) (s' : Seq α), a = b ∨ C s' → C (cons b s')
k : ℕ
IH : ∀ {s : Seq α}, some a = ↑s k → C s
s : Seq α
⊢ some a = ↑s (Nat.succ k) → C s

Next tactic:
apply s.recOn _ fun b s' => _
theorem mem_rec_on {C : Seq α → Prop} {a s} (M : a ∈ s)
    (h1 : ∀ b s', a = b ∨ C s' → C (cons b s')) : C s := by
  cases' M with k e; unfold Stream'.get at e
  induction' k with k IH generalizing s
  · have TH : s = cons a (tail s) := by
      apply destruct_eq_cons
      unfold destruct get? Functor.map
      rw [← e]
      rfl
    rw [TH]
    apply h1 _ _ (Or.inl rfl)
  -- porting note: had to reshuffle `intro`
  revert e; apply s.recOn _ fun b s' => _
  · 

Proof state:
α : Type u
β : Type v
γ : Type w
C : Seq α → Prop
a : α
h1 : ∀ (b : α) (s' : Seq α), a = b ∨ C s' → C (cons b s')
k : ℕ
IH : ∀ {s : Seq α}, some a = ↑s k → C s
s : Seq α
⊢ some a = ↑nil (Nat.succ k) → C nil

Next tactic:
intro e
theorem mem_rec_on {C : Seq α → Prop} {a s} (M : a ∈ s)
    (h1 : ∀ b s', a = b ∨ C s' → C (cons b s')) : C s := by
  cases' M with k e; unfold Stream'.get at e
  induction' k with k IH generalizing s
  · have TH : s = cons a (tail s) := by
      apply destruct_eq_cons
      unfold destruct get? Functor.map
      rw [← e]
      rfl
    rw [TH]
    apply h1 _ _ (Or.inl rfl)
  -- porting note: had to reshuffle `intro`
  revert e; apply s.recOn _ fun b s' => _
  · intro e; 

Proof state:
α : Type u
β : Type v
γ : Type w
C : Seq α → Prop
a : α
h1 : ∀ (b : α) (s' : Seq α), a = b ∨ C s' → C (cons b s')
k : ℕ
IH : ∀ {s : Seq α}, some a = ↑s k → C s
s : Seq α
e : some a = ↑nil (Nat.succ k)
⊢ C nil

Next tactic:
injection e
theorem mem_rec_on {C : Seq α → Prop} {a s} (M : a ∈ s)
    (h1 : ∀ b s', a = b ∨ C s' → C (cons b s')) : C s := by
  cases' M with k e; unfold Stream'.get at e
  induction' k with k IH generalizing s
  · have TH : s = cons a (tail s) := by
      apply destruct_eq_cons
      unfold destruct get? Functor.map
      rw [← e]
      rfl
    rw [TH]
    apply h1 _ _ (Or.inl rfl)
  -- porting note: had to reshuffle `intro`
  revert e; apply s.recOn _ fun b s' => _
  · intro e; injection e
  · 

Proof state:
α : Type u
β : Type v
γ : Type w
C : Seq α → Prop
a : α
h1 : ∀ (b : α) (s' : Seq α), a = b ∨ C s' → C (cons b s')
k : ℕ
IH : ∀ {s : Seq α}, some a = ↑s k → C s
s : Seq α
⊢ ∀ (b : α) (s' : Seq α), some a = ↑(cons b s') (Nat.succ k) → C (cons b s')

Next tactic:
intro b s' e
theorem mem_rec_on {C : Seq α → Prop} {a s} (M : a ∈ s)
    (h1 : ∀ b s', a = b ∨ C s' → C (cons b s')) : C s := by
  cases' M with k e; unfold Stream'.get at e
  induction' k with k IH generalizing s
  · have TH : s = cons a (tail s) := by
      apply destruct_eq_cons
      unfold destruct get? Functor.map
      rw [← e]
      rfl
    rw [TH]
    apply h1 _ _ (Or.inl rfl)
  -- porting note: had to reshuffle `intro`
  revert e; apply s.recOn _ fun b s' => _
  · intro e; injection e
  · intro b s' e
    

Proof state:
α : Type u
β : Type v
γ : Type w
C : Seq α → Prop
a : α
h1 : ∀ (b : α) (s' : Seq α), a = b ∨ C s' → C (cons b s')
k : ℕ
IH : ∀ {s : Seq α}, some a = ↑s k → C s
s : Seq α
b : α
s' : Seq α
e : some a = ↑(cons b s') (Nat.succ k)
⊢ C (cons b s')

Next tactic:
have h_eq : (cons b s').val (Nat.succ k) = s'.val k := by cases s'; rfl
theorem mem_rec_on {C : Seq α → Prop} {a s} (M : a ∈ s)
    (h1 : ∀ b s', a = b ∨ C s' → C (cons b s')) : C s := by
  cases' M with k e; unfold Stream'.get at e
  induction' k with k IH generalizing s
  · have TH : s = cons a (tail s) := by
      apply destruct_eq_cons
      unfold destruct get? Functor.map
      rw [← e]
      rfl
    rw [TH]
    apply h1 _ _ (Or.inl rfl)
  -- porting note: had to reshuffle `intro`
  revert e; apply s.recOn _ fun b s' => _
  · intro e; injection e
  · intro b s' e
    have h_eq : (cons b s').val (Nat.succ k) = s'.val k := by 

Proof state:
α : Type u
β : Type v
γ : Type w
C : Seq α → Prop
a : α
h1 : ∀ (b : α) (s' : Seq α), a = b ∨ C s' → C (cons b s')
k : ℕ
IH : ∀ {s : Seq α}, some a = ↑s k → C s
s : Seq α
b : α
s' : Seq α
e : some a = ↑(cons b s') (Nat.succ k)
⊢ ↑(cons b s') (Nat.succ k) = ↑s' k

Next tactic:
cases s'
theorem mem_rec_on {C : Seq α → Prop} {a s} (M : a ∈ s)
    (h1 : ∀ b s', a = b ∨ C s' → C (cons b s')) : C s := by
  cases' M with k e; unfold Stream'.get at e
  induction' k with k IH generalizing s
  · have TH : s = cons a (tail s) := by
      apply destruct_eq_cons
      unfold destruct get? Functor.map
      rw [← e]
      rfl
    rw [TH]
    apply h1 _ _ (Or.inl rfl)
  -- porting note: had to reshuffle `intro`
  revert e; apply s.recOn _ fun b s' => _
  · intro e; injection e
  · intro b s' e
    have h_eq : (cons b s').val (Nat.succ k) = s'.val k := by cases s'; 

Proof state:
case mk
α : Type u
β : Type v
γ : Type w
C : Seq α → Prop
a : α
h1 : ∀ (b : α) (s' : Seq α), a = b ∨ C s' → C (cons b s')
k : ℕ
IH : ∀ {s : Seq α}, some a = ↑s k → C s
s : Seq α
b : α
val✝ : Stream' (Option α)
property✝ : IsSeq val✝
e : some a = ↑(cons b { val := val✝, property := property✝ }) (Nat.succ k)
⊢ ↑(cons b { val := val✝, property := property✝ }) (Nat.succ k) = ↑{ val := val✝, property := property✝ } k

Next tactic:
rfl
theorem mem_rec_on {C : Seq α → Prop} {a s} (M : a ∈ s)
    (h1 : ∀ b s', a = b ∨ C s' → C (cons b s')) : C s := by
  cases' M with k e; unfold Stream'.get at e
  induction' k with k IH generalizing s
  · have TH : s = cons a (tail s) := by
      apply destruct_eq_cons
      unfold destruct get? Functor.map
      rw [← e]
      rfl
    rw [TH]
    apply h1 _ _ (Or.inl rfl)
  -- porting note: had to reshuffle `intro`
  revert e; apply s.recOn _ fun b s' => _
  · intro e; injection e
  · intro b s' e
    have h_eq : (cons b s').val (Nat.succ k) = s'.val k := by cases s'; rfl
    

Proof state:
α : Type u
β : Type v
γ : Type w
C : Seq α → Prop
a : α
h1 : ∀ (b : α) (s' : Seq α), a = b ∨ C s' → C (cons b s')
k : ℕ
IH : ∀ {s : Seq α}, some a = ↑s k → C s
s : Seq α
b : α
s' : Seq α
e : some a = ↑(cons b s') (Nat.succ k)
h_eq : ↑(cons b s') (Nat.succ k) = ↑s' k
⊢ C (cons b s')

Next tactic:
rw [h_eq] at e
theorem mem_rec_on {C : Seq α → Prop} {a s} (M : a ∈ s)
    (h1 : ∀ b s', a = b ∨ C s' → C (cons b s')) : C s := by
  cases' M with k e; unfold Stream'.get at e
  induction' k with k IH generalizing s
  · have TH : s = cons a (tail s) := by
      apply destruct_eq_cons
      unfold destruct get? Functor.map
      rw [← e]
      rfl
    rw [TH]
    apply h1 _ _ (Or.inl rfl)
  -- porting note: had to reshuffle `intro`
  revert e; apply s.recOn _ fun b s' => _
  · intro e; injection e
  · intro b s' e
    have h_eq : (cons b s').val (Nat.succ k) = s'.val k := by cases s'; rfl
    rw [h_eq] at e
    

Proof state:
α : Type u
β : Type v
γ : Type w
C : Seq α → Prop
a : α
h1 : ∀ (b : α) (s' : Seq α), a = b ∨ C s' → C (cons b s')
k : ℕ
IH : ∀ {s : Seq α}, some a = ↑s k → C s
s : Seq α
b : α
s' : Seq α
e : some a = ↑s' k
h_eq : ↑(cons b s') (Nat.succ k) = ↑s' k
⊢ C (cons b s')

Next tactic:
apply h1 _ _ (Or.inr (IH e))
/-- Corecursor for `Seq α` as a coinductive type. Iterates `f` to produce new elements
  of the sequence until `none` is obtained. -/
def corec (f : β → Option (α × β)) (b : β) : Seq α := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
f : β → Option (α × β)
b : β
⊢ Seq α

Next tactic:
refine' ⟨Stream'.corec' (Corec.f f) (some b), fun {n} h => _⟩
/-- Corecursor for `Seq α` as a coinductive type. Iterates `f` to produce new elements
  of the sequence until `none` is obtained. -/
def corec (f : β → Option (α × β)) (b : β) : Seq α := by
  refine' ⟨Stream'.corec' (Corec.f f) (some b), fun {n} h => _⟩
  

Proof state:
α : Type u
β : Type v
γ : Type w
f : β → Option (α × β)
b : β
n : ℕ
h : corec' (Corec.f f) (some b) n = none
⊢ corec' (Corec.f f) (some b) (n + 1) = none

Next tactic:
rw [Stream'.corec'_eq]
/-- Corecursor for `Seq α` as a coinductive type. Iterates `f` to produce new elements
  of the sequence until `none` is obtained. -/
def corec (f : β → Option (α × β)) (b : β) : Seq α := by
  refine' ⟨Stream'.corec' (Corec.f f) (some b), fun {n} h => _⟩
  rw [Stream'.corec'_eq]
  

Proof state:
α : Type u
β : Type v
γ : Type w
f : β → Option (α × β)
b : β
n : ℕ
h : corec' (Corec.f f) (some b) n = none
⊢ ((Corec.f f (some b)).1 :: corec' (Corec.f f) (Corec.f f (some b)).2) (n + 1) = none

Next tactic:
change Stream'.corec' (Corec.f f) (Corec.f f (some b)).2 n = none
/-- Corecursor for `Seq α` as a coinductive type. Iterates `f` to produce new elements
  of the sequence until `none` is obtained. -/
def corec (f : β → Option (α × β)) (b : β) : Seq α := by
  refine' ⟨Stream'.corec' (Corec.f f) (some b), fun {n} h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (some b)).2 n = none
  

Proof state:
α : Type u
β : Type v
γ : Type w
f : β → Option (α × β)
b : β
n : ℕ
h : corec' (Corec.f f) (some b) n = none
⊢ corec' (Corec.f f) (Corec.f f (some b)).2 n = none

Next tactic:
revert h
/-- Corecursor for `Seq α` as a coinductive type. Iterates `f` to produce new elements
  of the sequence until `none` is obtained. -/
def corec (f : β → Option (α × β)) (b : β) : Seq α := by
  refine' ⟨Stream'.corec' (Corec.f f) (some b), fun {n} h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (some b)).2 n = none
  revert h; 

Proof state:
α : Type u
β : Type v
γ : Type w
f : β → Option (α × β)
b : β
n : ℕ
⊢ corec' (Corec.f f) (some b) n = none → corec' (Corec.f f) (Corec.f f (some b)).2 n = none

Next tactic:
generalize some b = o
/-- Corecursor for `Seq α` as a coinductive type. Iterates `f` to produce new elements
  of the sequence until `none` is obtained. -/
def corec (f : β → Option (α × β)) (b : β) : Seq α := by
  refine' ⟨Stream'.corec' (Corec.f f) (some b), fun {n} h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (some b)).2 n = none
  revert h; generalize some b = o; 

Proof state:
α : Type u
β : Type v
γ : Type w
f : β → Option (α × β)
b : β
n : ℕ
o : Option β
⊢ corec' (Corec.f f) o n = none → corec' (Corec.f f) (Corec.f f o).2 n = none

Next tactic:
revert o
/-- Corecursor for `Seq α` as a coinductive type. Iterates `f` to produce new elements
  of the sequence until `none` is obtained. -/
def corec (f : β → Option (α × β)) (b : β) : Seq α := by
  refine' ⟨Stream'.corec' (Corec.f f) (some b), fun {n} h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (some b)).2 n = none
  revert h; generalize some b = o; revert o
  

Proof state:
α : Type u
β : Type v
γ : Type w
f : β → Option (α × β)
b : β
n : ℕ
⊢ ∀ (o : Option β), corec' (Corec.f f) o n = none → corec' (Corec.f f) (Corec.f f o).2 n = none

Next tactic:
induction' n with n IH
/-- Corecursor for `Seq α` as a coinductive type. Iterates `f` to produce new elements
  of the sequence until `none` is obtained. -/
def corec (f : β → Option (α × β)) (b : β) : Seq α := by
  refine' ⟨Stream'.corec' (Corec.f f) (some b), fun {n} h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (some b)).2 n = none
  revert h; generalize some b = o; revert o
  induction' n with n IH <;> 

Proof state:
case zero
α : Type u
β : Type v
γ : Type w
f : β → Option (α × β)
b : β
⊢ ∀ (o : Option β), corec' (Corec.f f) o Nat.zero = none → corec' (Corec.f f) (Corec.f f o).2 Nat.zero = none

Next tactic:
intro o
/-- Corecursor for `Seq α` as a coinductive type. Iterates `f` to produce new elements
  of the sequence until `none` is obtained. -/
def corec (f : β → Option (α × β)) (b : β) : Seq α := by
  refine' ⟨Stream'.corec' (Corec.f f) (some b), fun {n} h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (some b)).2 n = none
  revert h; generalize some b = o; revert o
  induction' n with n IH <;> 

Proof state:
case succ
α : Type u
β : Type v
γ : Type w
f : β → Option (α × β)
b : β
n : ℕ
IH : ∀ (o : Option β), corec' (Corec.f f) o n = none → corec' (Corec.f f) (Corec.f f o).2 n = none
⊢ ∀ (o : Option β), corec' (Corec.f f) o (Nat.succ n) = none → corec' (Corec.f f) (Corec.f f o).2 (Nat.succ n) = none

Next tactic:
intro o
/-- Corecursor for `Seq α` as a coinductive type. Iterates `f` to produce new elements
  of the sequence until `none` is obtained. -/
def corec (f : β → Option (α × β)) (b : β) : Seq α := by
  refine' ⟨Stream'.corec' (Corec.f f) (some b), fun {n} h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (some b)).2 n = none
  revert h; generalize some b = o; revert o
  induction' n with n IH <;> intro o
  · 

Proof state:
case zero
α : Type u
β : Type v
γ : Type w
f : β → Option (α × β)
b : β
o : Option β
⊢ corec' (Corec.f f) o Nat.zero = none → corec' (Corec.f f) (Corec.f f o).2 Nat.zero = none

Next tactic:
change (Corec.f f o).1 = none → (Corec.f f (Corec.f f o).2).1 = none
/-- Corecursor for `Seq α` as a coinductive type. Iterates `f` to produce new elements
  of the sequence until `none` is obtained. -/
def corec (f : β → Option (α × β)) (b : β) : Seq α := by
  refine' ⟨Stream'.corec' (Corec.f f) (some b), fun {n} h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (some b)).2 n = none
  revert h; generalize some b = o; revert o
  induction' n with n IH <;> intro o
  · change (Corec.f f o).1 = none → (Corec.f f (Corec.f f o).2).1 = none
    

Proof state:
case zero
α : Type u
β : Type v
γ : Type w
f : β → Option (α × β)
b : β
o : Option β
⊢ (Corec.f f o).1 = none → (Corec.f f (Corec.f f o).2).1 = none

Next tactic:
cases' o with b
/-- Corecursor for `Seq α` as a coinductive type. Iterates `f` to produce new elements
  of the sequence until `none` is obtained. -/
def corec (f : β → Option (α × β)) (b : β) : Seq α := by
  refine' ⟨Stream'.corec' (Corec.f f) (some b), fun {n} h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (some b)).2 n = none
  revert h; generalize some b = o; revert o
  induction' n with n IH <;> intro o
  · change (Corec.f f o).1 = none → (Corec.f f (Corec.f f o).2).1 = none
    cases' o with b <;> 

Proof state:
case zero.none
α : Type u
β : Type v
γ : Type w
f : β → Option (α × β)
b : β
⊢ (Corec.f f none).1 = none → (Corec.f f (Corec.f f none).2).1 = none

Next tactic:
intro h
/-- Corecursor for `Seq α` as a coinductive type. Iterates `f` to produce new elements
  of the sequence until `none` is obtained. -/
def corec (f : β → Option (α × β)) (b : β) : Seq α := by
  refine' ⟨Stream'.corec' (Corec.f f) (some b), fun {n} h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (some b)).2 n = none
  revert h; generalize some b = o; revert o
  induction' n with n IH <;> intro o
  · change (Corec.f f o).1 = none → (Corec.f f (Corec.f f o).2).1 = none
    cases' o with b <;> 

Proof state:
case zero.some
α : Type u
β : Type v
γ : Type w
f : β → Option (α × β)
b✝ b : β
⊢ (Corec.f f (some b)).1 = none → (Corec.f f (Corec.f f (some b)).2).1 = none

Next tactic:
intro h
/-- Corecursor for `Seq α` as a coinductive type. Iterates `f` to produce new elements
  of the sequence until `none` is obtained. -/
def corec (f : β → Option (α × β)) (b : β) : Seq α := by
  refine' ⟨Stream'.corec' (Corec.f f) (some b), fun {n} h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (some b)).2 n = none
  revert h; generalize some b = o; revert o
  induction' n with n IH <;> intro o
  · change (Corec.f f o).1 = none → (Corec.f f (Corec.f f o).2).1 = none
    cases' o with b <;> intro h
    · 

Proof state:
case zero.none
α : Type u
β : Type v
γ : Type w
f : β → Option (α × β)
b : β
h : (Corec.f f none).1 = none
⊢ (Corec.f f (Corec.f f none).2).1 = none

Next tactic:
rfl
/-- Corecursor for `Seq α` as a coinductive type. Iterates `f` to produce new elements
  of the sequence until `none` is obtained. -/
def corec (f : β → Option (α × β)) (b : β) : Seq α := by
  refine' ⟨Stream'.corec' (Corec.f f) (some b), fun {n} h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (some b)).2 n = none
  revert h; generalize some b = o; revert o
  induction' n with n IH <;> intro o
  · change (Corec.f f o).1 = none → (Corec.f f (Corec.f f o).2).1 = none
    cases' o with b <;> intro h
    · rfl
    

Proof state:
case zero.some
α : Type u
β : Type v
γ : Type w
f : β → Option (α × β)
b✝ b : β
h : (Corec.f f (some b)).1 = none
⊢ (Corec.f f (Corec.f f (some b)).2).1 = none

Next tactic:
dsimp [Corec.f] at h
/-- Corecursor for `Seq α` as a coinductive type. Iterates `f` to produce new elements
  of the sequence until `none` is obtained. -/
def corec (f : β → Option (α × β)) (b : β) : Seq α := by
  refine' ⟨Stream'.corec' (Corec.f f) (some b), fun {n} h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (some b)).2 n = none
  revert h; generalize some b = o; revert o
  induction' n with n IH <;> intro o
  · change (Corec.f f o).1 = none → (Corec.f f (Corec.f f o).2).1 = none
    cases' o with b <;> intro h
    · rfl
    dsimp [Corec.f] at h
    

Proof state:
case zero.some
α : Type u
β : Type v
γ : Type w
f : β → Option (α × β)
b✝ b : β
h :
  (match f b with
      | none => (none, none)
      | some (a, b') => (some a, some b')).1 =
    none
⊢ (Corec.f f (Corec.f f (some b)).2).1 = none

Next tactic:
dsimp [Corec.f]
/-- Corecursor for `Seq α` as a coinductive type. Iterates `f` to produce new elements
  of the sequence until `none` is obtained. -/
def corec (f : β → Option (α × β)) (b : β) : Seq α := by
  refine' ⟨Stream'.corec' (Corec.f f) (some b), fun {n} h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (some b)).2 n = none
  revert h; generalize some b = o; revert o
  induction' n with n IH <;> intro o
  · change (Corec.f f o).1 = none → (Corec.f f (Corec.f f o).2).1 = none
    cases' o with b <;> intro h
    · rfl
    dsimp [Corec.f] at h
    dsimp [Corec.f]
    

Proof state:
case zero.some
α : Type u
β : Type v
γ : Type w
f : β → Option (α × β)
b✝ b : β
h :
  (match f b with
      | none => (none, none)
      | some (a, b') => (some a, some b')).1 =
    none
⊢ (match
        (match f b with
          | none => (none, none)
          | some (a, b') => (some a, some b')).2 with
      | none => (none, none)
      | some b =>
        match f b with
        | none => (none, none)
        | some (a, b') => (some a, some b')).1 =
    none

Next tactic:
revert h
/-- Corecursor for `Seq α` as a coinductive type. Iterates `f` to produce new elements
  of the sequence until `none` is obtained. -/
def corec (f : β → Option (α × β)) (b : β) : Seq α := by
  refine' ⟨Stream'.corec' (Corec.f f) (some b), fun {n} h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (some b)).2 n = none
  revert h; generalize some b = o; revert o
  induction' n with n IH <;> intro o
  · change (Corec.f f o).1 = none → (Corec.f f (Corec.f f o).2).1 = none
    cases' o with b <;> intro h
    · rfl
    dsimp [Corec.f] at h
    dsimp [Corec.f]
    revert h; 

Proof state:
case zero.some
α : Type u
β : Type v
γ : Type w
f : β → Option (α × β)
b✝ b : β
⊢ (match f b with
        | none => (none, none)
        | some (a, b') => (some a, some b')).1 =
      none →
    (match
          (match f b with
            | none => (none, none)
            | some (a, b') => (some a, some b')).2 with
        | none => (none, none)
        | some b =>
          match f b with
          | none => (none, none)
          | some (a, b') => (some a, some b')).1 =
      none

Next tactic:
cases' h₁: f b with s
/-- Corecursor for `Seq α` as a coinductive type. Iterates `f` to produce new elements
  of the sequence until `none` is obtained. -/
def corec (f : β → Option (α × β)) (b : β) : Seq α := by
  refine' ⟨Stream'.corec' (Corec.f f) (some b), fun {n} h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (some b)).2 n = none
  revert h; generalize some b = o; revert o
  induction' n with n IH <;> intro o
  · change (Corec.f f o).1 = none → (Corec.f f (Corec.f f o).2).1 = none
    cases' o with b <;> intro h
    · rfl
    dsimp [Corec.f] at h
    dsimp [Corec.f]
    revert h; cases' h₁: f b with s <;> 

Proof state:
case zero.some.none
α : Type u
β : Type v
γ : Type w
f : β → Option (α × β)
b✝ b : β
h₁ : f b = none
⊢ (match none with
        | none => (none, none)
        | some (a, b') => (some a, some b')).1 =
      none →
    (match
          (match none with
            | none => (none, none)
            | some (a, b') => (some a, some b')).2 with
        | none => (none, none)
        | some b =>
          match f b with
          | none => (none, none)
          | some (a, b') => (some a, some b')).1 =
      none

Next tactic:
intro h
/-- Corecursor for `Seq α` as a coinductive type. Iterates `f` to produce new elements
  of the sequence until `none` is obtained. -/
def corec (f : β → Option (α × β)) (b : β) : Seq α := by
  refine' ⟨Stream'.corec' (Corec.f f) (some b), fun {n} h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (some b)).2 n = none
  revert h; generalize some b = o; revert o
  induction' n with n IH <;> intro o
  · change (Corec.f f o).1 = none → (Corec.f f (Corec.f f o).2).1 = none
    cases' o with b <;> intro h
    · rfl
    dsimp [Corec.f] at h
    dsimp [Corec.f]
    revert h; cases' h₁: f b with s <;> 

Proof state:
case zero.some.some
α : Type u
β : Type v
γ : Type w
f : β → Option (α × β)
b✝ b : β
s : α × β
h₁ : f b = some s
⊢ (match some s with
        | none => (none, none)
        | some (a, b') => (some a, some b')).1 =
      none →
    (match
          (match some s with
            | none => (none, none)
            | some (a, b') => (some a, some b')).2 with
        | none => (none, none)
        | some b =>
          match f b with
          | none => (none, none)
          | some (a, b') => (some a, some b')).1 =
      none

Next tactic:
intro h