l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem mem_rfind {p : ℕ →. Bool} {n : ℕ} :
    n ∈ rfind p ↔ true ∈ p n ∧ ∀ {m : ℕ}, m < n → false ∈ p m :=
  ⟨fun h => ⟨rfind_spec h, @rfind_min _ _ h⟩, fun ⟨h₁, h₂⟩ => by
    let ⟨m, hm⟩ := dom_iff_mem.1 <| (@rfind_dom p).2 ⟨_, h₁, fun {m} mn => (h₂ mn).fst⟩
    rcases lt_trichotomy m n with (h | h | h)
    · injection mem_unique (h₂ h) (rfind_spec hm)
    · 

Proof state:
case inr.inl
p : ℕ →. Bool
n : ℕ
x✝ : true ∈ p n ∧ ∀ {m : ℕ}, m < n → false ∈ p m
h₁ : true ∈ p n
h₂ : ∀ {m : ℕ}, m < n → false ∈ p m
m : ℕ
hm : m ∈ rfind p
h : m = n
⊢ n ∈ rfind p

Next tactic:
rwa [← h]
@[simp]
theorem mem_rfind {p : ℕ →. Bool} {n : ℕ} :
    n ∈ rfind p ↔ true ∈ p n ∧ ∀ {m : ℕ}, m < n → false ∈ p m :=
  ⟨fun h => ⟨rfind_spec h, @rfind_min _ _ h⟩, fun ⟨h₁, h₂⟩ => by
    let ⟨m, hm⟩ := dom_iff_mem.1 <| (@rfind_dom p).2 ⟨_, h₁, fun {m} mn => (h₂ mn).fst⟩
    rcases lt_trichotomy m n with (h | h | h)
    · injection mem_unique (h₂ h) (rfind_spec hm)
    · rwa [← h]
    · 

Proof state:
case inr.inr
p : ℕ →. Bool
n : ℕ
x✝ : true ∈ p n ∧ ∀ {m : ℕ}, m < n → false ∈ p m
h₁ : true ∈ p n
h₂ : ∀ {m : ℕ}, m < n → false ∈ p m
m : ℕ
hm : m ∈ rfind p
h : n < m
⊢ n ∈ rfind p

Next tactic:
injection mem_unique h₁ (rfind_min hm h)
theorem rfind_min' {p : ℕ → Bool} {m : ℕ} (pm : p m) : ∃ n ∈ rfind p, n ≤ m :=
  have : true ∈ (p : ℕ →. Bool) m := ⟨trivial, pm⟩
  let ⟨n, hn⟩ := dom_iff_mem.1 <| (@rfind_dom p).2 ⟨m, this, fun {k} _ => ⟨⟩⟩
  ⟨n, hn, not_lt.1 fun h => by 

Proof state:
p : ℕ → Bool
m : ℕ
pm : p m = true
this : true ∈ ↑p m
n : ℕ
hn : n ∈ rfind ↑p
h : m < n
⊢ False

Next tactic:
injection mem_unique this (rfind_min hn h)
theorem rfindOpt_dom {α} {f : ℕ → Option α} : (rfindOpt f).Dom ↔ ∃ n a, a ∈ f n :=
  ⟨fun h => (rfindOpt_spec ⟨h, rfl⟩).imp fun n h => ⟨_, h⟩, fun h => by
    

Proof state:
α : Type u_1
f : ℕ → Option α
h : ∃ n a, a ∈ f n
⊢ (rfindOpt f).Dom

Next tactic:
have h' : ∃ n, (f n).isSome := h.imp fun n => Option.isSome_iff_exists.2
theorem rfindOpt_dom {α} {f : ℕ → Option α} : (rfindOpt f).Dom ↔ ∃ n a, a ∈ f n :=
  ⟨fun h => (rfindOpt_spec ⟨h, rfl⟩).imp fun n h => ⟨_, h⟩, fun h => by
    have h' : ∃ n, (f n).isSome := h.imp fun n => Option.isSome_iff_exists.2
    

Proof state:
α : Type u_1
f : ℕ → Option α
h : ∃ n a, a ∈ f n
h' : ∃ n, Option.isSome (f n) = true
⊢ (rfindOpt f).Dom

Next tactic:
have s := Nat.find_spec h'
theorem rfindOpt_dom {α} {f : ℕ → Option α} : (rfindOpt f).Dom ↔ ∃ n a, a ∈ f n :=
  ⟨fun h => (rfindOpt_spec ⟨h, rfl⟩).imp fun n h => ⟨_, h⟩, fun h => by
    have h' : ∃ n, (f n).isSome := h.imp fun n => Option.isSome_iff_exists.2
    have s := Nat.find_spec h'
    

