l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem bind_assoc (s : Computation α) (f : α → Computation β) (g : β → Computation γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  apply
    eq_of_bisim fun c₁ c₂ =>
      c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x : α => bind (f x) g
  · intro c₁ c₂ h
    match c₁, c₂, h with
    | _, c₂, Or.inl (Eq.refl _) => cases' destruct c₂ with b cb <;> simp
    | _, _, Or.inr ⟨s, rfl, rfl⟩ =>
      apply recOn s <;> 

Proof state:
case h2
α : Type u
β : Type v
γ : Type w
s✝ : Computation α
f : α → Computation β
g : β → Computation γ
c₁ c₂ : Computation γ
h : c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x => bind (f x) g
s : Computation α
⊢ ∀ (s : Computation α),
    BisimO (fun c₁ c₂ => c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x => bind (f x) g)
      (destruct (bind (bind (think s) f) g)) (destruct (bind (think s) fun x => bind (f x) g))

Next tactic:
intro s
@[simp]
theorem bind_assoc (s : Computation α) (f : α → Computation β) (g : β → Computation γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  apply
    eq_of_bisim fun c₁ c₂ =>
      c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x : α => bind (f x) g
  · intro c₁ c₂ h
    match c₁, c₂, h with
    | _, c₂, Or.inl (Eq.refl _) => cases' destruct c₂ with b cb <;> simp
    | _, _, Or.inr ⟨s, rfl, rfl⟩ =>
      apply recOn s <;> intro s <;> 

Proof state:
case h1
α : Type u
β : Type v
γ : Type w
s✝¹ : Computation α
f : α → Computation β
g : β → Computation γ
c₁ c₂ : Computation γ
h : c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x => bind (f x) g
s✝ : Computation α
s : α
⊢ BisimO (fun c₁ c₂ => c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x => bind (f x) g)
    (destruct (bind (bind (pure s) f) g)) (destruct (bind (pure s) fun x => bind (f x) g))

Next tactic:
simp
@[simp]
theorem bind_assoc (s : Computation α) (f : α → Computation β) (g : β → Computation γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  apply
    eq_of_bisim fun c₁ c₂ =>
      c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x : α => bind (f x) g
  · intro c₁ c₂ h
    match c₁, c₂, h with
    | _, c₂, Or.inl (Eq.refl _) => cases' destruct c₂ with b cb <;> simp
    | _, _, Or.inr ⟨s, rfl, rfl⟩ =>
      apply recOn s <;> intro s <;> 

Proof state:
case h2
α : Type u
β : Type v
γ : Type w
s✝¹ : Computation α
f : α → Computation β
g : β → Computation γ
c₁ c₂ : Computation γ
h : c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x => bind (f x) g
s✝ s : Computation α
⊢ BisimO (fun c₁ c₂ => c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x => bind (f x) g)
    (destruct (bind (bind (think s) f) g)) (destruct (bind (think s) fun x => bind (f x) g))

Next tactic:
simp
@[simp]
theorem bind_assoc (s : Computation α) (f : α → Computation β) (g : β → Computation γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  apply
    eq_of_bisim fun c₁ c₂ =>
      c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x : α => bind (f x) g
  · intro c₁ c₂ h
    match c₁, c₂, h with
    | _, c₂, Or.inl (Eq.refl _) => cases' destruct c₂ with b cb <;> simp
    | _, _, Or.inr ⟨s, rfl, rfl⟩ =>
      apply recOn s <;> intro s <;> simp
      · 

Proof state:
case h1
α : Type u
β : Type v
γ : Type w
s✝¹ : Computation α
f : α → Computation β
g : β → Computation γ
c₁ c₂ : Computation γ
h : c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x => bind (f x) g
s✝ : Computation α
s : α
⊢ match destruct (bind (f s) g), destruct (bind (f s) g) with
  | Sum.inl a, Sum.inl a' => a = a'
  | Sum.inr s, Sum.inr s' => s = s' ∨ ∃ s_1, s = bind (bind s_1 f) g ∧ s' = bind s_1 fun x => bind (f x) g
  | x, x_1 => False

Next tactic:
generalize f s = fs
@[simp]
theorem bind_assoc (s : Computation α) (f : α → Computation β) (g : β → Computation γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  apply
    eq_of_bisim fun c₁ c₂ =>
      c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x : α => bind (f x) g
  · intro c₁ c₂ h
    match c₁, c₂, h with
    | _, c₂, Or.inl (Eq.refl _) => cases' destruct c₂ with b cb <;> simp
    | _, _, Or.inr ⟨s, rfl, rfl⟩ =>
      apply recOn s <;> intro s <;> simp
      · generalize f s = fs
        

Proof state:
case h1
α : Type u
β : Type v
γ : Type w
s✝¹ : Computation α
f : α → Computation β
g : β → Computation γ
c₁ c₂ : Computation γ
h : c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x => bind (f x) g
s✝ : Computation α
s : α
fs : Computation β
⊢ match destruct (bind fs g), destruct (bind fs g) with
  | Sum.inl a, Sum.inl a' => a = a'
  | Sum.inr s, Sum.inr s' => s = s' ∨ ∃ s_1, s = bind (bind s_1 f) g ∧ s' = bind s_1 fun x => bind (f x) g
  | x, x_1 => False

Next tactic:
apply recOn fs
@[simp]
theorem bind_assoc (s : Computation α) (f : α → Computation β) (g : β → Computation γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  apply
    eq_of_bisim fun c₁ c₂ =>
      c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x : α => bind (f x) g
  · intro c₁ c₂ h
    match c₁, c₂, h with
    | _, c₂, Or.inl (Eq.refl _) => cases' destruct c₂ with b cb <;> simp
    | _, _, Or.inr ⟨s, rfl, rfl⟩ =>
      apply recOn s <;> intro s <;> simp
      · generalize f s = fs
        apply recOn fs <;> 

Proof state:
case h1.h1
α : Type u
β : Type v
γ : Type w
s✝¹ : Computation α
f : α → Computation β
g : β → Computation γ
c₁ c₂ : Computation γ
h : c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x => bind (f x) g
s✝ : Computation α
s : α
fs : Computation β
⊢ ∀ (a : β),
    match destruct (bind (pure a) g), destruct (bind (pure a) g) with
    | Sum.inl a, Sum.inl a' => a = a'
    | Sum.inr s, Sum.inr s' => s = s' ∨ ∃ s_1, s = bind (bind s_1 f) g ∧ s' = bind s_1 fun x => bind (f x) g
    | x, x_1 => False

Next tactic:
intro t
@[simp]
theorem bind_assoc (s : Computation α) (f : α → Computation β) (g : β → Computation γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  apply
    eq_of_bisim fun c₁ c₂ =>
      c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x : α => bind (f x) g
  · intro c₁ c₂ h
    match c₁, c₂, h with
    | _, c₂, Or.inl (Eq.refl _) => cases' destruct c₂ with b cb <;> simp
    | _, _, Or.inr ⟨s, rfl, rfl⟩ =>
      apply recOn s <;> intro s <;> simp
      · generalize f s = fs
        apply recOn fs <;> 

Proof state:
case h1.h2
α : Type u
β : Type v
γ : Type w
s✝¹ : Computation α
f : α → Computation β
g : β → Computation γ
c₁ c₂ : Computation γ
h : c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x => bind (f x) g
s✝ : Computation α
s : α
fs : Computation β
⊢ ∀ (s : Computation β),
    match destruct (bind (think s) g), destruct (bind (think s) g) with
    | Sum.inl a, Sum.inl a' => a = a'
    | Sum.inr s, Sum.inr s' => s = s' ∨ ∃ s_1, s = bind (bind s_1 f) g ∧ s' = bind s_1 fun x => bind (f x) g
    | x, x_1 => False

Next tactic:
intro t
@[simp]
theorem bind_assoc (s : Computation α) (f : α → Computation β) (g : β → Computation γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  apply
    eq_of_bisim fun c₁ c₂ =>
      c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x : α => bind (f x) g
  · intro c₁ c₂ h
    match c₁, c₂, h with
    | _, c₂, Or.inl (Eq.refl _) => cases' destruct c₂ with b cb <;> simp
    | _, _, Or.inr ⟨s, rfl, rfl⟩ =>
      apply recOn s <;> intro s <;> simp
      · generalize f s = fs
        apply recOn fs <;> intro t <;> 

Proof state:
case h1.h1
α : Type u
β : Type v
γ : Type w
s✝¹ : Computation α
f : α → Computation β
g : β → Computation γ
c₁ c₂ : Computation γ
h : c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x => bind (f x) g
s✝ : Computation α
s : α
fs : Computation β
t : β
⊢ match destruct (bind (pure t) g), destruct (bind (pure t) g) with
  | Sum.inl a, Sum.inl a' => a = a'
  | Sum.inr s, Sum.inr s' => s = s' ∨ ∃ s_1, s = bind (bind s_1 f) g ∧ s' = bind s_1 fun x => bind (f x) g
  | x, x_1 => False

Next tactic:
simp
@[simp]
theorem bind_assoc (s : Computation α) (f : α → Computation β) (g : β → Computation γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  apply
    eq_of_bisim fun c₁ c₂ =>
      c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x : α => bind (f x) g
  · intro c₁ c₂ h
    match c₁, c₂, h with
    | _, c₂, Or.inl (Eq.refl _) => cases' destruct c₂ with b cb <;> simp
    | _, _, Or.inr ⟨s, rfl, rfl⟩ =>
      apply recOn s <;> intro s <;> simp
      · generalize f s = fs
        apply recOn fs <;> intro t <;> 

Proof state:
case h1.h2
α : Type u
β : Type v
γ : Type w
s✝¹ : Computation α
f : α → Computation β
g : β → Computation γ
c₁ c₂ : Computation γ
h : c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x => bind (f x) g
s✝ : Computation α
s : α
fs t : Computation β
⊢ match destruct (bind (think t) g), destruct (bind (think t) g) with
  | Sum.inl a, Sum.inl a' => a = a'
  | Sum.inr s, Sum.inr s' => s = s' ∨ ∃ s_1, s = bind (bind s_1 f) g ∧ s' = bind s_1 fun x => bind (f x) g
  | x, x_1 => False

Next tactic:
simp
@[simp]
theorem bind_assoc (s : Computation α) (f : α → Computation β) (g : β → Computation γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  apply
    eq_of_bisim fun c₁ c₂ =>
      c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x : α => bind (f x) g
  · intro c₁ c₂ h
    match c₁, c₂, h with
    | _, c₂, Or.inl (Eq.refl _) => cases' destruct c₂ with b cb <;> simp
    | _, _, Or.inr ⟨s, rfl, rfl⟩ =>
      apply recOn s <;> intro s <;> simp
      · generalize f s = fs
        apply recOn fs <;> intro t <;> simp
        · 

Proof state:
case h1.h1
α : Type u
β : Type v
γ : Type w
s✝¹ : Computation α
f : α → Computation β
g : β → Computation γ
c₁ c₂ : Computation γ
h : c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x => bind (f x) g
s✝ : Computation α
s : α
fs : Computation β
t : β
⊢ match destruct (g t), destruct (g t) with
  | Sum.inl a, Sum.inl a' => a = a'
  | Sum.inr s, Sum.inr s' => s = s' ∨ ∃ s_1, s = bind (bind s_1 f) g ∧ s' = bind s_1 fun x => bind (f x) g
  | x, x_1 => False

Next tactic:
cases' destruct (g t) with b cb
@[simp]
theorem bind_assoc (s : Computation α) (f : α → Computation β) (g : β → Computation γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  apply
    eq_of_bisim fun c₁ c₂ =>
      c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x : α => bind (f x) g
  · intro c₁ c₂ h
    match c₁, c₂, h with
    | _, c₂, Or.inl (Eq.refl _) => cases' destruct c₂ with b cb <;> simp
    | _, _, Or.inr ⟨s, rfl, rfl⟩ =>
      apply recOn s <;> intro s <;> simp
      · generalize f s = fs
        apply recOn fs <;> intro t <;> simp
        · cases' destruct (g t) with b cb <;> 

Proof state:
case h1.h1.inl
α : Type u
β : Type v
γ : Type w
s✝¹ : Computation α
f : α → Computation β
g : β → Computation γ
c₁ c₂ : Computation γ
h : c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x => bind (f x) g
s✝ : Computation α
s : α
fs : Computation β
t : β
b : γ
⊢ match Sum.inl b, Sum.inl b with
  | Sum.inl a, Sum.inl a' => a = a'
  | Sum.inr s, Sum.inr s' => s = s' ∨ ∃ s_1, s = bind (bind s_1 f) g ∧ s' = bind s_1 fun x => bind (f x) g
  | x, x_1 => False

Next tactic:
simp
@[simp]
theorem bind_assoc (s : Computation α) (f : α → Computation β) (g : β → Computation γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  apply
    eq_of_bisim fun c₁ c₂ =>
      c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x : α => bind (f x) g
  · intro c₁ c₂ h
    match c₁, c₂, h with
    | _, c₂, Or.inl (Eq.refl _) => cases' destruct c₂ with b cb <;> simp
    | _, _, Or.inr ⟨s, rfl, rfl⟩ =>
      apply recOn s <;> intro s <;> simp
      · generalize f s = fs
        apply recOn fs <;> intro t <;> simp
        · cases' destruct (g t) with b cb <;> 

Proof state:
case h1.h1.inr
α : Type u
β : Type v
γ : Type w
s✝¹ : Computation α
f : α → Computation β
g : β → Computation γ
c₁ c₂ : Computation γ
h : c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x => bind (f x) g
s✝ : Computation α
s : α
fs : Computation β
t : β
cb : Computation γ
⊢ match Sum.inr cb, Sum.inr cb with
  | Sum.inl a, Sum.inl a' => a = a'
  | Sum.inr s, Sum.inr s' => s = s' ∨ ∃ s_1, s = bind (bind s_1 f) g ∧ s' = bind s_1 fun x => bind (f x) g
  | x, x_1 => False

Next tactic:
simp
@[simp]
theorem bind_assoc (s : Computation α) (f : α → Computation β) (g : β → Computation γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  apply
    eq_of_bisim fun c₁ c₂ =>
      c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x : α => bind (f x) g
  · intro c₁ c₂ h
    match c₁, c₂, h with
    | _, c₂, Or.inl (Eq.refl _) => cases' destruct c₂ with b cb <;> simp
    | _, _, Or.inr ⟨s, rfl, rfl⟩ =>
      apply recOn s <;> intro s <;> simp
      · generalize f s = fs
        apply recOn fs <;> intro t <;> simp
        · cases' destruct (g t) with b cb <;> simp
      · 

Proof state:
case h2
α : Type u
β : Type v
γ : Type w
s✝¹ : Computation α
f : α → Computation β
g : β → Computation γ
c₁ c₂ : Computation γ
h : c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x => bind (f x) g
s✝ s : Computation α
⊢ (bind (bind s f) g = bind s fun x => bind (f x) g) ∨
    ∃ s_1, bind (bind s f) g = bind (bind s_1 f) g ∧ (bind s fun x => bind (f x) g) = bind s_1 fun x => bind (f x) g

Next tactic:
exact Or.inr ⟨s, rfl, rfl⟩
@[simp]
theorem bind_assoc (s : Computation α) (f : α → Computation β) (g : β → Computation γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g := by
  apply
    eq_of_bisim fun c₁ c₂ =>
      c₁ = c₂ ∨ ∃ s, c₁ = bind (bind s f) g ∧ c₂ = bind s fun x : α => bind (f x) g
  · intro c₁ c₂ h
    match c₁, c₂, h with
    | _, c₂, Or.inl (Eq.refl _) => cases' destruct c₂ with b cb <;> simp
    | _, _, Or.inr ⟨s, rfl, rfl⟩ =>
      apply recOn s <;> intro s <;> simp
      · generalize f s = fs
        apply recOn fs <;> intro t <;> simp
        · cases' destruct (g t) with b cb <;> simp
      · exact Or.inr ⟨s, rfl, rfl⟩
  · 

Proof state:
case r
α : Type u
β : Type v
γ : Type w
s : Computation α
f : α → Computation β
g : β → Computation γ
⊢ (bind (bind s f) g = bind s fun x => bind (f x) g) ∨
    ∃ s_1, bind (bind s f) g = bind (bind s_1 f) g ∧ (bind s fun x => bind (f x) g) = bind s_1 fun x => bind (f x) g

Next tactic:
exact Or.inr ⟨s, rfl, rfl⟩
theorem results_bind {s : Computation α} {f : α → Computation β} {a b m n} (h1 : Results s a m)
    (h2 : Results (f a) b n) : Results (bind s f) b (n + m) := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
s : Computation α
f : α → Computation β
a : α
b : β
m n : ℕ
h1 : Results s a m
h2 : Results (f a) b n
⊢ Results (bind s f) b (n + m)

Next tactic:
have := h1.mem
theorem results_bind {s : Computation α} {f : α → Computation β} {a b m n} (h1 : Results s a m)
    (h2 : Results (f a) b n) : Results (bind s f) b (n + m) := by
  have := h1.mem; 

Proof state:
α : Type u
β : Type v
γ : Type w
s : Computation α
f : α → Computation β
a : α
b : β
m n : ℕ
h1 : Results s a m
h2 : Results (f a) b n
this : a ∈ s
⊢ Results (bind s f) b (n + m)

Next tactic:
revert m
theorem results_bind {s : Computation α} {f : α → Computation β} {a b m n} (h1 : Results s a m)
    (h2 : Results (f a) b n) : Results (bind s f) b (n + m) := by
  have := h1.mem; revert m
  

Proof state:
α : Type u
β : Type v
γ : Type w
s : Computation α
f : α → Computation β
a : α
b : β
n : ℕ
h2 : Results (f a) b n
this : a ∈ s
⊢ ∀ {m : ℕ}, Results s a m → Results (bind s f) b (n + m)

Next tactic:
apply memRecOn this _ fun s IH => _
theorem results_bind {s : Computation α} {f : α → Computation β} {a b m n} (h1 : Results s a m)
    (h2 : Results (f a) b n) : Results (bind s f) b (n + m) := by
  have := h1.mem; revert m
  apply memRecOn this _ fun s IH => _
  · 

Proof state:
α : Type u
β : Type v
γ : Type w
s : Computation α
f : α → Computation β
a : α
b : β
n : ℕ
h2 : Results (f a) b n
this : a ∈ s
⊢ ∀ {m : ℕ}, Results (pure a) a m → Results (bind (pure a) f) b (n + m)

Next tactic:
intro _ h1
theorem results_bind {s : Computation α} {f : α → Computation β} {a b m n} (h1 : Results s a m)
    (h2 : Results (f a) b n) : Results (bind s f) b (n + m) := by
  have := h1.mem; revert m
  apply memRecOn this _ fun s IH => _
  · intro _ h1
    

Proof state:
α : Type u
β : Type v
γ : Type w
s : Computation α
f : α → Computation β
a : α
b : β
n : ℕ
h2 : Results (f a) b n
this : a ∈ s
m✝ : ℕ
h1 : Results (pure a) a m✝
⊢ Results (bind (pure a) f) b (n + m✝)

Next tactic:
rw [ret_bind]
theorem results_bind {s : Computation α} {f : α → Computation β} {a b m n} (h1 : Results s a m)
    (h2 : Results (f a) b n) : Results (bind s f) b (n + m) := by
  have := h1.mem; revert m
  apply memRecOn this _ fun s IH => _
  · intro _ h1
    rw [ret_bind]
    

Proof state:
α : Type u
β : Type v
γ : Type w
s : Computation α
f : α → Computation β
a : α
b : β
n : ℕ
h2 : Results (f a) b n
this : a ∈ s
m✝ : ℕ
h1 : Results (pure a) a m✝
⊢ Results (f a) b (n + m✝)

Next tactic:
rw [h1.len_unique (results_pure _)]
theorem results_bind {s : Computation α} {f : α → Computation β} {a b m n} (h1 : Results s a m)
    (h2 : Results (f a) b n) : Results (bind s f) b (n + m) := by
  have := h1.mem; revert m
  apply memRecOn this _ fun s IH => _
  · intro _ h1
    rw [ret_bind]
    rw [h1.len_unique (results_pure _)]
    

Proof state:
α : Type u
β : Type v
γ : Type w
s : Computation α
f : α → Computation β
a : α
b : β
n : ℕ
h2 : Results (f a) b n
this : a ∈ s
m✝ : ℕ
h1 : Results (pure a) a m✝
⊢ Results (f a) b (n + 0)

Next tactic:
exact h2
theorem results_bind {s : Computation α} {f : α → Computation β} {a b m n} (h1 : Results s a m)
    (h2 : Results (f a) b n) : Results (bind s f) b (n + m) := by
  have := h1.mem; revert m
  apply memRecOn this _ fun s IH => _
  · intro _ h1
    rw [ret_bind]
    rw [h1.len_unique (results_pure _)]
    exact h2
  · 

Proof state:
α : Type u
β : Type v
γ : Type w
s : Computation α
f : α → Computation β
a : α
b : β
n : ℕ
h2 : Results (f a) b n
this : a ∈ s
⊢ ∀ (s : Computation α),
    (∀ {m : ℕ}, Results s a m → Results (bind s f) b (n + m)) →
      ∀ {m : ℕ}, Results (think s) a m → Results (bind (think s) f) b (n + m)

Next tactic:
intro _ h3 _ h1
theorem results_bind {s : Computation α} {f : α → Computation β} {a b m n} (h1 : Results s a m)
    (h2 : Results (f a) b n) : Results (bind s f) b (n + m) := by
  have := h1.mem; revert m
  apply memRecOn this _ fun s IH => _
  · intro _ h1
    rw [ret_bind]
    rw [h1.len_unique (results_pure _)]
    exact h2
  · intro _ h3 _ h1
    

Proof state:
α : Type u
β : Type v
γ : Type w
s : Computation α
f : α → Computation β
a : α
b : β
n : ℕ
h2 : Results (f a) b n
this : a ∈ s
s✝ : Computation α
h3 : ∀ {m : ℕ}, Results s✝ a m → Results (bind s✝ f) b (n + m)
m✝ : ℕ
h1 : Results (think s✝) a m✝
⊢ Results (bind (think s✝) f) b (n + m✝)

Next tactic:
rw [think_bind]
theorem results_bind {s : Computation α} {f : α → Computation β} {a b m n} (h1 : Results s a m)
    (h2 : Results (f a) b n) : Results (bind s f) b (n + m) := by
  have := h1.mem; revert m
  apply memRecOn this _ fun s IH => _
  · intro _ h1
    rw [ret_bind]
    rw [h1.len_unique (results_pure _)]
    exact h2
  · intro _ h3 _ h1
    rw [think_bind]
    

Proof state:
α : Type u
β : Type v
γ : Type w
s : Computation α
f : α → Computation β
a : α
b : β
n : ℕ
h2 : Results (f a) b n
this : a ∈ s
s✝ : Computation α
h3 : ∀ {m : ℕ}, Results s✝ a m → Results (bind s✝ f) b (n + m)
m✝ : ℕ
h1 : Results (think s✝) a m✝
⊢ Results (think (bind s✝ f)) b (n + m✝)

Next tactic:
cases' of_results_think h1 with m' h
theorem results_bind {s : Computation α} {f : α → Computation β} {a b m n} (h1 : Results s a m)
    (h2 : Results (f a) b n) : Results (bind s f) b (n + m) := by
  have := h1.mem; revert m
  apply memRecOn this _ fun s IH => _
  · intro _ h1
    rw [ret_bind]
    rw [h1.len_unique (results_pure _)]
    exact h2
  · intro _ h3 _ h1
    rw [think_bind]
    cases' of_results_think h1 with m' h
    

Proof state:
case intro
α : Type u
β : Type v
γ : Type w
s : Computation α
f : α → Computation β
a : α
b : β
n : ℕ
h2 : Results (f a) b n
this : a ∈ s
s✝ : Computation α
h3 : ∀ {m : ℕ}, Results s✝ a m → Results (bind s✝ f) b (n + m)
m✝ : ℕ
h1 : Results (think s✝) a m✝
m' : ℕ
h : Results s✝ a m' ∧ m✝ = m' + 1
⊢ Results (think (bind s✝ f)) b (n + m✝)

Next tactic:
cases' h with h1 e
theorem results_bind {s : Computation α} {f : α → Computation β} {a b m n} (h1 : Results s a m)
    (h2 : Results (f a) b n) : Results (bind s f) b (n + m) := by
  have := h1.mem; revert m
  apply memRecOn this _ fun s IH => _
  · intro _ h1
    rw [ret_bind]
    rw [h1.len_unique (results_pure _)]
    exact h2
  · intro _ h3 _ h1
    rw [think_bind]
    cases' of_results_think h1 with m' h
    cases' h with h1 e
    

Proof state:
case intro.intro
α : Type u
β : Type v
γ : Type w
s : Computation α
f : α → Computation β
a : α
b : β
n : ℕ
h2 : Results (f a) b n
this : a ∈ s
s✝ : Computation α
h3 : ∀ {m : ℕ}, Results s✝ a m → Results (bind s✝ f) b (n + m)
m✝ : ℕ
h1✝ : Results (think s✝) a m✝
m' : ℕ
h1 : Results s✝ a m'
e : m✝ = m' + 1
⊢ Results (think (bind s✝ f)) b (n + m✝)

Next tactic:
rw [e]
theorem results_bind {s : Computation α} {f : α → Computation β} {a b m n} (h1 : Results s a m)
    (h2 : Results (f a) b n) : Results (bind s f) b (n + m) := by
  have := h1.mem; revert m
  apply memRecOn this _ fun s IH => _
  · intro _ h1
    rw [ret_bind]
    rw [h1.len_unique (results_pure _)]
    exact h2
  · intro _ h3 _ h1
    rw [think_bind]
    cases' of_results_think h1 with m' h
    cases' h with h1 e
    rw [e]
    

Proof state:
case intro.intro
α : Type u
β : Type v
γ : Type w
s : Computation α
f : α → Computation β
a : α
b : β
n : ℕ
h2 : Results (f a) b n
this : a ∈ s
s✝ : Computation α
h3 : ∀ {m : ℕ}, Results s✝ a m → Results (bind s✝ f) b (n + m)
m✝ : ℕ
h1✝ : Results (think s✝) a m✝
m' : ℕ
h1 : Results s✝ a m'
e : m✝ = m' + 1
⊢ Results (think (bind s✝ f)) b (n + (m' + 1))

Next tactic:
exact results_think (h3 h1)
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
  

Proof state:
α : Type u
β : Type v
γ : Type w
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

Next tactic:
induction' k with n IH generalizing s
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 <;> 

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

Next tactic:
apply recOn s (fun a => _) fun s' => _
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 <;> 

Proof state:
case succ
α : 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 α
⊢ Results (bind s f) b (Nat.succ n) → ∃ a m n_1, Results s a m ∧ Results (f a) b n_1 ∧ Nat.succ n = n_1 + m

Next tactic:
apply recOn s (fun a => _) fun s' => _
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 α
⊢ ∀ (a : α),
    Results (bind (pure a) f) b Nat.zero → ∃ a_2 m n, Results (pure a) a_2 m ∧ Results (f a_2) b n ∧ Nat.zero = n + m

Next tactic:
intro e h