l3lab/ntp-mathlib huggingface dataset:
theorem of_results_bind {s : Computation α} {f : α → Computation β} {b k} :
    Results (bind s f) b k → ∃ a m n, Results s a m ∧ Results (f a) b n ∧ k = n + m := by
  induction' k with n IH generalizing s <;> apply recOn s (fun a => _) fun s' => _ <;> 

Proof state:
α : Type u
β : Type v
γ : Type w
f : α → Computation β
b : β
s : Computation α
⊢ ∀ (s' : Computation α),
    Results (bind (think s') f) b Nat.zero → ∃ a m n, Results (think s') a m ∧ Results (f a) b n ∧ Nat.zero = n + m

Next tactic:
intro e h
theorem of_results_bind {s : Computation α} {f : α → Computation β} {b k} :
    Results (bind s f) b k → ∃ a m n, Results s a m ∧ Results (f a) b n ∧ k = n + m := by
  induction' k with n IH generalizing s <;> apply recOn s (fun a => _) fun s' => _ <;> 

Proof state:
α : Type u
β : Type v
γ : Type w
f : α → Computation β
b : β
n : ℕ
IH : ∀ {s : Computation α}, Results (bind s f) b n → ∃ a m n_1, Results s a m ∧ Results (f a) b n_1 ∧ n = n_1 + m
s : Computation α
⊢ ∀ (a : α),
    Results (bind (pure a) f) b (Nat.succ n) →
      ∃ a_2 m n_1, Results (pure a) a_2 m ∧ Results (f a_2) b n_1 ∧ Nat.succ n = n_1 + m

Next tactic:
intro e h
theorem of_results_bind {s : Computation α} {f : α → Computation β} {b k} :
    Results (bind s f) b k → ∃ a m n, Results s a m ∧ Results (f a) b n ∧ k = n + m := by
  induction' k with n IH generalizing s <;> apply recOn s (fun a => _) fun s' => _ <;> 

Proof state:
α : Type u
β : Type v
γ : Type w
f : α → Computation β
b : β
n : ℕ
IH : ∀ {s : Computation α}, Results (bind s f) b n → ∃ a m n_1, Results s a m ∧ Results (f a) b n_1 ∧ n = n_1 + m
s : Computation α
⊢ ∀ (s' : Computation α),
    Results (bind (think s') f) b (Nat.succ n) →
      ∃ a m n_1, Results (think s') a m ∧ Results (f a) b n_1 ∧ Nat.succ n = n_1 + m

Next tactic:
intro e h
theorem of_results_bind {s : Computation α} {f : α → Computation β} {b k} :
    Results (bind s f) b k → ∃ a m n, Results s a m ∧ Results (f a) b n ∧ k = n + m := by
  induction' k with n IH generalizing s <;> apply recOn s (fun a => _) fun s' => _ <;> intro e h
  · 

Proof state:
α : Type u
β : Type v
γ : Type w
f : α → Computation β
b : β
s : Computation α
e : α
h : Results (bind (pure e) f) b Nat.zero
⊢ ∃ a m n, Results (pure e) a m ∧ Results (f a) b n ∧ Nat.zero = n + m

Next tactic:
simp only [ret_bind, Nat.zero_eq] at h
theorem of_results_bind {s : Computation α} {f : α → Computation β} {b k} :
    Results (bind s f) b k → ∃ a m n, Results s a m ∧ Results (f a) b n ∧ k = n + m := by
  induction' k with n IH generalizing s <;> apply recOn s (fun a => _) fun s' => _ <;> intro e h
  · simp only [ret_bind, Nat.zero_eq] at h
    

Proof state:
α : Type u
β : Type v
γ : Type w
f : α → Computation β
b : β
s : Computation α
e : α
h : Results (f e) b 0
⊢ ∃ a m n, Results (pure e) a m ∧ Results (f a) b n ∧ Nat.zero = n + m

Next tactic:
refine' ⟨e, _, _, results_pure _, h, rfl⟩
theorem of_results_bind {s : Computation α} {f : α → Computation β} {b k} :
    Results (bind s f) b k → ∃ a m n, Results s a m ∧ Results (f a) b n ∧ k = n + m := by
  induction' k with n IH generalizing s <;> apply recOn s (fun a => _) fun s' => _ <;> intro e h
  · simp only [ret_bind, Nat.zero_eq] at h
    refine' ⟨e, _, _, results_pure _, h, rfl⟩
  · 

Proof state:
α : Type u
β : Type v
γ : Type w
f : α → Computation β
b : β
s e : Computation α
h : Results (bind (think e) f) b Nat.zero
⊢ ∃ a m n, Results (think e) a m ∧ Results (f a) b n ∧ Nat.zero = n + m

Next tactic:
have := congr_arg head (eq_thinkN h)
theorem of_results_bind {s : Computation α} {f : α → Computation β} {b k} :
    Results (bind s f) b k → ∃ a m n, Results s a m ∧ Results (f a) b n ∧ k = n + m := by
  induction' k with n IH generalizing s <;> apply recOn s (fun a => _) fun s' => _ <;> intro e h
  · simp only [ret_bind, Nat.zero_eq] at h
    refine' ⟨e, _, _, results_pure _, h, rfl⟩
  · have := congr_arg head (eq_thinkN h)
    

Proof state:
α : Type u
β : Type v
γ : Type w
f : α → Computation β
b : β
s e : Computation α
h : Results (bind (think e) f) b Nat.zero
this : head (bind (think e) f) = head (thinkN (pure b) Nat.zero)
⊢ ∃ a m n, Results (think e) a m ∧ Results (f a) b n ∧ Nat.zero = n + m

Next tactic:
contradiction
theorem of_results_bind {s : Computation α} {f : α → Computation β} {b k} :
    Results (bind s f) b k → ∃ a m n, Results s a m ∧ Results (f a) b n ∧ k = n + m := by
  induction' k with n IH generalizing s <;> apply recOn s (fun a => _) fun s' => _ <;> intro e h
  · simp only [ret_bind, Nat.zero_eq] at h
    refine' ⟨e, _, _, results_pure _, h, rfl⟩
  · have := congr_arg head (eq_thinkN h)
    contradiction
  · 

Proof state:
α : Type u
β : Type v
γ : Type w
f : α → Computation β
b : β
n : ℕ
IH : ∀ {s : Computation α}, Results (bind s f) b n → ∃ a m n_1, Results s a m ∧ Results (f a) b n_1 ∧ n = n_1 + m
s : Computation α
e : α
h : Results (bind (pure e) f) b (Nat.succ n)
⊢ ∃ a m n_1, Results (pure e) a m ∧ Results (f a) b n_1 ∧ Nat.succ n = n_1 + m

Next tactic:
simp only [ret_bind] at h
theorem of_results_bind {s : Computation α} {f : α → Computation β} {b k} :
    Results (bind s f) b k → ∃ a m n, Results s a m ∧ Results (f a) b n ∧ k = n + m := by
  induction' k with n IH generalizing s <;> apply recOn s (fun a => _) fun s' => _ <;> intro e h
  · simp only [ret_bind, Nat.zero_eq] at h
    refine' ⟨e, _, _, results_pure _, h, rfl⟩
  · have := congr_arg head (eq_thinkN h)
    contradiction
  · simp only [ret_bind] at h
    

Proof state:
α : Type u
β : Type v
γ : Type w
f : α → Computation β
b : β
n : ℕ
IH : ∀ {s : Computation α}, Results (bind s f) b n → ∃ a m n_1, Results s a m ∧ Results (f a) b n_1 ∧ n = n_1 + m
s : Computation α
e : α
h : Results (f e) b (Nat.succ n)
⊢ ∃ a m n_1, Results (pure e) a m ∧ Results (f a) b n_1 ∧ Nat.succ n = n_1 + m

Next tactic:
refine' ⟨e, _, n + 1, results_pure _, h, rfl⟩
theorem of_results_bind {s : Computation α} {f : α → Computation β} {b k} :
    Results (bind s f) b k → ∃ a m n, Results s a m ∧ Results (f a) b n ∧ k = n + m := by
  induction' k with n IH generalizing s <;> apply recOn s (fun a => _) fun s' => _ <;> intro e h
  · simp only [ret_bind, Nat.zero_eq] at h
    refine' ⟨e, _, _, results_pure _, h, rfl⟩
  · have := congr_arg head (eq_thinkN h)
    contradiction
  · simp only [ret_bind] at h
    refine' ⟨e, _, n + 1, results_pure _, h, rfl⟩
  · 

Proof state:
α : Type u
β : Type v
γ : Type w
f : α → Computation β
b : β
n : ℕ
IH : ∀ {s : Computation α}, Results (bind s f) b n → ∃ a m n_1, Results s a m ∧ Results (f a) b n_1 ∧ n = n_1 + m
s e : Computation α
h : Results (bind (think e) f) b (Nat.succ n)
⊢ ∃ a m n_1, Results (think e) a m ∧ Results (f a) b n_1 ∧ Nat.succ n = n_1 + m

Next tactic:
simp only [think_bind, results_think_iff] at h
theorem of_results_bind {s : Computation α} {f : α → Computation β} {b k} :
    Results (bind s f) b k → ∃ a m n, Results s a m ∧ Results (f a) b n ∧ k = n + m := by
  induction' k with n IH generalizing s <;> apply recOn s (fun a => _) fun s' => _ <;> intro e h
  · simp only [ret_bind, Nat.zero_eq] at h
    refine' ⟨e, _, _, results_pure _, h, rfl⟩
  · have := congr_arg head (eq_thinkN h)
    contradiction
  · simp only [ret_bind] at h
    refine' ⟨e, _, n + 1, results_pure _, h, rfl⟩
  · simp only [think_bind, results_think_iff] at h
    

Proof state:
α : Type u
β : Type v
γ : Type w
f : α → Computation β
b : β
n : ℕ
IH : ∀ {s : Computation α}, Results (bind s f) b n → ∃ a m n_1, Results s a m ∧ Results (f a) b n_1 ∧ n = n_1 + m
s e : Computation α
h : Results (bind e f) b n
⊢ ∃ a m n_1, Results (think e) a m ∧ Results (f a) b n_1 ∧ Nat.succ n = n_1 + m

Next tactic:
let ⟨a, m, n', h1, h2, e'⟩ := IH h
theorem of_results_bind {s : Computation α} {f : α → Computation β} {b k} :
    Results (bind s f) b k → ∃ a m n, Results s a m ∧ Results (f a) b n ∧ k = n + m := by
  induction' k with n IH generalizing s <;> apply recOn s (fun a => _) fun s' => _ <;> intro e h
  · simp only [ret_bind, Nat.zero_eq] at h
    refine' ⟨e, _, _, results_pure _, h, rfl⟩
  · have := congr_arg head (eq_thinkN h)
    contradiction
  · simp only [ret_bind] at h
    refine' ⟨e, _, n + 1, results_pure _, h, rfl⟩
  · simp only [think_bind, results_think_iff] at h
    let ⟨a, m, n', h1, h2, e'⟩ := IH h
    

Proof state:
α : Type u
β : Type v
γ : Type w
f : α → Computation β
b : β
n : ℕ
IH : ∀ {s : Computation α}, Results (bind s f) b n → ∃ a m n_1, Results s a m ∧ Results (f a) b n_1 ∧ n = n_1 + m
s e : Computation α
h : Results (bind e f) b n
a : α
m n' : ℕ
h1 : Results e a m
h2 : Results (f a) b n'
e' : n = n' + m
⊢ ∃ a m n_1, Results (think e) a m ∧ Results (f a) b n_1 ∧ Nat.succ n = n_1 + m

Next tactic:
rw [e']
theorem of_results_bind {s : Computation α} {f : α → Computation β} {b k} :
    Results (bind s f) b k → ∃ a m n, Results s a m ∧ Results (f a) b n ∧ k = n + m := by
  induction' k with n IH generalizing s <;> apply recOn s (fun a => _) fun s' => _ <;> intro e h
  · simp only [ret_bind, Nat.zero_eq] at h
    refine' ⟨e, _, _, results_pure _, h, rfl⟩
  · have := congr_arg head (eq_thinkN h)
    contradiction
  · simp only [ret_bind] at h
    refine' ⟨e, _, n + 1, results_pure _, h, rfl⟩
  · simp only [think_bind, results_think_iff] at h
    let ⟨a, m, n', h1, h2, e'⟩ := IH h
    rw [e']
    

Proof state:
α : Type u
β : Type v
γ : Type w
f : α → Computation β
b : β
n : ℕ
IH : ∀ {s : Computation α}, Results (bind s f) b n → ∃ a m n_1, Results s a m ∧ Results (f a) b n_1 ∧ n = n_1 + m
s e : Computation α
h : Results (bind e f) b n
a : α
m n' : ℕ
h1 : Results e a m
h2 : Results (f a) b n'
e' : n = n' + m
⊢ ∃ a m_1 n, Results (think e) a m_1 ∧ Results (f a) b n ∧ Nat.succ (n' + m) = n + m_1

Next tactic:
exact ⟨a, m.succ, n', results_think h1, h2, rfl⟩
theorem bind_promises {s : Computation α} {f : α → Computation β} {a b} (h1 : s ~> a)
    (h2 : f a ~> b) : bind s f ~> b := fun b' bB => by
  

Proof state:
α : Type u
β : Type v
γ : Type w
s : Computation α
f : α → Computation β
a : α
b : β
h1 : s ~> a
h2 : f a ~> b
b' : β
bB : b' ∈ bind s f
⊢ b = b'

Next tactic:
rcases exists_of_mem_bind bB with ⟨a', a's, ba'⟩
theorem bind_promises {s : Computation α} {f : α → Computation β} {a b} (h1 : s ~> a)
    (h2 : f a ~> b) : bind s f ~> b := fun b' bB => by
  rcases exists_of_mem_bind bB with ⟨a', a's, ba'⟩
  

Proof state:
case intro.intro
α : Type u
β : Type v
γ : Type w
s : Computation α
f : α → Computation β
a : α
b : β
h1 : s ~> a
h2 : f a ~> b
b' : β
bB : b' ∈ bind s f
a' : α
a's : a' ∈ s
ba' : b' ∈ f a'
⊢ b = b'

Next tactic:
rw [← h1 a's] at ba'
theorem bind_promises {s : Computation α} {f : α → Computation β} {a b} (h1 : s ~> a)
    (h2 : f a ~> b) : bind s f ~> b := fun b' bB => by
  rcases exists_of_mem_bind bB with ⟨a', a's, ba'⟩
  rw [← h1 a's] at ba'; 

Proof state:
case intro.intro
α : Type u
β : Type v
γ : Type w
s : Computation α
f : α → Computation β
a : α
b : β
h1 : s ~> a
h2 : f a ~> b
b' : β
bB : b' ∈ bind s f
a' : α
a's : a' ∈ s
ba' : b' ∈ f a
⊢ b = b'

Next tactic:
exact h2 ba'
theorem mem_map (f : α → β) {a} {s : Computation α} (m : a ∈ s) : f a ∈ map f s := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
f : α → β
a : α
s : Computation α
m : a ∈ s
⊢ f a ∈ map f s

Next tactic:
rw [← bind_pure]
theorem mem_map (f : α → β) {a} {s : Computation α} (m : a ∈ s) : f a ∈ map f s := by
  rw [← bind_pure]; 

Proof state:
α : Type u
β : Type v
γ : Type w
f : α → β
a : α
s : Computation α
m : a ∈ s
⊢ f a ∈ bind s (pure ∘ f)

Next tactic:
apply mem_bind m
theorem mem_map (f : α → β) {a} {s : Computation α} (m : a ∈ s) : f a ∈ map f s := by
  rw [← bind_pure]; apply mem_bind m; 

Proof state:
α : Type u
β : Type v
γ : Type w
f : α → β
a : α
s : Computation α
m : a ∈ s
⊢ f a ∈ (pure ∘ f) a

Next tactic:
apply ret_mem
theorem exists_of_mem_map {f : α → β} {b : β} {s : Computation α} (h : b ∈ map f s) :
    ∃ a, a ∈ s ∧ f a = b := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
f : α → β
b : β
s : Computation α
h : b ∈ map f s
⊢ ∃ a, a ∈ s ∧ f a = b

Next tactic:
rw [← bind_pure] at h
theorem exists_of_mem_map {f : α → β} {b : β} {s : Computation α} (h : b ∈ map f s) :
    ∃ a, a ∈ s ∧ f a = b := by
  rw [← bind_pure] at h
  

Proof state:
α : Type u
β : Type v
γ : Type w
f : α → β
b : β
s : Computation α
h : b ∈ bind s (pure ∘ f)
⊢ ∃ a, a ∈ s ∧ f a = b

Next tactic:
let ⟨a, as, fb⟩ := exists_of_mem_bind h
theorem exists_of_mem_map {f : α → β} {b : β} {s : Computation α} (h : b ∈ map f s) :
    ∃ a, a ∈ s ∧ f a = b := by
  rw [← bind_pure] at h
  let ⟨a, as, fb⟩ := exists_of_mem_bind h
  

Proof state:
α : Type u
β : Type v
γ : Type w
f : α → β
b : β
s : Computation α
h : b ∈ bind s (pure ∘ f)
a : α
as : a ∈ s
fb : b ∈ (pure ∘ f) a
⊢ ∃ a, a ∈ s ∧ f a = b

Next tactic:
exact ⟨a, as, mem_unique (ret_mem _) fb⟩
instance terminates_map (f : α → β) (s : Computation α) [Terminates s] : Terminates (map f s) := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
f : α → β
s : Computation α
inst✝ : Terminates s
⊢ Terminates (map f s)

Next tactic:
rw [← bind_pure]
instance terminates_map (f : α → β) (s : Computation α) [Terminates s] : Terminates (map f s) := by
  rw [← bind_pure]; 

Proof state:
α : Type u
β : Type v
γ : Type w
f : α → β
s : Computation α
inst✝ : Terminates s
⊢ Terminates (bind s (pure ∘ f))

Next tactic:
exact terminates_of_mem (mem_bind (get_mem s) (get_mem (f (get s))))
@[simp]
theorem ret_orElse (a : α) (c₂ : Computation α) : (pure a <|> c₂) = pure a :=
  destruct_eq_pure <| by
    

Proof state:
α : Type u
β : Type v
γ : Type w
a : α
c₂ : Computation α
⊢ destruct (HOrElse.hOrElse (pure a) fun x => c₂) = Sum.inl a

Next tactic:
unfold HOrElse.hOrElse instHOrElse
@[simp]
theorem ret_orElse (a : α) (c₂ : Computation α) : (pure a <|> c₂) = pure a :=
  destruct_eq_pure <| by
    unfold HOrElse.hOrElse instHOrElse
    

Proof state:
α : Type u
β : Type v
γ : Type w
a : α
c₂ : Computation α
⊢ destruct ({ hOrElse := fun a b => OrElse.orElse a b }.1 (pure a) fun x => c₂) = Sum.inl a

Next tactic:
unfold OrElse.orElse instOrElse Alternative.orElse instAlternativeComputation
@[simp]
theorem ret_orElse (a : α) (c₂ : Computation α) : (pure a <|> c₂) = pure a :=
  destruct_eq_pure <| by
    unfold HOrElse.hOrElse instHOrElse
    unfold OrElse.orElse instOrElse Alternative.orElse instAlternativeComputation
    

Proof state:
α : Type u
β : Type v
γ : Type w
a : α
c₂ : Computation α
⊢ destruct
      ({
            hOrElse := fun a b =>
              {
                    orElse :=
                      (let src := monad;
                        Alternative.mk empty @orElse).3 }.1
                a b }.1
        (pure a) fun x => c₂) =
    Sum.inl a

Next tactic:
simp [orElse]
@[simp]
theorem orElse_pure (c₁ : Computation α) (a : α) : (think c₁ <|> pure a) = pure a :=
  destruct_eq_pure <| by
    

Proof state:
α : Type u
β : Type v
γ : Type w
c₁ : Computation α
a : α
⊢ destruct (HOrElse.hOrElse (think c₁) fun x => pure a) = Sum.inl a

Next tactic:
unfold HOrElse.hOrElse instHOrElse
@[simp]
theorem orElse_pure (c₁ : Computation α) (a : α) : (think c₁ <|> pure a) = pure a :=
  destruct_eq_pure <| by
    unfold HOrElse.hOrElse instHOrElse
    

Proof state:
α : Type u
β : Type v
γ : Type w
c₁ : Computation α
a : α
⊢ destruct ({ hOrElse := fun a b => OrElse.orElse a b }.1 (think c₁) fun x => pure a) = Sum.inl a

Next tactic:
unfold OrElse.orElse instOrElse Alternative.orElse instAlternativeComputation
@[simp]
theorem orElse_pure (c₁ : Computation α) (a : α) : (think c₁ <|> pure a) = pure a :=
  destruct_eq_pure <| by
    unfold HOrElse.hOrElse instHOrElse
    unfold OrElse.orElse instOrElse Alternative.orElse instAlternativeComputation
    

Proof state:
α : Type u
β : Type v
γ : Type w
c₁ : Computation α
a : α
⊢ destruct
      ({
            hOrElse := fun a b =>
              {
                    orElse :=
                      (let src := monad;
                        Alternative.mk empty @orElse).3 }.1
                a b }.1
        (think c₁) fun x => pure a) =
    Sum.inl a

Next tactic:
simp [orElse]
@[simp]
theorem orElse_think (c₁ c₂ : Computation α) : (think c₁ <|> think c₂) = think (c₁ <|> c₂) :=
  destruct_eq_think <| by
    

Proof state:
α : Type u
β : Type v
γ : Type w
c₁ c₂ : Computation α
⊢ destruct (HOrElse.hOrElse (think c₁) fun x => think c₂) = Sum.inr (HOrElse.hOrElse c₁ fun x => c₂)

Next tactic:
unfold HOrElse.hOrElse instHOrElse
@[simp]
theorem orElse_think (c₁ c₂ : Computation α) : (think c₁ <|> think c₂) = think (c₁ <|> c₂) :=
  destruct_eq_think <| by
    unfold HOrElse.hOrElse instHOrElse
    

Proof state:
α : Type u
β : Type v
γ : Type w
c₁ c₂ : Computation α
⊢ destruct ({ hOrElse := fun a b => OrElse.orElse a b }.1 (think c₁) fun x => think c₂) =
    Sum.inr ({ hOrElse := fun a b => OrElse.orElse a b }.1 c₁ fun x => c₂)

Next tactic:
unfold OrElse.orElse instOrElse Alternative.orElse instAlternativeComputation
@[simp]
theorem orElse_think (c₁ c₂ : Computation α) : (think c₁ <|> think c₂) = think (c₁ <|> c₂) :=
  destruct_eq_think <| by
    unfold HOrElse.hOrElse instHOrElse
    unfold OrElse.orElse instOrElse Alternative.orElse instAlternativeComputation
    

Proof state:
α : Type u
β : Type v
γ : Type w
c₁ c₂ : Computation α
⊢ destruct
      ({
            hOrElse := fun a b =>
              {
                    orElse :=
                      (let src := monad;
                        Alternative.mk empty @orElse).3 }.1
                a b }.1
        (think c₁) fun x => think c₂) =
    Sum.inr
      ({
            hOrElse := fun a b =>
              {
                    orElse :=
                      (let src := monad;
                        Alternative.mk empty @orElse).3 }.1
                a b }.1
        c₁ fun x => c₂)

Next tactic:
simp [orElse]
@[simp]
theorem empty_orElse (c) : (empty α <|> c) = c := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
c : Computation α
⊢ (HOrElse.hOrElse (empty α) fun x => c) = c

Next tactic:
apply eq_of_bisim (fun c₁ c₂ => (empty α <|> c₂) = c₁) _ rfl
@[simp]
theorem empty_orElse (c) : (empty α <|> c) = c := by
  apply eq_of_bisim (fun c₁ c₂ => (empty α <|> c₂) = c₁) _ rfl
  

Proof state:
α : Type u
β : Type v
γ : Type w
c : Computation α
⊢ IsBisimulation fun c₁ c₂ => (HOrElse.hOrElse (empty α) fun x => c₂) = c₁

Next tactic:
intro s' s h
@[simp]
theorem empty_orElse (c) : (empty α <|> c) = c := by
  apply eq_of_bisim (fun c₁ c₂ => (empty α <|> c₂) = c₁) _ rfl
  intro s' s h; 

Proof state:
α : Type u
β : Type v
γ : Type w
c s' s : Computation α
h : (HOrElse.hOrElse (empty α) fun x => s) = s'
⊢ BisimO (fun c₁ c₂ => (HOrElse.hOrElse (empty α) fun x => c₂) = c₁) (destruct s') (destruct s)

Next tactic:
rw [← h]
@[simp]
theorem empty_orElse (c) : (empty α <|> c) = c := by
  apply eq_of_bisim (fun c₁ c₂ => (empty α <|> c₂) = c₁) _ rfl
  intro s' s h; rw [← h]
  

Proof state:
α : Type u
β : Type v
γ : Type w
c s' s : Computation α
h : (HOrElse.hOrElse (empty α) fun x => s) = s'
⊢ BisimO (fun c₁ c₂ => (HOrElse.hOrElse (empty α) fun x => c₂) = c₁) (destruct (HOrElse.hOrElse (empty α) fun x => s))
    (destruct s)

Next tactic:
apply recOn s
@[simp]
theorem empty_orElse (c) : (empty α <|> c) = c := by
  apply eq_of_bisim (fun c₁ c₂ => (empty α <|> c₂) = c₁) _ rfl
  intro s' s h; rw [← h]
  apply recOn s <;> 

Proof state:
case h1
α : Type u
β : Type v
γ : Type w
c s' s : Computation α
h : (HOrElse.hOrElse (empty α) fun x => s) = s'
⊢ ∀ (a : α),
    BisimO (fun c₁ c₂ => (HOrElse.hOrElse (empty α) fun x => c₂) = c₁)
      (destruct (HOrElse.hOrElse (empty α) fun x => pure a)) (destruct (pure a))

Next tactic:
intro s
@[simp]
theorem empty_orElse (c) : (empty α <|> c) = c := by
  apply eq_of_bisim (fun c₁ c₂ => (empty α <|> c₂) = c₁) _ rfl
  intro s' s h; rw [← h]
  apply recOn s <;> 

Proof state:
case h2
α : Type u
β : Type v
γ : Type w
c s' s : Computation α
h : (HOrElse.hOrElse (empty α) fun x => s) = s'
⊢ ∀ (s : Computation α),
    BisimO (fun c₁ c₂ => (HOrElse.hOrElse (empty α) fun x => c₂) = c₁)
      (destruct (HOrElse.hOrElse (empty α) fun x => think s)) (destruct (think s))

Next tactic:
intro s
@[simp]
theorem empty_orElse (c) : (empty α <|> c) = c := by
  apply eq_of_bisim (fun c₁ c₂ => (empty α <|> c₂) = c₁) _ rfl
  intro s' s h; rw [← h]
  apply recOn s <;> intro s <;> 

Proof state:
case h1
α : Type u
β : Type v
γ : Type w
c s' s✝ : Computation α
h : (HOrElse.hOrElse (empty α) fun x => s✝) = s'
s : α
⊢ BisimO (fun c₁ c₂ => (HOrElse.hOrElse (empty α) fun x => c₂) = c₁)
    (destruct (HOrElse.hOrElse (empty α) fun x => pure s)) (destruct (pure s))

Next tactic:
rw [think_empty]
@[simp]
theorem empty_orElse (c) : (empty α <|> c) = c := by
  apply eq_of_bisim (fun c₁ c₂ => (empty α <|> c₂) = c₁) _ rfl
  intro s' s h; rw [← h]
  apply recOn s <;> intro s <;> 

Proof state:
case h2
α : Type u
β : Type v
γ : Type w
c s' s✝ : Computation α
h : (HOrElse.hOrElse (empty α) fun x => s✝) = s'
s : Computation α
⊢ BisimO (fun c₁ c₂ => (HOrElse.hOrElse (empty α) fun x => c₂) = c₁)
    (destruct (HOrElse.hOrElse (empty α) fun x => think s)) (destruct (think s))

Next tactic:
rw [think_empty]
@[simp]
theorem empty_orElse (c) : (empty α <|> c) = c := by
  apply eq_of_bisim (fun c₁ c₂ => (empty α <|> c₂) = c₁) _ rfl
  intro s' s h; rw [← h]
  apply recOn s <;> intro s <;> rw [think_empty] <;> 

Proof state:
case h1
α : Type u
β : Type v
γ : Type w
c s' s✝ : Computation α
h : (HOrElse.hOrElse (empty α) fun x => s✝) = s'
s : α
⊢ BisimO (fun c₁ c₂ => (HOrElse.hOrElse (think (empty α)) fun x => c₂) = c₁)
    (destruct (HOrElse.hOrElse (think (empty α)) fun x => pure s)) (destruct (pure s))

Next tactic:
simp
@[simp]
theorem empty_orElse (c) : (empty α <|> c) = c := by
  apply eq_of_bisim (fun c₁ c₂ => (empty α <|> c₂) = c₁) _ rfl
  intro s' s h; rw [← h]
  apply recOn s <;> intro s <;> rw [think_empty] <;> 

Proof state:
case h2
α : Type u
β : Type v
γ : Type w
c s' s✝ : Computation α
h : (HOrElse.hOrElse (empty α) fun x => s✝) = s'
s : Computation α
⊢ BisimO (fun c₁ c₂ => (HOrElse.hOrElse (think (empty α)) fun x => c₂) = c₁)
    (destruct (HOrElse.hOrElse (think (empty α)) fun x => think s)) (destruct (think s))

Next tactic:
simp
@[simp]
theorem empty_orElse (c) : (empty α <|> c) = c := by
  apply eq_of_bisim (fun c₁ c₂ => (empty α <|> c₂) = c₁) _ rfl
  intro s' s h; rw [← h]
  apply recOn s <;> intro s <;> rw [think_empty] <;> simp
  

Proof state:
case h2
α : Type u
β : Type v
γ : Type w
c s' s✝ : Computation α
h : (HOrElse.hOrElse (empty α) fun x => s✝) = s'
s : Computation α
⊢ (HOrElse.hOrElse (think (empty α)) fun x => s) = HOrElse.hOrElse (empty α) fun x => s

Next tactic:
rw [← think_empty]
@[simp]
theorem orElse_empty (c : Computation α) : (c <|> empty α) = c := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
c : Computation α
⊢ (HOrElse.hOrElse c fun x => empty α) = c

Next tactic:
apply eq_of_bisim (fun c₁ c₂ => (c₂ <|> empty α) = c₁) _ rfl
@[simp]
theorem orElse_empty (c : Computation α) : (c <|> empty α) = c := by
  apply eq_of_bisim (fun c₁ c₂ => (c₂ <|> empty α) = c₁) _ rfl
  

Proof state:
α : Type u
β : Type v
γ : Type w
c : Computation α
⊢ IsBisimulation fun c₁ c₂ => (HOrElse.hOrElse c₂ fun x => empty α) = c₁

Next tactic:
intro s' s h
@[simp]
theorem orElse_empty (c : Computation α) : (c <|> empty α) = c := by
  apply eq_of_bisim (fun c₁ c₂ => (c₂ <|> empty α) = c₁) _ rfl
  intro s' s h; 

Proof state:
α : Type u
β : Type v
γ : Type w
c s' s : Computation α
h : (HOrElse.hOrElse s fun x => empty α) = s'
⊢ BisimO (fun c₁ c₂ => (HOrElse.hOrElse c₂ fun x => empty α) = c₁) (destruct s') (destruct s)

Next tactic:
rw [← h]
@[simp]
theorem orElse_empty (c : Computation α) : (c <|> empty α) = c := by
  apply eq_of_bisim (fun c₁ c₂ => (c₂ <|> empty α) = c₁) _ rfl
  intro s' s h; rw [← h]
  

Proof state:
α : Type u
β : Type v
γ : Type w
c s' s : Computation α
h : (HOrElse.hOrElse s fun x => empty α) = s'
⊢ BisimO (fun c₁ c₂ => (HOrElse.hOrElse c₂ fun x => empty α) = c₁) (destruct (HOrElse.hOrElse s fun x => empty α))
    (destruct s)

Next tactic:
apply recOn s