Proof state:
α : Type u_1
f : ℕ → Option α
h : ∃ n a, a ∈ f n
h' : ∃ n, Option.isSome (f n) = true
s : Option.isSome (f (Nat.find h')) = true
⊢ (rfindOpt f).Dom

Next tactic:
have fd : (rfind fun n => (f n).isSome).Dom :=
      ⟨Nat.find h', by simpa using s.symm, fun _ _ => trivial⟩
theorem rfindOpt_dom {α} {f : ℕ → Option α} : (rfindOpt f).Dom ↔ ∃ n a, a ∈ f n :=
  ⟨fun h => (rfindOpt_spec ⟨h, rfl⟩).imp fun n h => ⟨_, h⟩, fun h => by
    have h' : ∃ n, (f n).isSome := h.imp fun n => Option.isSome_iff_exists.2
    have s := Nat.find_spec h'
    have fd : (rfind fun n => (f n).isSome).Dom :=
      ⟨Nat.find h', by 

Proof state:
α : Type u_1
f : ℕ → Option α
h : ∃ n a, a ∈ f n
h' : ∃ n, Option.isSome (f n) = true
s : Option.isSome (f (Nat.find h')) = true
⊢ true ∈ (fun n => ↑(Option.some (Option.isSome (f n)))) (Nat.find h')

Next tactic:
simpa using s.symm
theorem rfindOpt_dom {α} {f : ℕ → Option α} : (rfindOpt f).Dom ↔ ∃ n a, a ∈ f n :=
  ⟨fun h => (rfindOpt_spec ⟨h, rfl⟩).imp fun n h => ⟨_, h⟩, fun h => by
    have h' : ∃ n, (f n).isSome := h.imp fun n => Option.isSome_iff_exists.2
    have s := Nat.find_spec h'
    have fd : (rfind fun n => (f n).isSome).Dom :=
      ⟨Nat.find h', by simpa using s.symm, fun _ _ => trivial⟩
    

Proof state:
α : Type u_1
f : ℕ → Option α
h : ∃ n a, a ∈ f n
h' : ∃ n, Option.isSome (f n) = true
s : Option.isSome (f (Nat.find h')) = true
fd : (rfind fun n => ↑(Option.some (Option.isSome (f n)))).Dom
⊢ (rfindOpt f).Dom

Next tactic:
refine' ⟨fd, _⟩
theorem rfindOpt_dom {α} {f : ℕ → Option α} : (rfindOpt f).Dom ↔ ∃ n a, a ∈ f n :=
  ⟨fun h => (rfindOpt_spec ⟨h, rfl⟩).imp fun n h => ⟨_, h⟩, fun h => by
    have h' : ∃ n, (f n).isSome := h.imp fun n => Option.isSome_iff_exists.2
    have s := Nat.find_spec h'
    have fd : (rfind fun n => (f n).isSome).Dom :=
      ⟨Nat.find h', by simpa using s.symm, fun _ _ => trivial⟩
    refine' ⟨fd, _⟩
    

Proof state:
α : Type u_1
f : ℕ → Option α
h : ∃ n a, a ∈ f n
h' : ∃ n, Option.isSome (f n) = true
s : Option.isSome (f (Nat.find h')) = true
fd : (rfind fun n => ↑(Option.some (Option.isSome (f n)))).Dom
⊢ ((fun b => (fun n => ↑(f n)) (Part.get (rfind fun n => ↑(Option.some (Option.isSome (f n)))) b)) fd).Dom

Next tactic:
have := rfind_spec (get_mem fd)
theorem rfindOpt_dom {α} {f : ℕ → Option α} : (rfindOpt f).Dom ↔ ∃ n a, a ∈ f n :=
  ⟨fun h => (rfindOpt_spec ⟨h, rfl⟩).imp fun n h => ⟨_, h⟩, fun h => by
    have h' : ∃ n, (f n).isSome := h.imp fun n => Option.isSome_iff_exists.2
    have s := Nat.find_spec h'
    have fd : (rfind fun n => (f n).isSome).Dom :=
      ⟨Nat.find h', by simpa using s.symm, fun _ _ => trivial⟩
    refine' ⟨fd, _⟩
    have := rfind_spec (get_mem fd)
    

Proof state:
α : Type u_1
f : ℕ → Option α
h : ∃ n a, a ∈ f n
h' : ∃ n, Option.isSome (f n) = true
s : Option.isSome (f (Nat.find h')) = true
fd : (rfind fun n => ↑(Option.some (Option.isSome (f n)))).Dom
this : true ∈ ↑(Option.some (Option.isSome (f (Part.get (rfind fun n => ↑(Option.some (Option.isSome (f n)))) fd))))
⊢ ((fun b => (fun n => ↑(f n)) (Part.get (rfind fun n => ↑(Option.some (Option.isSome (f n)))) b)) fd).Dom

Next tactic:
simp? at this ⊢ says simp only [coe_some, mem_some_iff, ofOption_dom] at this ⊢
theorem rfindOpt_dom {α} {f : ℕ → Option α} : (rfindOpt f).Dom ↔ ∃ n a, a ∈ f n :=
  ⟨fun h => (rfindOpt_spec ⟨h, rfl⟩).imp fun n h => ⟨_, h⟩, fun h => by
    have h' : ∃ n, (f n).isSome := h.imp fun n => Option.isSome_iff_exists.2
    have s := Nat.find_spec h'
    have fd : (rfind fun n => (f n).isSome).Dom :=
      ⟨Nat.find h', by simpa using s.symm, fun _ _ => trivial⟩
    refine' ⟨fd, _⟩
    have := rfind_spec (get_mem fd)
    simp? at this ⊢ says 

Proof state:
α : Type u_1
f : ℕ → Option α
h : ∃ n a, a ∈ f n
h' : ∃ n, Option.isSome (f n) = true
s : Option.isSome (f (Nat.find h')) = true
fd : (rfind fun n => ↑(Option.some (Option.isSome (f n)))).Dom
this : true ∈ ↑(Option.some (Option.isSome (f (Part.get (rfind fun n => ↑(Option.some (Option.isSome (f n)))) fd))))
⊢ ((fun b => (fun n => ↑(f n)) (Part.get (rfind fun n => ↑(Option.some (Option.isSome (f n)))) b)) fd).Dom

Next tactic:
simp only [coe_some, mem_some_iff, ofOption_dom] at this ⊢
theorem rfindOpt_dom {α} {f : ℕ → Option α} : (rfindOpt f).Dom ↔ ∃ n a, a ∈ f n :=
  ⟨fun h => (rfindOpt_spec ⟨h, rfl⟩).imp fun n h => ⟨_, h⟩, fun h => by
    have h' : ∃ n, (f n).isSome := h.imp fun n => Option.isSome_iff_exists.2
    have s := Nat.find_spec h'
    have fd : (rfind fun n => (f n).isSome).Dom :=
      ⟨Nat.find h', by simpa using s.symm, fun _ _ => trivial⟩
    refine' ⟨fd, _⟩
    have := rfind_spec (get_mem fd)
    simp? at this ⊢ says simp only [coe_some, mem_some_iff, ofOption_dom] at this ⊢
    

Proof state:
α : Type u_1
f : ℕ → Option α
h : ∃ n a, a ∈ f n
h' : ∃ n, Option.isSome (f n) = true
s : Option.isSome (f (Nat.find h')) = true
fd : (rfind fun n => ↑(Option.some (Option.isSome (f n)))).Dom
this :
  true =
    Option.isSome
      (f
        (Part.get (rfind fun n => Part.some (Option.isSome (f n)))
          (_ : (rfind fun n => Part.some (Option.isSome (f n))).Dom)))
⊢ Option.isSome
      (f
        (Part.get (rfind fun n => Part.some (Option.isSome (f n)))
          (_ : (rfind fun n => Part.some (Option.isSome (f n))).Dom))) =
    true

Next tactic:
cases' Option.isSome_iff_exists.1 this.symm with a e
theorem rfindOpt_dom {α} {f : ℕ → Option α} : (rfindOpt f).Dom ↔ ∃ n a, a ∈ f n :=
  ⟨fun h => (rfindOpt_spec ⟨h, rfl⟩).imp fun n h => ⟨_, h⟩, fun h => by
    have h' : ∃ n, (f n).isSome := h.imp fun n => Option.isSome_iff_exists.2
    have s := Nat.find_spec h'
    have fd : (rfind fun n => (f n).isSome).Dom :=
      ⟨Nat.find h', by simpa using s.symm, fun _ _ => trivial⟩
    refine' ⟨fd, _⟩
    have := rfind_spec (get_mem fd)
    simp? at this ⊢ says simp only [coe_some, mem_some_iff, ofOption_dom] at this ⊢
    cases' Option.isSome_iff_exists.1 this.symm with a e
    

Proof state:
case intro
α : Type u_1
f : ℕ → Option α
h : ∃ n a, a ∈ f n
h' : ∃ n, Option.isSome (f n) = true
s : Option.isSome (f (Nat.find h')) = true
fd : (rfind fun n => ↑(Option.some (Option.isSome (f n)))).Dom
this :
  true =
    Option.isSome
      (f
        (Part.get (rfind fun n => Part.some (Option.isSome (f n)))
          (_ : (rfind fun n => Part.some (Option.isSome (f n))).Dom)))
a : α
e :
  f
      (Part.get (rfind fun n => Part.some (Option.isSome (f n)))
        (_ : (rfind fun n => Part.some (Option.isSome (f n))).Dom)) =
    Option.some a
⊢ Option.isSome
      (f
        (Part.get (rfind fun n => Part.some (Option.isSome (f n)))
          (_ : (rfind fun n => Part.some (Option.isSome (f n))).Dom))) =
    true

Next tactic:
rw [e]
theorem rfindOpt_dom {α} {f : ℕ → Option α} : (rfindOpt f).Dom ↔ ∃ n a, a ∈ f n :=
  ⟨fun h => (rfindOpt_spec ⟨h, rfl⟩).imp fun n h => ⟨_, h⟩, fun h => by
    have h' : ∃ n, (f n).isSome := h.imp fun n => Option.isSome_iff_exists.2
    have s := Nat.find_spec h'
    have fd : (rfind fun n => (f n).isSome).Dom :=
      ⟨Nat.find h', by simpa using s.symm, fun _ _ => trivial⟩
    refine' ⟨fd, _⟩
    have := rfind_spec (get_mem fd)
    simp? at this ⊢ says simp only [coe_some, mem_some_iff, ofOption_dom] at this ⊢
    cases' Option.isSome_iff_exists.1 this.symm with a e
    rw [e]; 

Proof state:
case intro
α : Type u_1
f : ℕ → Option α
h : ∃ n a, a ∈ f n
h' : ∃ n, Option.isSome (f n) = true
s : Option.isSome (f (Nat.find h')) = true
fd : (rfind fun n => ↑(Option.some (Option.isSome (f n)))).Dom
this :
  true =
    Option.isSome
      (f
        (Part.get (rfind fun n => Part.some (Option.isSome (f n)))
          (_ : (rfind fun n => Part.some (Option.isSome (f n))).Dom)))
a : α
e :
  f
      (Part.get (rfind fun n => Part.some (Option.isSome (f n)))
        (_ : (rfind fun n => Part.some (Option.isSome (f n))).Dom)) =
    Option.some a
⊢ Option.isSome (Option.some a) = true

Next tactic:
trivial
theorem rfindOpt_mono {α} {f : ℕ → Option α} (H : ∀ {a m n}, m ≤ n → a ∈ f m → a ∈ f n) {a} :
    a ∈ rfindOpt f ↔ ∃ n, a ∈ f n :=
  ⟨rfindOpt_spec, fun ⟨n, h⟩ => by
    

Proof state:
α : Type u_1
f : ℕ → Option α
H : ∀ {a : α} {m n : ℕ}, m ≤ n → a ∈ f m → a ∈ f n
a : α
x✝ : ∃ n, a ∈ f n
n : ℕ
h : a ∈ f n
⊢ a ∈ rfindOpt f

Next tactic:
have h' := rfindOpt_dom.2 ⟨_, _, h⟩
theorem rfindOpt_mono {α} {f : ℕ → Option α} (H : ∀ {a m n}, m ≤ n → a ∈ f m → a ∈ f n) {a} :
    a ∈ rfindOpt f ↔ ∃ n, a ∈ f n :=
  ⟨rfindOpt_spec, fun ⟨n, h⟩ => by
    have h' := rfindOpt_dom.2 ⟨_, _, h⟩
    

Proof state:
α : Type u_1
f : ℕ → Option α
H : ∀ {a : α} {m n : ℕ}, m ≤ n → a ∈ f m → a ∈ f n
a : α
x✝ : ∃ n, a ∈ f n
n : ℕ
h : a ∈ f n
h' : (rfindOpt f).Dom
⊢ a ∈ rfindOpt f

Next tactic:
cases' rfindOpt_spec ⟨h', rfl⟩ with k hk
theorem rfindOpt_mono {α} {f : ℕ → Option α} (H : ∀ {a m n}, m ≤ n → a ∈ f m → a ∈ f n) {a} :
    a ∈ rfindOpt f ↔ ∃ n, a ∈ f n :=
  ⟨rfindOpt_spec, fun ⟨n, h⟩ => by
    have h' := rfindOpt_dom.2 ⟨_, _, h⟩
    cases' rfindOpt_spec ⟨h', rfl⟩ with k hk
    

Proof state:
case intro
α : Type u_1
f : ℕ → Option α
H : ∀ {a : α} {m n : ℕ}, m ≤ n → a ∈ f m → a ∈ f n
a : α
x✝ : ∃ n, a ∈ f n
n : ℕ
h : a ∈ f n
h' : (rfindOpt f).Dom
k : ℕ
hk : Part.get (rfindOpt f) h' ∈ f k
⊢ a ∈ rfindOpt f

Next tactic:
have := (H (le_max_left _ _) h).symm.trans (H (le_max_right _ _) hk)
theorem rfindOpt_mono {α} {f : ℕ → Option α} (H : ∀ {a m n}, m ≤ n → a ∈ f m → a ∈ f n) {a} :
    a ∈ rfindOpt f ↔ ∃ n, a ∈ f n :=
  ⟨rfindOpt_spec, fun ⟨n, h⟩ => by
    have h' := rfindOpt_dom.2 ⟨_, _, h⟩
    cases' rfindOpt_spec ⟨h', rfl⟩ with k hk
    have := (H (le_max_left _ _) h).symm.trans (H (le_max_right _ _) hk)
    

Proof state:
case intro
α : Type u_1
f : ℕ → Option α
H : ∀ {a : α} {m n : ℕ}, m ≤ n → a ∈ f m → a ∈ f n
a : α
x✝ : ∃ n, a ∈ f n
n : ℕ
h : a ∈ f n
h' : (rfindOpt f).Dom
k : ℕ
hk : Part.get (rfindOpt f) h' ∈ f k
this : Option.some a = Option.some (Part.get (rfindOpt f) h')
⊢ a ∈ rfindOpt f

Next tactic:
simp at this
theorem rfindOpt_mono {α} {f : ℕ → Option α} (H : ∀ {a m n}, m ≤ n → a ∈ f m → a ∈ f n) {a} :
    a ∈ rfindOpt f ↔ ∃ n, a ∈ f n :=
  ⟨rfindOpt_spec, fun ⟨n, h⟩ => by
    have h' := rfindOpt_dom.2 ⟨_, _, h⟩
    cases' rfindOpt_spec ⟨h', rfl⟩ with k hk
    have := (H (le_max_left _ _) h).symm.trans (H (le_max_right _ _) hk)
    simp at this; 

Proof state:
case intro
α : Type u_1
f : ℕ → Option α
H : ∀ {a : α} {m n : ℕ}, m ≤ n → a ∈ f m → a ∈ f n
a : α
x✝ : ∃ n, a ∈ f n
n : ℕ
h : a ∈ f n
h' : (rfindOpt f).Dom
k : ℕ
hk : Part.get (rfindOpt f) h' ∈ f k
this : a = Part.get (rfindOpt f) h'
⊢ a ∈ rfindOpt f

Next tactic:
simp [this, get_mem]
theorem of_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) : Partrec f := by
  

Proof state:
f : ℕ → ℕ
hf : Nat.Primrec f
⊢ Partrec ↑f

Next tactic:
induction hf with
  | zero => exact zero
  | succ => exact succ
  | left => exact left
  | right => exact right
  | pair _ _ pf pg =>
    refine' (pf.pair pg).of_eq_tot fun n => _
    simp [Seq.seq]
  | comp _ _ pf pg =>
    refine' (pf.comp pg).of_eq_tot fun n => _
    simp
  | prec _ _ pf pg =>
    refine' (pf.prec pg).of_eq_tot fun n => _
    simp only [unpaired, PFun.coe_val, bind_eq_bind]
    induction n.unpair.2 with
    | zero => simp
    | succ m IH =>
      simp only [mem_bind_iff, mem_some_iff]
      exact ⟨_, IH, rfl⟩
theorem of_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) : Partrec f := by
  induction hf with
  

Proof state:
case zero
f : ℕ → ℕ
⊢ Partrec ↑fun x => 0

Next tactic:
| zero => exact zero
theorem of_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) : Partrec f := by
  induction hf with
  | zero => 

Proof state:
case zero
f : ℕ → ℕ
⊢ Partrec ↑fun x => 0

Next tactic:
exact zero
theorem of_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) : Partrec f := by
  induction hf with
  | zero => exact zero
  

Proof state:
case succ
f : ℕ → ℕ
⊢ Partrec ↑Nat.succ

Next tactic:
| succ => exact succ
theorem of_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) : Partrec f := by
  induction hf with
  | zero => exact zero
  | succ => 

Proof state:
case succ
f : ℕ → ℕ
⊢ Partrec ↑Nat.succ

Next tactic:
exact succ
theorem of_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) : Partrec f := by
  induction hf with
  | zero => exact zero
  | succ => exact succ
  

Proof state:
case left
f : ℕ → ℕ
⊢ Partrec ↑fun n => (unpair n).1

Next tactic:
| left => exact left
theorem of_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) : Partrec f := by
  induction hf with
  | zero => exact zero
  | succ => exact succ
  | left => 

Proof state:
case left
f : ℕ → ℕ
⊢ Partrec ↑fun n => (unpair n).1

Next tactic:
exact left
theorem of_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) : Partrec f := by
  induction hf with
  | zero => exact zero
  | succ => exact succ
  | left => exact left
  

Proof state:
case right
f : ℕ → ℕ
⊢ Partrec ↑fun n => (unpair n).2

Next tactic:
| right => exact right
theorem of_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) : Partrec f := by
  induction hf with
  | zero => exact zero
  | succ => exact succ
  | left => exact left
  | right => 

Proof state:
case right
f : ℕ → ℕ
⊢ Partrec ↑fun n => (unpair n).2

Next tactic:
exact right
theorem of_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) : Partrec f := by
  induction hf with
  | zero => exact zero
  | succ => exact succ
  | left => exact left
  | right => exact right
  

Proof state:
case pair
f f✝ g✝ : ℕ → ℕ
a✝¹ : Nat.Primrec f✝
a✝ : Nat.Primrec g✝
pf : Partrec ↑f✝
pg : Partrec ↑g✝
⊢ Partrec ↑fun n => Nat.pair (f✝ n) (g✝ n)

Next tactic:
| pair _ _ pf pg =>
    refine' (pf.pair pg).of_eq_tot fun n => _
    simp [Seq.seq]
theorem of_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) : Partrec f := by
  induction hf with
  | zero => exact zero
  | succ => exact succ
  | left => exact left
  | right => exact right
  | pair _ _ pf pg =>
    

Proof state:
case pair
f f✝ g✝ : ℕ → ℕ
a✝¹ : Nat.Primrec f✝
a✝ : Nat.Primrec g✝
pf : Partrec ↑f✝
pg : Partrec ↑g✝
⊢ Partrec ↑fun n => Nat.pair (f✝ n) (g✝ n)

Next tactic:
refine' (pf.pair pg).of_eq_tot fun n => _
theorem of_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) : Partrec f := by
  induction hf with
  | zero => exact zero
  | succ => exact succ
  | left => exact left
  | right => exact right
  | pair _ _ pf pg =>
    refine' (pf.pair pg).of_eq_tot fun n => _
    

Proof state:
case pair
f f✝ g✝ : ℕ → ℕ
a✝¹ : Nat.Primrec f✝
a✝ : Nat.Primrec g✝
pf : Partrec ↑f✝
pg : Partrec ↑g✝
n : ℕ
⊢ Nat.pair (f✝ n) (g✝ n) ∈ Seq.seq (Nat.pair <$> ↑f✝ n) fun x => ↑g✝ n

Next tactic:
simp [Seq.seq]
theorem of_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) : Partrec f := by
  induction hf with
  | zero => exact zero
  | succ => exact succ
  | left => exact left
  | right => exact right
  | pair _ _ pf pg =>
    refine' (pf.pair pg).of_eq_tot fun n => _
    simp [Seq.seq]
  

Proof state:
case comp
f f✝ g✝ : ℕ → ℕ
a✝¹ : Nat.Primrec f✝
a✝ : Nat.Primrec g✝
pf : Partrec ↑f✝
pg : Partrec ↑g✝
⊢ Partrec ↑fun n => f✝ (g✝ n)

Next tactic:
| comp _ _ pf pg =>
    refine' (pf.comp pg).of_eq_tot fun n => _
    simp
theorem of_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) : Partrec f := by
  induction hf with
  | zero => exact zero
  | succ => exact succ
  | left => exact left
  | right => exact right
  | pair _ _ pf pg =>
    refine' (pf.pair pg).of_eq_tot fun n => _
    simp [Seq.seq]
  | comp _ _ pf pg =>
    

Proof state:
case comp
f f✝ g✝ : ℕ → ℕ
a✝¹ : Nat.Primrec f✝
a✝ : Nat.Primrec g✝
pf : Partrec ↑f✝
pg : Partrec ↑g✝
⊢ Partrec ↑fun n => f✝ (g✝ n)

Next tactic:
refine' (pf.comp pg).of_eq_tot fun n => _
theorem of_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) : Partrec f := by
  induction hf with
  | zero => exact zero
  | succ => exact succ
  | left => exact left
  | right => exact right
  | pair _ _ pf pg =>
    refine' (pf.pair pg).of_eq_tot fun n => _
    simp [Seq.seq]
  | comp _ _ pf pg =>
    refine' (pf.comp pg).of_eq_tot fun n => _
    

Proof state:
case comp
f f✝ g✝ : ℕ → ℕ
a✝¹ : Nat.Primrec f✝
a✝ : Nat.Primrec g✝
pf : Partrec ↑f✝
pg : Partrec ↑g✝
n : ℕ
⊢ f✝ (g✝ n) ∈ ↑g✝ n >>= ↑f✝

Next tactic:
simp
theorem of_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) : Partrec f := by
  induction hf with
  | zero => exact zero
  | succ => exact succ
  | left => exact left
  | right => exact right
  | pair _ _ pf pg =>
    refine' (pf.pair pg).of_eq_tot fun n => _
    simp [Seq.seq]
  | comp _ _ pf pg =>
    refine' (pf.comp pg).of_eq_tot fun n => _
    simp
  

Proof state:
case prec
f f✝ g✝ : ℕ → ℕ
a✝¹ : Nat.Primrec f✝
a✝ : Nat.Primrec g✝
pf : Partrec ↑f✝
pg : Partrec ↑g✝
⊢ Partrec ↑(unpaired fun z n => Nat.rec (f✝ z) (fun y IH => g✝ (Nat.pair z (Nat.pair y IH))) n)

Next tactic:
| prec _ _ pf pg =>
    refine' (pf.prec pg).of_eq_tot fun n => _
    simp only [unpaired, PFun.coe_val, bind_eq_bind]
    induction n.unpair.2 with
    | zero => simp
    | succ m IH =>
      simp only [mem_bind_iff, mem_some_iff]
      exact ⟨_, IH, rfl⟩
theorem of_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) : Partrec f := by
  induction hf with
  | zero => exact zero
  | succ => exact succ
  | left => exact left
  | right => exact right
  | pair _ _ pf pg =>
    refine' (pf.pair pg).of_eq_tot fun n => _
    simp [Seq.seq]
  | comp _ _ pf pg =>
    refine' (pf.comp pg).of_eq_tot fun n => _
    simp
  | prec _ _ pf pg =>
    

Proof state:
case prec
f f✝ g✝ : ℕ → ℕ
a✝¹ : Nat.Primrec f✝
a✝ : Nat.Primrec g✝
pf : Partrec ↑f✝
pg : Partrec ↑g✝
⊢ Partrec ↑(unpaired fun z n => Nat.rec (f✝ z) (fun y IH => g✝ (Nat.pair z (Nat.pair y IH))) n)

Next tactic:
refine' (pf.prec pg).of_eq_tot fun n => _
theorem of_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) : Partrec f := by
  induction hf with
  | zero => exact zero
  | succ => exact succ
  | left => exact left
  | right => exact right
  | pair _ _ pf pg =>
    refine' (pf.pair pg).of_eq_tot fun n => _
    simp [Seq.seq]
  | comp _ _ pf pg =>
    refine' (pf.comp pg).of_eq_tot fun n => _
    simp
  | prec _ _ pf pg =>
    refine' (pf.prec pg).of_eq_tot fun n => _
    

Proof state:
case prec
f f✝ g✝ : ℕ → ℕ
a✝¹ : Nat.Primrec f✝
a✝ : Nat.Primrec g✝
pf : Partrec ↑f✝
pg : Partrec ↑g✝
n : ℕ
⊢ unpaired (fun z n => Nat.rec (f✝ z) (fun y IH => g✝ (Nat.pair z (Nat.pair y IH))) n) n ∈
    unpaired
      (fun a n =>
        Nat.rec (↑f✝ a)
          (fun y IH => do
            let i ← IH
            ↑g✝ (Nat.pair a (Nat.pair y i)))
          n)
      n

Next tactic:
simp only [unpaired, PFun.coe_val, bind_eq_bind]
theorem of_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) : Partrec f := by
  induction hf with
  | zero => exact zero
  | succ => exact succ
  | left => exact left
  | right => exact right
  | pair _ _ pf pg =>
    refine' (pf.pair pg).of_eq_tot fun n => _
    simp [Seq.seq]
  | comp _ _ pf pg =>
    refine' (pf.comp pg).of_eq_tot fun n => _
    simp
  | prec _ _ pf pg =>
    refine' (pf.prec pg).of_eq_tot fun n => _
    simp only [unpaired, PFun.coe_val, bind_eq_bind]
    

Proof state:
case prec
f f✝ g✝ : ℕ → ℕ
a✝¹ : Nat.Primrec f✝
a✝ : Nat.Primrec g✝
pf : Partrec ↑f✝
pg : Partrec ↑g✝
n : ℕ
⊢ Nat.rec (f✝ (unpair n).1) (fun y IH => g✝ (Nat.pair (unpair n).1 (Nat.pair y IH))) (unpair n).2 ∈
    Nat.rec (Part.some (f✝ (unpair n).1))
      (fun y IH => Part.bind IH fun i => Part.some (g✝ (Nat.pair (unpair n).1 (Nat.pair y i)))) (unpair n).2

Next tactic:
induction n.unpair.2 with
    | zero => simp
    | succ m IH =>
      simp only [mem_bind_iff, mem_some_iff]
      exact ⟨_, IH, rfl⟩
theorem of_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) : Partrec f := by
  induction hf with
  | zero => exact zero
  | succ => exact succ
  | left => exact left
  | right => exact right
  | pair _ _ pf pg =>
    refine' (pf.pair pg).of_eq_tot fun n => _
    simp [Seq.seq]
  | comp _ _ pf pg =>
    refine' (pf.comp pg).of_eq_tot fun n => _
    simp
  | prec _ _ pf pg =>
    refine' (pf.prec pg).of_eq_tot fun n => _
    simp only [unpaired, PFun.coe_val, bind_eq_bind]
    

