l3lab/ntp-mathlib huggingface dataset:
/-- Helper lemma for the evaluation of `prec` in the base case. -/
@[simp]
theorem eval_prec_zero (cf cg : Code) (a : ℕ) : eval (prec cf cg) (Nat.pair a 0) = eval cf a := by
  rw [eval, Nat.unpaired, Nat.unpair_pair]
  simp (config := { Lean.Meta.Simp.neutralConfig with proj := true }) only []
  

Proof state:
cf cg : Code
a : ℕ
⊢ Nat.rec (eval cf a)
      (fun y IH => do
        let i ← IH
        eval cg (Nat.pair a (Nat.pair y i)))
      0 =
    eval cf a

Next tactic:
rw [Nat.rec_zero]
/-- Helper lemma for the evaluation of `prec` in the recursive case. -/
theorem eval_prec_succ (cf cg : Code) (a k : ℕ) :
    eval (prec cf cg) (Nat.pair a (Nat.succ k)) =
      do {let ih ← eval (prec cf cg) (Nat.pair a k); eval cg (Nat.pair a (Nat.pair k ih))} := by
  

Proof state:
cf cg : Code
a k : ℕ
⊢ eval (prec cf cg) (Nat.pair a (Nat.succ k)) = do
    let ih ← eval (prec cf cg) (Nat.pair a k)
    eval cg (Nat.pair a (Nat.pair k ih))

Next tactic:
rw [eval, Nat.unpaired, Part.bind_eq_bind, Nat.unpair_pair]
/-- Helper lemma for the evaluation of `prec` in the recursive case. -/
theorem eval_prec_succ (cf cg : Code) (a k : ℕ) :
    eval (prec cf cg) (Nat.pair a (Nat.succ k)) =
      do {let ih ← eval (prec cf cg) (Nat.pair a k); eval cg (Nat.pair a (Nat.pair k ih))} := by
  rw [eval, Nat.unpaired, Part.bind_eq_bind, Nat.unpair_pair]
  

Proof state:
cf cg : Code
a k : ℕ
⊢ Nat.rec (eval cf (a, Nat.succ k).1)
      (fun y IH => do
        let i ← IH
        eval cg (Nat.pair (a, Nat.succ k).1 (Nat.pair y i)))
      (a, Nat.succ k).2 =
    Part.bind
      (unpaired
        (fun a n =>
          Nat.rec (eval cf a)
            (fun y IH => do
              let i ← IH
              eval cg (Nat.pair a (Nat.pair y i)))
            n)
        (Nat.pair a k))
      fun ih => eval cg (Nat.pair a (Nat.pair k ih))

Next tactic:
simp
@[simp]
theorem eval_const : ∀ n m, eval (Code.const n) m = Part.some n
  | 0, m => rfl
  | n + 1, m => by 

Proof state:
n m : ℕ
⊢ eval (Code.const (n + 1)) m = Part.some (n + 1)

Next tactic:
simp! [eval_const n m]
@[simp]
theorem eval_id (n) : eval Code.id n = Part.some n := by 

Proof state:
n : ℕ
⊢ eval Code.id n = Part.some n

Next tactic:
simp! [Seq.seq]
@[simp]
theorem eval_curry (c n x) : eval (curry c n) x = eval c (Nat.pair n x) := by 

Proof state:
c : Code
n x : ℕ
⊢ eval (curry c n) x = eval c (Nat.pair n x)

Next tactic:
simp! [Seq.seq]
theorem const_prim : Primrec Code.const :=
  (_root_.Primrec.id.nat_iterate (_root_.Primrec.const zero)
    (comp_prim.comp (_root_.Primrec.const succ) Primrec.snd).to₂).of_eq
    fun n => by 

Proof state:
n : ℕ
⊢ (fun b => comp succ (n, b).2)^[id n] zero = Code.const n

