l3lab/ntp-mathlib huggingface dataset:
theorem destruct_eq_think {s : Computation α} {s'} : destruct s = Sum.inr s' → s = think s' := by
  dsimp [destruct]
  induction' f0 : s.1 0 with a' <;> intro h
  · 

Proof state:
case none
α : Type u
β : Type v
γ : Type w
s s' : Computation α
f0 : ↑s 0 = none
h :
  (match none with
    | none => Sum.inr (tail s)
    | some a => Sum.inl a) =
    Sum.inr s'
⊢ s = think s'

Next tactic:
injection h with h'
theorem destruct_eq_think {s : Computation α} {s'} : destruct s = Sum.inr s' → s = think s' := by
  dsimp [destruct]
  induction' f0 : s.1 0 with a' <;> intro h
  · injection h with h'
    

Proof state:
case none
α : Type u
β : Type v
γ : Type w
s s' : Computation α
f0 : ↑s 0 = none
h' : tail s = s'
⊢ s = think s'

Next tactic:
rw [← h']
theorem destruct_eq_think {s : Computation α} {s'} : destruct s = Sum.inr s' → s = think s' := by
  dsimp [destruct]
  induction' f0 : s.1 0 with a' <;> intro h
  · injection h with h'
    rw [← h']
    

Proof state:
case none
α : Type u
β : Type v
γ : Type w
s s' : Computation α
f0 : ↑s 0 = none
h' : tail s = s'
⊢ s = think (tail s)

Next tactic:
cases' s with f al
theorem destruct_eq_think {s : Computation α} {s'} : destruct s = Sum.inr s' → s = think s' := by
  dsimp [destruct]
  induction' f0 : s.1 0 with a' <;> intro h
  · injection h with h'
    rw [← h']
    cases' s with f al
    

Proof state:
case none.mk
α : Type u
β : Type v
γ : Type w
s' : Computation α
f : Stream' (Option α)
al : ∀ ⦃n : ℕ⦄ ⦃a : α⦄, f n = some a → f (n + 1) = some a
f0 : ↑{ val := f, property := al } 0 = none
h' : tail { val := f, property := al } = s'
⊢ { val := f, property := al } = think (tail { val := f, property := al })

Next tactic:
apply Subtype.eq
theorem destruct_eq_think {s : Computation α} {s'} : destruct s = Sum.inr s' → s = think s' := by
  dsimp [destruct]
  induction' f0 : s.1 0 with a' <;> intro h
  · injection h with h'
    rw [← h']
    cases' s with f al
    apply Subtype.eq
    

Proof state:
case none.mk.a
α : Type u
β : Type v
γ : Type w
s' : Computation α
f : Stream' (Option α)
al : ∀ ⦃n : ℕ⦄ ⦃a : α⦄, f n = some a → f (n + 1) = some a
f0 : ↑{ val := f, property := al } 0 = none
h' : tail { val := f, property := al } = s'
⊢ ↑{ val := f, property := al } = ↑(think (tail { val := f, property := al }))

Next tactic:
dsimp [think, tail]
theorem destruct_eq_think {s : Computation α} {s'} : destruct s = Sum.inr s' → s = think s' := by
  dsimp [destruct]
  induction' f0 : s.1 0 with a' <;> intro h
  · injection h with h'
    rw [← h']
    cases' s with f al
    apply Subtype.eq
    dsimp [think, tail]
    

Proof state:
case none.mk.a
α : Type u
β : Type v
γ : Type w
s' : Computation α
f : Stream' (Option α)
al : ∀ ⦃n : ℕ⦄ ⦃a : α⦄, f n = some a → f (n + 1) = some a
f0 : ↑{ val := f, property := al } 0 = none
h' : tail { val := f, property := al } = s'
⊢ f = Stream'.cons none (Stream'.tail f)

Next tactic:
rw [← f0]
theorem destruct_eq_think {s : Computation α} {s'} : destruct s = Sum.inr s' → s = think s' := by
  dsimp [destruct]
  induction' f0 : s.1 0 with a' <;> intro h
  · injection h with h'
    rw [← h']
    cases' s with f al
    apply Subtype.eq
    dsimp [think, tail]
    rw [← f0]
    

Proof state:
case none.mk.a
α : Type u
β : Type v
γ : Type w
s' : Computation α
f : Stream' (Option α)
al : ∀ ⦃n : ℕ⦄ ⦃a : α⦄, f n = some a → f (n + 1) = some a
f0 : ↑{ val := f, property := al } 0 = none
h' : tail { val := f, property := al } = s'
⊢ f = Stream'.cons (↑{ val := f, property := al } 0) (Stream'.tail f)

Next tactic:
exact (Stream'.eta f).symm
theorem destruct_eq_think {s : Computation α} {s'} : destruct s = Sum.inr s' → s = think s' := by
  dsimp [destruct]
  induction' f0 : s.1 0 with a' <;> intro h
  · injection h with h'
    rw [← h']
    cases' s with f al
    apply Subtype.eq
    dsimp [think, tail]
    rw [← f0]
    exact (Stream'.eta f).symm
  · 

Proof state:
case some
α : Type u
β : Type v
γ : Type w
s s' : Computation α
a' : α
f0 : ↑s 0 = some a'
h :
  (match some a' with
    | none => Sum.inr (tail s)
    | some a => Sum.inl a) =
    Sum.inr s'
⊢ s = think s'

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

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

Next tactic:
cases' s with f al
@[simp]
theorem tail_think (s : Computation α) : tail (think s) = s := by
  cases' s with f al; 

Proof state:
case mk
α : Type u
β : Type v
γ : Type w
f : Stream' (Option α)
al : ∀ ⦃n : ℕ⦄ ⦃a : α⦄, f n = some a → f (n + 1) = some a
⊢ tail (think { val := f, property := al }) = { val := f, property := al }

Next tactic:
apply Subtype.eq
@[simp]
theorem tail_think (s : Computation α) : tail (think s) = s := by
  cases' s with f al; apply Subtype.eq; 

Proof state:
case mk.a
α : Type u
β : Type v
γ : Type w
f : Stream' (Option α)
al : ∀ ⦃n : ℕ⦄ ⦃a : α⦄, f n = some a → f (n + 1) = some a
⊢ ↑(tail (think { val := f, property := al })) = ↑{ val := f, property := al }

Next tactic:
dsimp [tail, think]
/-- Recursion principle for computations, compare with `List.recOn`. -/
def recOn {C : Computation α → Sort v} (s : Computation α) (h1 : ∀ a, C (pure a))
    (h2 : ∀ s, C (think s)) : C s :=
  match H : destruct s with
  | Sum.inl v => by
    

Proof state:
α : Type u
β : Type v
γ : Type w
C : Computation α → Sort v
s : Computation α
h1 : (a : α) → C (pure a)
h2 : (s : Computation α) → C (think s)
v : α
H : destruct s = Sum.inl v
⊢ C s

Next tactic:
rw [destruct_eq_pure H]
/-- Recursion principle for computations, compare with `List.recOn`. -/
def recOn {C : Computation α → Sort v} (s : Computation α) (h1 : ∀ a, C (pure a))
    (h2 : ∀ s, C (think s)) : C s :=
  match H : destruct s with
  | Sum.inl v => by
    rw [destruct_eq_pure H]
    

Proof state:
α : Type u
β : Type v
γ : Type w
C : Computation α → Sort v
s : Computation α
h1 : (a : α) → C (pure a)
h2 : (s : Computation α) → C (think s)
v : α
H : destruct s = Sum.inl v
⊢ C (pure v)

Next tactic:
apply h1
/-- Recursion principle for computations, compare with `List.recOn`. -/
def recOn {C : Computation α → Sort v} (s : Computation α) (h1 : ∀ a, C (pure a))
    (h2 : ∀ s, C (think s)) : C s :=
  match H : destruct s with
  | Sum.inl v => by
    rw [destruct_eq_pure H]
    apply h1
  | Sum.inr v => match v with
    | ⟨a, s'⟩ => by
      

Proof state:
α : Type u
β : Type v
γ : Type w
C : Computation α → Sort v
s : Computation α
h1 : (a : α) → C (pure a)
h2 : (s : Computation α) → C (think s)
v : Computation α
a : Stream' (Option α)
s' : ∀ ⦃n : ℕ⦄ ⦃a_1 : α⦄, a n = some a_1 → a (n + 1) = some a_1
H : destruct s = Sum.inr { val := a, property := s' }
⊢ C s

Next tactic:
rw [destruct_eq_think H]
/-- Recursion principle for computations, compare with `List.recOn`. -/
def recOn {C : Computation α → Sort v} (s : Computation α) (h1 : ∀ a, C (pure a))
    (h2 : ∀ s, C (think s)) : C s :=
  match H : destruct s with
  | Sum.inl v => by
    rw [destruct_eq_pure H]
    apply h1
  | Sum.inr v => match v with
    | ⟨a, s'⟩ => by
      rw [destruct_eq_think H]
      

Proof state:
α : Type u
β : Type v
γ : Type w
C : Computation α → Sort v
s : Computation α
h1 : (a : α) → C (pure a)
h2 : (s : Computation α) → C (think s)
v : Computation α
a : Stream' (Option α)
s' : ∀ ⦃n : ℕ⦄ ⦃a_1 : α⦄, a n = some a_1 → a (n + 1) = some a_1
H : destruct s = Sum.inr { val := a, property := s' }
⊢ C (think { val := a, property := s' })

Next tactic:
apply h2
/-- `corec f b` is the corecursor for `Computation α` as a coinductive type.
  If `f b = inl a` then `corec f b = pure a`, and if `f b = inl b'` then
  `corec f b = think (corec f b')`. -/
def corec (f : β → Sum α β) (b : β) : Computation α := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
f : β → α ⊕ β
b : β
⊢ Computation α

Next tactic:
refine' ⟨Stream'.corec' (Corec.f f) (Sum.inr b), fun n a' h => _⟩
/-- `corec f b` is the corecursor for `Computation α` as a coinductive type.
  If `f b = inl a` then `corec f b = pure a`, and if `f b = inl b'` then
  `corec f b = think (corec f b')`. -/
def corec (f : β → Sum α β) (b : β) : Computation α := by
  refine' ⟨Stream'.corec' (Corec.f f) (Sum.inr b), fun n a' h => _⟩
  

Proof state:
α : Type u
β : Type v
γ : Type w
f : β → α ⊕ β
b : β
n : ℕ
a' : α
h : Stream'.corec' (Corec.f f) (Sum.inr b) n = some a'
⊢ Stream'.corec' (Corec.f f) (Sum.inr b) (n + 1) = some a'

Next tactic:
rw [Stream'.corec'_eq]
/-- `corec f b` is the corecursor for `Computation α` as a coinductive type.
  If `f b = inl a` then `corec f b = pure a`, and if `f b = inl b'` then
  `corec f b = think (corec f b')`. -/
def corec (f : β → Sum α β) (b : β) : Computation α := by
  refine' ⟨Stream'.corec' (Corec.f f) (Sum.inr b), fun n a' h => _⟩
  rw [Stream'.corec'_eq]
  

Proof state:
α : Type u
β : Type v
γ : Type w
f : β → α ⊕ β
b : β
n : ℕ
a' : α
h : Stream'.corec' (Corec.f f) (Sum.inr b) n = some a'
⊢ Stream'.cons (Corec.f f (Sum.inr b)).1 (Stream'.corec' (Corec.f f) (Corec.f f (Sum.inr b)).2) (n + 1) = some a'

Next tactic:
change Stream'.corec' (Corec.f f) (Corec.f f (Sum.inr b)).2 n = some a'
/-- `corec f b` is the corecursor for `Computation α` as a coinductive type.
  If `f b = inl a` then `corec f b = pure a`, and if `f b = inl b'` then
  `corec f b = think (corec f b')`. -/
def corec (f : β → Sum α β) (b : β) : Computation α := by
  refine' ⟨Stream'.corec' (Corec.f f) (Sum.inr b), fun n a' h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (Sum.inr b)).2 n = some a'
  

Proof state:
α : Type u
β : Type v
γ : Type w
f : β → α ⊕ β
b : β
n : ℕ
a' : α
h : Stream'.corec' (Corec.f f) (Sum.inr b) n = some a'
⊢ Stream'.corec' (Corec.f f) (Corec.f f (Sum.inr b)).2 n = some a'

Next tactic:
revert h
/-- `corec f b` is the corecursor for `Computation α` as a coinductive type.
  If `f b = inl a` then `corec f b = pure a`, and if `f b = inl b'` then
  `corec f b = think (corec f b')`. -/
def corec (f : β → Sum α β) (b : β) : Computation α := by
  refine' ⟨Stream'.corec' (Corec.f f) (Sum.inr b), fun n a' h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (Sum.inr b)).2 n = some a'
  revert h; 

Proof state:
α : Type u
β : Type v
γ : Type w
f : β → α ⊕ β
b : β
n : ℕ
a' : α
⊢ Stream'.corec' (Corec.f f) (Sum.inr b) n = some a' → Stream'.corec' (Corec.f f) (Corec.f f (Sum.inr b)).2 n = some a'

Next tactic:
generalize Sum.inr b = o
/-- `corec f b` is the corecursor for `Computation α` as a coinductive type.
  If `f b = inl a` then `corec f b = pure a`, and if `f b = inl b'` then
  `corec f b = think (corec f b')`. -/
def corec (f : β → Sum α β) (b : β) : Computation α := by
  refine' ⟨Stream'.corec' (Corec.f f) (Sum.inr b), fun n a' h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (Sum.inr b)).2 n = some a'
  revert h; generalize Sum.inr b = o; 

Proof state:
α : Type u
β : Type v
γ : Type w
f : β → α ⊕ β
b : β
n : ℕ
a' : α
o : α ⊕ β
⊢ Stream'.corec' (Corec.f f) o n = some a' → Stream'.corec' (Corec.f f) (Corec.f f o).2 n = some a'

Next tactic:
revert o
/-- `corec f b` is the corecursor for `Computation α` as a coinductive type.
  If `f b = inl a` then `corec f b = pure a`, and if `f b = inl b'` then
  `corec f b = think (corec f b')`. -/
def corec (f : β → Sum α β) (b : β) : Computation α := by
  refine' ⟨Stream'.corec' (Corec.f f) (Sum.inr b), fun n a' h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (Sum.inr b)).2 n = some a'
  revert h; generalize Sum.inr b = o; revert o
  

Proof state:
α : Type u
β : Type v
γ : Type w
f : β → α ⊕ β
b : β
n : ℕ
a' : α
⊢ ∀ (o : α ⊕ β), Stream'.corec' (Corec.f f) o n = some a' → Stream'.corec' (Corec.f f) (Corec.f f o).2 n = some a'

Next tactic:
induction' n with n IH
/-- `corec f b` is the corecursor for `Computation α` as a coinductive type.
  If `f b = inl a` then `corec f b = pure a`, and if `f b = inl b'` then
  `corec f b = think (corec f b')`. -/
def corec (f : β → Sum α β) (b : β) : Computation α := by
  refine' ⟨Stream'.corec' (Corec.f f) (Sum.inr b), fun n a' h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (Sum.inr b)).2 n = some a'
  revert h; generalize Sum.inr b = o; revert o
  induction' n with n IH <;> 

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

Next tactic:
intro o
/-- `corec f b` is the corecursor for `Computation α` as a coinductive type.
  If `f b = inl a` then `corec f b = pure a`, and if `f b = inl b'` then
  `corec f b = think (corec f b')`. -/
def corec (f : β → Sum α β) (b : β) : Computation α := by
  refine' ⟨Stream'.corec' (Corec.f f) (Sum.inr b), fun n a' h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (Sum.inr b)).2 n = some a'
  revert h; generalize Sum.inr b = o; revert o
  induction' n with n IH <;> 

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

Next tactic:
intro o
/-- `corec f b` is the corecursor for `Computation α` as a coinductive type.
  If `f b = inl a` then `corec f b = pure a`, and if `f b = inl b'` then
  `corec f b = think (corec f b')`. -/
def corec (f : β → Sum α β) (b : β) : Computation α := by
  refine' ⟨Stream'.corec' (Corec.f f) (Sum.inr b), fun n a' h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (Sum.inr b)).2 n = some a'
  revert h; generalize Sum.inr b = o; revert o
  induction' n with n IH <;> intro o
  · 

Proof state:
case zero
α : Type u
β : Type v
γ : Type w
f : β → α ⊕ β
b : β
a' : α
o : α ⊕ β
⊢ Stream'.corec' (Corec.f f) o Nat.zero = some a' → Stream'.corec' (Corec.f f) (Corec.f f o).2 Nat.zero = some a'

Next tactic:
change (Corec.f f o).1 = some a' → (Corec.f f (Corec.f f o).2).1 = some a'
/-- `corec f b` is the corecursor for `Computation α` as a coinductive type.
  If `f b = inl a` then `corec f b = pure a`, and if `f b = inl b'` then
  `corec f b = think (corec f b')`. -/
def corec (f : β → Sum α β) (b : β) : Computation α := by
  refine' ⟨Stream'.corec' (Corec.f f) (Sum.inr b), fun n a' h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (Sum.inr b)).2 n = some a'
  revert h; generalize Sum.inr b = o; revert o
  induction' n with n IH <;> intro o
  · change (Corec.f f o).1 = some a' → (Corec.f f (Corec.f f o).2).1 = some a'
    

Proof state:
case zero
α : Type u
β : Type v
γ : Type w
f : β → α ⊕ β
b : β
a' : α
o : α ⊕ β
⊢ (Corec.f f o).1 = some a' → (Corec.f f (Corec.f f o).2).1 = some a'

Next tactic:
cases' o with _ b
/-- `corec f b` is the corecursor for `Computation α` as a coinductive type.
  If `f b = inl a` then `corec f b = pure a`, and if `f b = inl b'` then
  `corec f b = think (corec f b')`. -/
def corec (f : β → Sum α β) (b : β) : Computation α := by
  refine' ⟨Stream'.corec' (Corec.f f) (Sum.inr b), fun n a' h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (Sum.inr b)).2 n = some a'
  revert h; generalize Sum.inr b = o; revert o
  induction' n with n IH <;> intro o
  · change (Corec.f f o).1 = some a' → (Corec.f f (Corec.f f o).2).1 = some a'
    cases' o with _ b <;> 

Proof state:
case zero.inl
α : Type u
β : Type v
γ : Type w
f : β → α ⊕ β
b : β
a' val✝ : α
⊢ (Corec.f f (Sum.inl val✝)).1 = some a' → (Corec.f f (Corec.f f (Sum.inl val✝)).2).1 = some a'

Next tactic:
intro h
/-- `corec f b` is the corecursor for `Computation α` as a coinductive type.
  If `f b = inl a` then `corec f b = pure a`, and if `f b = inl b'` then
  `corec f b = think (corec f b')`. -/
def corec (f : β → Sum α β) (b : β) : Computation α := by
  refine' ⟨Stream'.corec' (Corec.f f) (Sum.inr b), fun n a' h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (Sum.inr b)).2 n = some a'
  revert h; generalize Sum.inr b = o; revert o
  induction' n with n IH <;> intro o
  · change (Corec.f f o).1 = some a' → (Corec.f f (Corec.f f o).2).1 = some a'
    cases' o with _ b <;> 

Proof state:
case zero.inr
α : Type u
β : Type v
γ : Type w
f : β → α ⊕ β
b✝ : β
a' : α
b : β
⊢ (Corec.f f (Sum.inr b)).1 = some a' → (Corec.f f (Corec.f f (Sum.inr b)).2).1 = some a'

Next tactic:
intro h
/-- `corec f b` is the corecursor for `Computation α` as a coinductive type.
  If `f b = inl a` then `corec f b = pure a`, and if `f b = inl b'` then
  `corec f b = think (corec f b')`. -/
def corec (f : β → Sum α β) (b : β) : Computation α := by
  refine' ⟨Stream'.corec' (Corec.f f) (Sum.inr b), fun n a' h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (Sum.inr b)).2 n = some a'
  revert h; generalize Sum.inr b = o; revert o
  induction' n with n IH <;> intro o
  · change (Corec.f f o).1 = some a' → (Corec.f f (Corec.f f o).2).1 = some a'
    cases' o with _ b <;> intro h
    · 

Proof state:
case zero.inl
α : Type u
β : Type v
γ : Type w
f : β → α ⊕ β
b : β
a' val✝ : α
h : (Corec.f f (Sum.inl val✝)).1 = some a'
⊢ (Corec.f f (Corec.f f (Sum.inl val✝)).2).1 = some a'

Next tactic:
exact h
/-- `corec f b` is the corecursor for `Computation α` as a coinductive type.
  If `f b = inl a` then `corec f b = pure a`, and if `f b = inl b'` then
  `corec f b = think (corec f b')`. -/
def corec (f : β → Sum α β) (b : β) : Computation α := by
  refine' ⟨Stream'.corec' (Corec.f f) (Sum.inr b), fun n a' h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (Sum.inr b)).2 n = some a'
  revert h; generalize Sum.inr b = o; revert o
  induction' n with n IH <;> intro o
  · change (Corec.f f o).1 = some a' → (Corec.f f (Corec.f f o).2).1 = some a'
    cases' o with _ b <;> intro h
    · exact h
    

Proof state:
case zero.inr
α : Type u
β : Type v
γ : Type w
f : β → α ⊕ β
b✝ : β
a' : α
b : β
h : (Corec.f f (Sum.inr b)).1 = some a'
⊢ (Corec.f f (Corec.f f (Sum.inr b)).2).1 = some a'

Next tactic:
unfold Corec.f at *
/-- `corec f b` is the corecursor for `Computation α` as a coinductive type.
  If `f b = inl a` then `corec f b = pure a`, and if `f b = inl b'` then
  `corec f b = think (corec f b')`. -/
def corec (f : β → Sum α β) (b : β) : Computation α := by
  refine' ⟨Stream'.corec' (Corec.f f) (Sum.inr b), fun n a' h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (Sum.inr b)).2 n = some a'
  revert h; generalize Sum.inr b = o; revert o
  induction' n with n IH <;> intro o
  · change (Corec.f f o).1 = some a' → (Corec.f f (Corec.f f o).2).1 = some a'
    cases' o with _ b <;> intro h
    · exact h
    unfold Corec.f at *; 

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

Next tactic:
split
/-- `corec f b` is the corecursor for `Computation α` as a coinductive type.
  If `f b = inl a` then `corec f b = pure a`, and if `f b = inl b'` then
  `corec f b = think (corec f b')`. -/
def corec (f : β → Sum α β) (b : β) : Computation α := by
  refine' ⟨Stream'.corec' (Corec.f f) (Sum.inr b), fun n a' h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (Sum.inr b)).2 n = some a'
  revert h; generalize Sum.inr b = o; revert o
  induction' n with n IH <;> intro o
  · change (Corec.f f o).1 = some a' → (Corec.f f (Corec.f f o).2).1 = some a'
    cases' o with _ b <;> intro h
    · exact h
    unfold Corec.f at *; split <;> 

Proof state:
case zero.inr.h_1
α : Type u
β : Type v
γ : Type w
f : β → α ⊕ β
b✝ : β
a' : α
b : β
h :
  (match Sum.inr b with
      | Sum.inl a => (some a, Sum.inl a)
      | Sum.inr b =>
        (match f b with
          | Sum.inl a => some a
          | Sum.inr val => none,
          f b)).1 =
    some a'
x✝ : α ⊕ β
a✝ : α
heq✝ :
  (match Sum.inr b with
      | Sum.inl a => (some a, Sum.inl a)
      | Sum.inr b =>
        (match f b with
          | Sum.inl a => some a
          | Sum.inr val => none,
          f b)).2 =
    Sum.inl a✝
⊢ (some a✝, Sum.inl a✝).1 = some a'

Next tactic:
simp_all
/-- `corec f b` is the corecursor for `Computation α` as a coinductive type.
  If `f b = inl a` then `corec f b = pure a`, and if `f b = inl b'` then
  `corec f b = think (corec f b')`. -/
def corec (f : β → Sum α β) (b : β) : Computation α := by
  refine' ⟨Stream'.corec' (Corec.f f) (Sum.inr b), fun n a' h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (Sum.inr b)).2 n = some a'
  revert h; generalize Sum.inr b = o; revert o
  induction' n with n IH <;> intro o
  · change (Corec.f f o).1 = some a' → (Corec.f f (Corec.f f o).2).1 = some a'
    cases' o with _ b <;> intro h
    · exact h
    unfold Corec.f at *; split <;> 

Proof state:
case zero.inr.h_2
α : Type u
β : Type v
γ : Type w
f : β → α ⊕ β
b✝ : β
a' : α
b : β
h :
  (match Sum.inr b with
      | Sum.inl a => (some a, Sum.inl a)
      | Sum.inr b =>
        (match f b with
          | Sum.inl a => some a
          | Sum.inr val => none,
          f b)).1 =
    some a'
x✝ : α ⊕ β
val✝ : β
heq✝ :
  (match Sum.inr b with
      | Sum.inl a => (some a, Sum.inl a)
      | Sum.inr b =>
        (match f b with
          | Sum.inl a => some a
          | Sum.inr val => none,
          f b)).2 =
    Sum.inr val✝
⊢ (match f val✝ with
        | Sum.inl a => some a
        | Sum.inr val => none,
        f val✝).1 =
    some a'

Next tactic:
simp_all
/-- `corec f b` is the corecursor for `Computation α` as a coinductive type.
  If `f b = inl a` then `corec f b = pure a`, and if `f b = inl b'` then
  `corec f b = think (corec f b')`. -/
def corec (f : β → Sum α β) (b : β) : Computation α := by
  refine' ⟨Stream'.corec' (Corec.f f) (Sum.inr b), fun n a' h => _⟩
  rw [Stream'.corec'_eq]
  change Stream'.corec' (Corec.f f) (Corec.f f (Sum.inr b)).2 n = some a'
  revert h; generalize Sum.inr b = o; revert o
  induction' n with n IH <;> intro o
  · change (Corec.f f o).1 = some a' → (Corec.f f (Corec.f f o).2).1 = some a'
    cases' o with _ b <;> intro h
    · exact h
    unfold Corec.f at *; split <;> simp_all
  · 

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

Next tactic:
rw [Stream'.corec'_eq (Corec.f f) (Corec.f f o).2, Stream'.corec'_eq (Corec.f f) o]