Proof state:
case prec
f f✝ g✝ : ℕ → ℕ
a✝¹ : Nat.Primrec f✝
a✝ : Nat.Primrec g✝
pf : Partrec ↑f✝
pg : Partrec ↑g✝
n x✝ : ℕ
⊢ Nat.rec (f✝ (unpair n).1) (fun y IH => g✝ (Nat.pair (unpair n).1 (Nat.pair y IH))) x✝ ∈
    Nat.rec (Part.some (f✝ (unpair n).1))
      (fun y IH => Part.bind IH fun i => Part.some (g✝ (Nat.pair (unpair n).1 (Nat.pair y i)))) x✝

Next tactic:
induction n.unpair.2 with
    | zero => simp
    | succ m IH =>
      simp only [mem_bind_iff, mem_some_iff]
      exact ⟨_, IH, rfl⟩
theorem of_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) : Partrec f := by
  induction hf with
  | zero => exact zero
  | succ => exact succ
  | left => exact left
  | right => exact right
  | pair _ _ pf pg =>
    refine' (pf.pair pg).of_eq_tot fun n => _
    simp [Seq.seq]
  | comp _ _ pf pg =>
    refine' (pf.comp pg).of_eq_tot fun n => _
    simp
  | prec _ _ pf pg =>
    refine' (pf.prec pg).of_eq_tot fun n => _
    simp only [unpaired, PFun.coe_val, bind_eq_bind]
    induction n.unpair.2 with
    

Proof state:
case prec.zero
f f✝ g✝ : ℕ → ℕ
a✝¹ : Nat.Primrec f✝
a✝ : Nat.Primrec g✝
pf : Partrec ↑f✝
pg : Partrec ↑g✝
n : ℕ
⊢ Nat.rec (f✝ (unpair n).1) (fun y IH => g✝ (Nat.pair (unpair n).1 (Nat.pair y IH))) Nat.zero ∈
    Nat.rec (Part.some (f✝ (unpair n).1))
      (fun y IH => Part.bind IH fun i => Part.some (g✝ (Nat.pair (unpair n).1 (Nat.pair y i)))) Nat.zero

Next tactic:
| zero => simp