Next tactic:
simp
theorem const_prim : Primrec Code.const :=
  (_root_.Primrec.id.nat_iterate (_root_.Primrec.const zero)
    (comp_prim.comp (_root_.Primrec.const succ) Primrec.snd).to₂).of_eq
    fun n => by simp; 

Proof state:
n : ℕ
⊢ (fun b => comp succ b)^[n] zero = Code.const n

Next tactic:
induction n
theorem const_prim : Primrec Code.const :=
  (_root_.Primrec.id.nat_iterate (_root_.Primrec.const zero)
    (comp_prim.comp (_root_.Primrec.const succ) Primrec.snd).to₂).of_eq
    fun n => by simp; induction n <;>
      

Proof state:
case zero
⊢ (fun b => comp succ b)^[Nat.zero] zero = Code.const Nat.zero

Next tactic:
simp [*, Code.const, Function.iterate_succ', -Function.iterate_succ]
theorem const_prim : Primrec Code.const :=
  (_root_.Primrec.id.nat_iterate (_root_.Primrec.const zero)
    (comp_prim.comp (_root_.Primrec.const succ) Primrec.snd).to₂).of_eq
    fun n => by simp; induction n <;>
      

Proof state:
case succ
n✝ : ℕ
n_ih✝ : (fun b => comp succ b)^[n✝] zero = Code.const n✝
⊢ (fun b => comp succ b)^[Nat.succ n✝] zero = Code.const (Nat.succ n✝)

Next tactic:
simp [*, Code.const, Function.iterate_succ', -Function.iterate_succ]
theorem curry_inj {c₁ c₂ n₁ n₂} (h : curry c₁ n₁ = curry c₂ n₂) : c₁ = c₂ ∧ n₁ = n₂ :=
  ⟨by 

Proof state:
c₁ c₂ : Code
n₁ n₂ : ℕ
h : curry c₁ n₁ = curry c₂ n₂
⊢ c₁ = c₂

Next tactic:
injection h
theorem curry_inj {c₁ c₂ n₁ n₂} (h : curry c₁ n₁ = curry c₂ n₂) : c₁ = c₂ ∧ n₁ = n₂ :=
  ⟨by injection h, by
    

Proof state:
c₁ c₂ : Code
n₁ n₂ : ℕ
h : curry c₁ n₁ = curry c₂ n₂
⊢ n₁ = n₂

Next tactic:
injection h with h₁ h₂
theorem curry_inj {c₁ c₂ n₁ n₂} (h : curry c₁ n₁ = curry c₂ n₂) : c₁ = c₂ ∧ n₁ = n₂ :=
  ⟨by injection h, by
    injection h with h₁ h₂
    

Proof state:
c₁ c₂ : Code
n₁ n₂ : ℕ
h₁ : c₁ = c₂
h₂ : pair (Code.const n₁) Code.id = pair (Code.const n₂) Code.id
⊢ n₁ = n₂

Next tactic:
injection h₂ with h₃ h₄
theorem curry_inj {c₁ c₂ n₁ n₂} (h : curry c₁ n₁ = curry c₂ n₂) : c₁ = c₂ ∧ n₁ = n₂ :=
  ⟨by injection h, by
    injection h with h₁ h₂
    injection h₂ with h₃ h₄
    

Proof state:
c₁ c₂ : Code
n₁ n₂ : ℕ
h₁ : c₁ = c₂
h₃ : Code.const n₁ = Code.const n₂
h₄ : Code.id = Code.id
⊢ n₁ = n₂

Next tactic:
exact const_inj h₃
/-- A function is partial recursive if and only if there is a code implementing it. -/
theorem exists_code {f : ℕ →. ℕ} : Nat.Partrec f ↔ ∃ c : Code, eval c = f :=
  ⟨fun h => by
    

Proof state:
f : ℕ →. ℕ
h : Partrec f
⊢ ∃ c, eval c = f

Next tactic:
induction h
/-- A function is partial recursive if and only if there is a code implementing it. -/
theorem exists_code {f : ℕ →. ℕ} : Nat.Partrec f ↔ ∃ c : Code, eval c = f :=
  ⟨fun h => by
    induction h
    

Proof state:
case zero
f : ℕ →. ℕ
⊢ ∃ c, eval c = pure 0
case succ
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑Nat.succ
case left
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑fun n => (unpair n).1
case right
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑fun n => (unpair n).2
case pair
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c, eval c = fun n => Seq.seq (Nat.pair <$> f✝ n) fun x => g✝ n
case comp
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c, eval c = fun n => g✝ n >>= f✝
case prec
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c,
    eval c =
      unpaired fun a n =>
        Nat.rec (f✝ a)
          (fun y IH => do
            let i ← IH
            g✝ (Nat.pair a (Nat.pair y i)))
          n
case rfind
f f✝ : ℕ →. ℕ
a✝ : Partrec f✝
a_ih✝ : ∃ c, eval c = f✝
⊢ ∃ c, eval c = fun a => Nat.rfind fun n => (fun m => decide (m = 0)) <$> f✝ (Nat.pair a n)

Next tactic:
case zero => exact ⟨zero, rfl⟩
/-- A function is partial recursive if and only if there is a code implementing it. -/
theorem exists_code {f : ℕ →. ℕ} : Nat.Partrec f ↔ ∃ c : Code, eval c = f :=
  ⟨fun h => by
    induction h
    

Proof state:
f : ℕ →. ℕ
⊢ ∃ c, eval c = pure 0

Next tactic:
case zero => exact ⟨zero, rfl⟩
/-- A function is partial recursive if and only if there is a code implementing it. -/
theorem exists_code {f : ℕ →. ℕ} : Nat.Partrec f ↔ ∃ c : Code, eval c = f :=
  ⟨fun h => by
    induction h
    case zero => 

Proof state:
f : ℕ →. ℕ
⊢ ∃ c, eval c = pure 0

Next tactic:
exact ⟨zero, rfl⟩
/-- A function is partial recursive if and only if there is a code implementing it. -/
theorem exists_code {f : ℕ →. ℕ} : Nat.Partrec f ↔ ∃ c : Code, eval c = f :=
  ⟨fun h => by
    induction h
    case zero => exact ⟨zero, rfl⟩
    

Proof state:
case succ
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑Nat.succ
case left
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑fun n => (unpair n).1
case right
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑fun n => (unpair n).2
case pair
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c, eval c = fun n => Seq.seq (Nat.pair <$> f✝ n) fun x => g✝ n
case comp
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c, eval c = fun n => g✝ n >>= f✝
case prec
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c,
    eval c =
      unpaired fun a n =>
        Nat.rec (f✝ a)
          (fun y IH => do
            let i ← IH
            g✝ (Nat.pair a (Nat.pair y i)))
          n
case rfind
f f✝ : ℕ →. ℕ
a✝ : Partrec f✝
a_ih✝ : ∃ c, eval c = f✝
⊢ ∃ c, eval c = fun a => Nat.rfind fun n => (fun m => decide (m = 0)) <$> f✝ (Nat.pair a n)

Next tactic:
case succ => exact ⟨succ, rfl⟩
/-- A function is partial recursive if and only if there is a code implementing it. -/
theorem exists_code {f : ℕ →. ℕ} : Nat.Partrec f ↔ ∃ c : Code, eval c = f :=
  ⟨fun h => by
    induction h
    case zero => exact ⟨zero, rfl⟩
    

Proof state:
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑Nat.succ

Next tactic:
case succ => exact ⟨succ, rfl⟩
/-- A function is partial recursive if and only if there is a code implementing it. -/
theorem exists_code {f : ℕ →. ℕ} : Nat.Partrec f ↔ ∃ c : Code, eval c = f :=
  ⟨fun h => by
    induction h
    case zero => exact ⟨zero, rfl⟩
    case succ => 

Proof state:
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑Nat.succ

Next tactic:
exact ⟨succ, rfl⟩
/-- A function is partial recursive if and only if there is a code implementing it. -/
theorem exists_code {f : ℕ →. ℕ} : Nat.Partrec f ↔ ∃ c : Code, eval c = f :=
  ⟨fun h => by
    induction h
    case zero => exact ⟨zero, rfl⟩
    case succ => exact ⟨succ, rfl⟩
    

Proof state:
case left
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑fun n => (unpair n).1
case right
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑fun n => (unpair n).2
case pair
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c, eval c = fun n => Seq.seq (Nat.pair <$> f✝ n) fun x => g✝ n
case comp
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c, eval c = fun n => g✝ n >>= f✝
case prec
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c,
    eval c =
      unpaired fun a n =>
        Nat.rec (f✝ a)
          (fun y IH => do
            let i ← IH
            g✝ (Nat.pair a (Nat.pair y i)))
          n
case rfind
f f✝ : ℕ →. ℕ
a✝ : Partrec f✝
a_ih✝ : ∃ c, eval c = f✝
⊢ ∃ c, eval c = fun a => Nat.rfind fun n => (fun m => decide (m = 0)) <$> f✝ (Nat.pair a n)

Next tactic:
case left => exact ⟨left, rfl⟩
/-- A function is partial recursive if and only if there is a code implementing it. -/
theorem exists_code {f : ℕ →. ℕ} : Nat.Partrec f ↔ ∃ c : Code, eval c = f :=
  ⟨fun h => by
    induction h
    case zero => exact ⟨zero, rfl⟩
    case succ => exact ⟨succ, rfl⟩
    

Proof state:
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑fun n => (unpair n).1

Next tactic:
case left => exact ⟨left, rfl⟩
/-- A function is partial recursive if and only if there is a code implementing it. -/
theorem exists_code {f : ℕ →. ℕ} : Nat.Partrec f ↔ ∃ c : Code, eval c = f :=
  ⟨fun h => by
    induction h
    case zero => exact ⟨zero, rfl⟩
    case succ => exact ⟨succ, rfl⟩
    case left => 

Proof state:
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑fun n => (unpair n).1

Next tactic:
exact ⟨left, rfl⟩
/-- A function is partial recursive if and only if there is a code implementing it. -/
theorem exists_code {f : ℕ →. ℕ} : Nat.Partrec f ↔ ∃ c : Code, eval c = f :=
  ⟨fun h => by
    induction h
    case zero => exact ⟨zero, rfl⟩
    case succ => exact ⟨succ, rfl⟩
    case left => exact ⟨left, rfl⟩
    

Proof state:
case right
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑fun n => (unpair n).2
case pair
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c, eval c = fun n => Seq.seq (Nat.pair <$> f✝ n) fun x => g✝ n
case comp
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c, eval c = fun n => g✝ n >>= f✝
case prec
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c,
    eval c =
      unpaired fun a n =>
        Nat.rec (f✝ a)
          (fun y IH => do
            let i ← IH
            g✝ (Nat.pair a (Nat.pair y i)))
          n
case rfind
f f✝ : ℕ →. ℕ
a✝ : Partrec f✝
a_ih✝ : ∃ c, eval c = f✝
⊢ ∃ c, eval c = fun a => Nat.rfind fun n => (fun m => decide (m = 0)) <$> f✝ (Nat.pair a n)

Next tactic:
case right => exact ⟨right, rfl⟩
/-- A function is partial recursive if and only if there is a code implementing it. -/
theorem exists_code {f : ℕ →. ℕ} : Nat.Partrec f ↔ ∃ c : Code, eval c = f :=
  ⟨fun h => by
    induction h
    case zero => exact ⟨zero, rfl⟩
    case succ => exact ⟨succ, rfl⟩
    case left => exact ⟨left, rfl⟩
    

Proof state:
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑fun n => (unpair n).2

Next tactic:
case right => exact ⟨right, rfl⟩
/-- A function is partial recursive if and only if there is a code implementing it. -/
theorem exists_code {f : ℕ →. ℕ} : Nat.Partrec f ↔ ∃ c : Code, eval c = f :=
  ⟨fun h => by
    induction h
    case zero => exact ⟨zero, rfl⟩
    case succ => exact ⟨succ, rfl⟩
    case left => exact ⟨left, rfl⟩
    case right => 

Proof state:
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑fun n => (unpair n).2

Next tactic:
exact ⟨right, rfl⟩
/-- A function is partial recursive if and only if there is a code implementing it. -/
theorem exists_code {f : ℕ →. ℕ} : Nat.Partrec f ↔ ∃ c : Code, eval c = f :=
  ⟨fun h => by
    induction h
    case zero => exact ⟨zero, rfl⟩
    case succ => exact ⟨succ, rfl⟩
    case left => exact ⟨left, rfl⟩
    case right => exact ⟨right, rfl⟩
    

Proof state:
case pair
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c, eval c = fun n => Seq.seq (Nat.pair <$> f✝ n) fun x => g✝ n
case comp
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c, eval c = fun n => g✝ n >>= f✝
case prec
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c,
    eval c =
      unpaired fun a n =>
        Nat.rec (f✝ a)
          (fun y IH => do
            let i ← IH
            g✝ (Nat.pair a (Nat.pair y i)))
          n
case rfind
f f✝ : ℕ →. ℕ
a✝ : Partrec f✝
a_ih✝ : ∃ c, eval c = f✝
⊢ ∃ c, eval c = fun a => Nat.rfind fun n => (fun m => decide (m = 0)) <$> f✝ (Nat.pair a n)

Next tactic:
case pair f g pf pg hf hg =>
      rcases hf with ⟨cf, rfl⟩; rcases hg with ⟨cg, rfl⟩
      exact ⟨pair cf cg, rfl⟩
/-- A function is partial recursive if and only if there is a code implementing it. -/
theorem exists_code {f : ℕ →. ℕ} : Nat.Partrec f ↔ ∃ c : Code, eval c = f :=
  ⟨fun h => by
    induction h
    case zero => exact ⟨zero, rfl⟩
    case succ => exact ⟨succ, rfl⟩
    case left => exact ⟨left, rfl⟩
    case right => exact ⟨right, rfl⟩
    

Proof state:
f✝ f g : ℕ →. ℕ
pf : Partrec f
pg : Partrec g
hf : ∃ c, eval c = f
hg : ∃ c, eval c = g
⊢ ∃ c, eval c = fun n => Seq.seq (Nat.pair <$> f n) fun x => g n

Next tactic:
case pair f g pf pg hf hg =>
      rcases hf with ⟨cf, rfl⟩; rcases hg with ⟨cg, rfl⟩
      exact ⟨pair cf cg, rfl⟩
/-- A function is partial recursive if and only if there is a code implementing it. -/
theorem exists_code {f : ℕ →. ℕ} : Nat.Partrec f ↔ ∃ c : Code, eval c = f :=
  ⟨fun h => by
    induction h
    case zero => exact ⟨zero, rfl⟩
    case succ => exact ⟨succ, rfl⟩
    case left => exact ⟨left, rfl⟩
    case right => exact ⟨right, rfl⟩
    case pair f g pf pg hf hg =>
      

Proof state:
f✝ f g : ℕ →. ℕ
pf : Partrec f
pg : Partrec g
hf : ∃ c, eval c = f
hg : ∃ c, eval c = g
⊢ ∃ c, eval c = fun n => Seq.seq (Nat.pair <$> f n) fun x => g n

Next tactic:
rcases hf with ⟨cf, rfl⟩
/-- A function is partial recursive if and only if there is a code implementing it. -/
theorem exists_code {f : ℕ →. ℕ} : Nat.Partrec f ↔ ∃ c : Code, eval c = f :=
  ⟨fun h => by
    induction h
    case zero => exact ⟨zero, rfl⟩
    case succ => exact ⟨succ, rfl⟩
    case left => exact ⟨left, rfl⟩
    case right => exact ⟨right, rfl⟩
    case pair f g pf pg hf hg =>
      rcases hf with ⟨cf, rfl⟩; 

Proof state:
case intro
f g : ℕ →. ℕ
pg : Partrec g
hg : ∃ c, eval c = g
cf : Code
pf : Partrec (eval cf)
⊢ ∃ c, eval c = fun n => Seq.seq (Nat.pair <$> eval cf n) fun x => g n

Next tactic:
rcases hg with ⟨cg, rfl⟩
/-- A function is partial recursive if and only if there is a code implementing it. -/
theorem exists_code {f : ℕ →. ℕ} : Nat.Partrec f ↔ ∃ c : Code, eval c = f :=
  ⟨fun h => by
    induction h
    case zero => exact ⟨zero, rfl⟩
    case succ => exact ⟨succ, rfl⟩
    case left => exact ⟨left, rfl⟩
    case right => exact ⟨right, rfl⟩
    case pair f g pf pg hf hg =>
      rcases hf with ⟨cf, rfl⟩; rcases hg with ⟨cg, rfl⟩
      

Proof state:
case intro.intro
f : ℕ →. ℕ
cf : Code
pf : Partrec (eval cf)
cg : Code
pg : Partrec (eval cg)
⊢ ∃ c, eval c = fun n => Seq.seq (Nat.pair <$> eval cf n) fun x => eval cg n

Next tactic:
exact ⟨pair cf cg, rfl⟩
/-- A function is partial recursive if and only if there is a code implementing it. -/
theorem exists_code {f : ℕ →. ℕ} : Nat.Partrec f ↔ ∃ c : Code, eval c = f :=
  ⟨fun h => by
    induction h
    case zero => exact ⟨zero, rfl⟩
    case succ => exact ⟨succ, rfl⟩
    case left => exact ⟨left, rfl⟩
    case right => exact ⟨right, rfl⟩
    case pair f g pf pg hf hg =>
      rcases hf with ⟨cf, rfl⟩; rcases hg with ⟨cg, rfl⟩
      exact ⟨pair cf cg, rfl⟩
    

Proof state:
case comp
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c, eval c = fun n => g✝ n >>= f✝
case prec
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c,
    eval c =
      unpaired fun a n =>
        Nat.rec (f✝ a)
          (fun y IH => do
            let i ← IH
            g✝ (Nat.pair a (Nat.pair y i)))
          n
case rfind
f f✝ : ℕ →. ℕ
a✝ : Partrec f✝
a_ih✝ : ∃ c, eval c = f✝
⊢ ∃ c, eval c = fun a => Nat.rfind fun n => (fun m => decide (m = 0)) <$> f✝ (Nat.pair a n)

Next tactic:
case comp f g pf pg hf hg =>
      rcases hf with ⟨cf, rfl⟩; rcases hg with ⟨cg, rfl⟩
      exact ⟨comp cf cg, rfl⟩
/-- A function is partial recursive if and only if there is a code implementing it. -/
theorem exists_code {f : ℕ →. ℕ} : Nat.Partrec f ↔ ∃ c : Code, eval c = f :=
  ⟨fun h => by
    induction h
    case zero => exact ⟨zero, rfl⟩
    case succ => exact ⟨succ, rfl⟩
    case left => exact ⟨left, rfl⟩
    case right => exact ⟨right, rfl⟩
    case pair f g pf pg hf hg =>
      rcases hf with ⟨cf, rfl⟩; rcases hg with ⟨cg, rfl⟩
      exact ⟨pair cf cg, rfl⟩
    

Proof state:
f✝ f g : ℕ →. ℕ
pf : Partrec f
pg : Partrec g
hf : ∃ c, eval c = f
hg : ∃ c, eval c = g
⊢ ∃ c, eval c = fun n => g n >>= f

Next tactic:
case comp f g pf pg hf hg =>
      rcases hf with ⟨cf, rfl⟩; rcases hg with ⟨cg, rfl⟩
      exact ⟨comp cf cg, rfl⟩
/-- A function is partial recursive if and only if there is a code implementing it. -/
theorem exists_code {f : ℕ →. ℕ} : Nat.Partrec f ↔ ∃ c : Code, eval c = f :=
  ⟨fun h => by
    induction h
    case zero => exact ⟨zero, rfl⟩
    case succ => exact ⟨succ, rfl⟩
    case left => exact ⟨left, rfl⟩
    case right => exact ⟨right, rfl⟩
    case pair f g pf pg hf hg =>
      rcases hf with ⟨cf, rfl⟩; rcases hg with ⟨cg, rfl⟩
      exact ⟨pair cf cg, rfl⟩
    case comp f g pf pg hf hg =>
      

Proof state:
f✝ f g : ℕ →. ℕ
pf : Partrec f
pg : Partrec g
hf : ∃ c, eval c = f
hg : ∃ c, eval c = g
⊢ ∃ c, eval c = fun n => g n >>= f

Next tactic:
rcases hf with ⟨cf, rfl⟩
/-- A function is partial recursive if and only if there is a code implementing it. -/
theorem exists_code {f : ℕ →. ℕ} : Nat.Partrec f ↔ ∃ c : Code, eval c = f :=
  ⟨fun h => by
    induction h
    case zero => exact ⟨zero, rfl⟩
    case succ => exact ⟨succ, rfl⟩
    case left => exact ⟨left, rfl⟩
    case right => exact ⟨right, rfl⟩
    case pair f g pf pg hf hg =>
      rcases hf with ⟨cf, rfl⟩; rcases hg with ⟨cg, rfl⟩
      exact ⟨pair cf cg, rfl⟩
    case comp f g pf pg hf hg =>
      rcases hf with ⟨cf, rfl⟩; 

Proof state:
case intro
f g : ℕ →. ℕ
pg : Partrec g
hg : ∃ c, eval c = g
cf : Code
pf : Partrec (eval cf)
⊢ ∃ c, eval c = fun n => g n >>= eval cf

Next tactic:
rcases hg with ⟨cg, rfl⟩
/-- A function is partial recursive if and only if there is a code implementing it. -/
theorem exists_code {f : ℕ →. ℕ} : Nat.Partrec f ↔ ∃ c : Code, eval c = f :=
  ⟨fun h => by
    induction h
    case zero => exact ⟨zero, rfl⟩
    case succ => exact ⟨succ, rfl⟩
    case left => exact ⟨left, rfl⟩
    case right => exact ⟨right, rfl⟩
    case pair f g pf pg hf hg =>
      rcases hf with ⟨cf, rfl⟩; rcases hg with ⟨cg, rfl⟩
      exact ⟨pair cf cg, rfl⟩
    case comp f g pf pg hf hg =>
      rcases hf with ⟨cf, rfl⟩; rcases hg with ⟨cg, rfl⟩
      

Proof state:
case intro.intro
f : ℕ →. ℕ
cf : Code
pf : Partrec (eval cf)
cg : Code
pg : Partrec (eval cg)
⊢ ∃ c, eval c = fun n => eval cg n >>= eval cf

Next tactic:
exact ⟨comp cf cg, rfl⟩
/-- A function is partial recursive if and only if there is a code implementing it. -/
theorem exists_code {f : ℕ →. ℕ} : Nat.Partrec f ↔ ∃ c : Code, eval c = f :=
  ⟨fun h => by
    induction h
    case zero => exact ⟨zero, rfl⟩
    case succ => exact ⟨succ, rfl⟩
    case left => exact ⟨left, rfl⟩
    case right => exact ⟨right, rfl⟩
    case pair f g pf pg hf hg =>
      rcases hf with ⟨cf, rfl⟩; rcases hg with ⟨cg, rfl⟩
      exact ⟨pair cf cg, rfl⟩
    case comp f g pf pg hf hg =>
      rcases hf with ⟨cf, rfl⟩; rcases hg with ⟨cg, rfl⟩
      exact ⟨comp cf cg, rfl⟩
    

Proof state:
case prec
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c,
    eval c =
      unpaired fun a n =>
        Nat.rec (f✝ a)
          (fun y IH => do
            let i ← IH
            g✝ (Nat.pair a (Nat.pair y i)))
          n
case rfind
f f✝ : ℕ →. ℕ
a✝ : Partrec f✝
a_ih✝ : ∃ c, eval c = f✝
⊢ ∃ c, eval c = fun a => Nat.rfind fun n => (fun m => decide (m = 0)) <$> f✝ (Nat.pair a n)

Next tactic:
case prec f g pf pg hf hg =>
      rcases hf with ⟨cf, rfl⟩; rcases hg with ⟨cg, rfl⟩
      exact ⟨prec cf cg, rfl⟩
/-- A function is partial recursive if and only if there is a code implementing it. -/
theorem exists_code {f : ℕ →. ℕ} : Nat.Partrec f ↔ ∃ c : Code, eval c = f :=
  ⟨fun h => by
    induction h
    case zero => exact ⟨zero, rfl⟩
    case succ => exact ⟨succ, rfl⟩
    case left => exact ⟨left, rfl⟩
    case right => exact ⟨right, rfl⟩
    case pair f g pf pg hf hg =>
      rcases hf with ⟨cf, rfl⟩; rcases hg with ⟨cg, rfl⟩
      exact ⟨pair cf cg, rfl⟩
    case comp f g pf pg hf hg =>
      rcases hf with ⟨cf, rfl⟩; rcases hg with ⟨cg, rfl⟩
      exact ⟨comp cf cg, rfl⟩
    

Proof state:
f✝ f g : ℕ →. ℕ
pf : Partrec f
pg : Partrec g
hf : ∃ c, eval c = f
hg : ∃ c, eval c = g
⊢ ∃ c,
    eval c =
      unpaired fun a n =>
        Nat.rec (f a)
          (fun y IH => do
            let i ← IH
            g (Nat.pair a (Nat.pair y i)))
          n

Next tactic:
case prec f g pf pg hf hg =>
      rcases hf with ⟨cf, rfl⟩; rcases hg with ⟨cg, rfl⟩
      exact ⟨prec cf cg, rfl⟩
/-- A function is partial recursive if and only if there is a code implementing it. -/
theorem exists_code {f : ℕ →. ℕ} : Nat.Partrec f ↔ ∃ c : Code, eval c = f :=
  ⟨fun h => by
    induction h
    case zero => exact ⟨zero, rfl⟩
    case succ => exact ⟨succ, rfl⟩
    case left => exact ⟨left, rfl⟩
    case right => exact ⟨right, rfl⟩
    case pair f g pf pg hf hg =>
      rcases hf with ⟨cf, rfl⟩; rcases hg with ⟨cg, rfl⟩
      exact ⟨pair cf cg, rfl⟩
    case comp f g pf pg hf hg =>
      rcases hf with ⟨cf, rfl⟩; rcases hg with ⟨cg, rfl⟩
      exact ⟨comp cf cg, rfl⟩
    case prec f g pf pg hf hg =>
      

Proof state:
f✝ f g : ℕ →. ℕ
pf : Partrec f
pg : Partrec g
hf : ∃ c, eval c = f
hg : ∃ c, eval c = g
⊢ ∃ c,
    eval c =
      unpaired fun a n =>
        Nat.rec (f a)
          (fun y IH => do
            let i ← IH
            g (Nat.pair a (Nat.pair y i)))
          n

Next tactic:
rcases hf with ⟨cf, rfl⟩