l3lab/ntp-mathlib huggingface dataset:
theorem computable_iff_re_compl_re {p : α → Prop} [DecidablePred p] :
    ComputablePred p ↔ RePred p ∧ RePred fun a => ¬p a :=
  ⟨fun h => ⟨h.to_re, h.not.to_re⟩, fun ⟨h₁, h₂⟩ =>
    ⟨‹_›, by
      obtain ⟨k, pk, hk⟩ :=
        Partrec.merge (h₁.map (Computable.const true).to₂) (h₂.map (Computable.const false).to₂)
        (by
          intro a x hx y hy
          simp only [Part.mem_map_iff, Part.mem_assert_iff, Part.mem_some_iff, exists_prop,
            and_true, exists_const] at hx hy
          cases hy.1 hx.1)
      · refine' Partrec.of_eq pk fun n => Part.eq_some_iff.2 _
        

Proof state:
case intro.intro
α : Type u_1
σ : Type u_2
inst✝² : Primcodable α
inst✝¹ : Primcodable σ
p : α → Prop
inst✝ : DecidablePred p
x✝ : RePred p ∧ RePred fun a => ¬p a
h₁ : RePred p
h₂ : RePred fun a => ¬p a
k : α →. Bool
pk : Partrec k
hk :
  ∀ (a : α) (x : Bool),
    x ∈ k a ↔
      x ∈ Part.map (fun b => true) (Part.assert (p a) fun x => Part.some ()) ∨
        x ∈ Part.map (fun b => false) (Part.assert ((fun a => ¬p a) a) fun x => Part.some ())
n : α
⊢ (fun a => decide (p a)) n ∈ k n

Next tactic:
rw [hk]
theorem computable_iff_re_compl_re {p : α → Prop} [DecidablePred p] :
    ComputablePred p ↔ RePred p ∧ RePred fun a => ¬p a :=
  ⟨fun h => ⟨h.to_re, h.not.to_re⟩, fun ⟨h₁, h₂⟩ =>
    ⟨‹_›, by
      obtain ⟨k, pk, hk⟩ :=
        Partrec.merge (h₁.map (Computable.const true).to₂) (h₂.map (Computable.const false).to₂)
        (by
          intro a x hx y hy
          simp only [Part.mem_map_iff, Part.mem_assert_iff, Part.mem_some_iff, exists_prop,
            and_true, exists_const] at hx hy
          cases hy.1 hx.1)
      · refine' Partrec.of_eq pk fun n => Part.eq_some_iff.2 _
        rw [hk]
        

Proof state:
case intro.intro
α : Type u_1
σ : Type u_2
inst✝² : Primcodable α
inst✝¹ : Primcodable σ
p : α → Prop
inst✝ : DecidablePred p
x✝ : RePred p ∧ RePred fun a => ¬p a
h₁ : RePred p
h₂ : RePred fun a => ¬p a
k : α →. Bool
pk : Partrec k
hk :
  ∀ (a : α) (x : Bool),
    x ∈ k a ↔
      x ∈ Part.map (fun b => true) (Part.assert (p a) fun x => Part.some ()) ∨
        x ∈ Part.map (fun b => false) (Part.assert ((fun a => ¬p a) a) fun x => Part.some ())
n : α
⊢ (fun a => decide (p a)) n ∈ Part.map (fun b => true) (Part.assert (p n) fun x => Part.some ()) ∨
    (fun a => decide (p a)) n ∈ Part.map (fun b => false) (Part.assert ((fun a => ¬p a) n) fun x => Part.some ())

Next tactic:
simp only [Part.mem_map_iff, Part.mem_assert_iff, Part.mem_some_iff, exists_prop, and_true,
          true_eq_decide_iff, and_self, exists_const, false_eq_decide_iff]
theorem computable_iff_re_compl_re {p : α → Prop} [DecidablePred p] :
    ComputablePred p ↔ RePred p ∧ RePred fun a => ¬p a :=
  ⟨fun h => ⟨h.to_re, h.not.to_re⟩, fun ⟨h₁, h₂⟩ =>
    ⟨‹_›, by
      obtain ⟨k, pk, hk⟩ :=
        Partrec.merge (h₁.map (Computable.const true).to₂) (h₂.map (Computable.const false).to₂)
        (by
          intro a x hx y hy
          simp only [Part.mem_map_iff, Part.mem_assert_iff, Part.mem_some_iff, exists_prop,
            and_true, exists_const] at hx hy
          cases hy.1 hx.1)
      · refine' Partrec.of_eq pk fun n => Part.eq_some_iff.2 _
        rw [hk]
        simp only [Part.mem_map_iff, Part.mem_assert_iff, Part.mem_some_iff, exists_prop, and_true,
          true_eq_decide_iff, and_self, exists_const, false_eq_decide_iff]
        

Proof state:
case intro.intro
α : Type u_1
σ : Type u_2
inst✝² : Primcodable α
inst✝¹ : Primcodable σ
p : α → Prop
inst✝ : DecidablePred p
x✝ : RePred p ∧ RePred fun a => ¬p a
h₁ : RePred p
h₂ : RePred fun a => ¬p a
k : α →. Bool
pk : Partrec k
hk :
  ∀ (a : α) (x : Bool),
    x ∈ k a ↔
      x ∈ Part.map (fun b => true) (Part.assert (p a) fun x => Part.some ()) ∨
        x ∈ Part.map (fun b => false) (Part.assert ((fun a => ¬p a) a) fun x => Part.some ())
n : α
⊢ p n ∨ ¬p n

Next tactic:
apply Decidable.em
theorem computable_iff_re_compl_re' {p : α → Prop} :
    ComputablePred p ↔ RePred p ∧ RePred fun a => ¬p a := by
  

Proof state:
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
p : α → Prop
⊢ ComputablePred p ↔ RePred p ∧ RePred fun a => ¬p a

Next tactic:
classical exact computable_iff_re_compl_re
theorem computable_iff_re_compl_re' {p : α → Prop} :
    ComputablePred p ↔ RePred p ∧ RePred fun a => ¬p a := by
  classical 

Proof state:
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
p : α → Prop
⊢ ComputablePred p ↔ RePred p ∧ RePred fun a => ¬p a

Next tactic:
exact computable_iff_re_compl_re
theorem to_part {n f} (pf : @Partrec' n f) : _root_.Partrec f := by
  

Proof state:
n : ℕ
f : Vector ℕ n →. ℕ
pf : Partrec' f
⊢ _root_.Partrec f

Next tactic:
induction pf
theorem to_part {n f} (pf : @Partrec' n f) : _root_.Partrec f := by
  induction pf
  

Proof state:
case prim
n : ℕ
f : Vector ℕ n →. ℕ
n✝ : ℕ
f✝ : Vector ℕ n✝ → ℕ
a✝ : Primrec' f✝
⊢ _root_.Partrec ↑f✝
case comp
n : ℕ
f : Vector ℕ n →. ℕ
m✝ n✝ : ℕ
f✝ : Vector ℕ n✝ →. ℕ
g✝ : Fin n✝ → Vector ℕ m✝ →. ℕ
a✝¹ : Partrec' f✝
a✝ : ∀ (i : Fin n✝), Partrec' (g✝ i)
a_ih✝¹ : _root_.Partrec f✝
a_ih✝ : ∀ (i : Fin n✝), _root_.Partrec (g✝ i)
⊢ _root_.Partrec fun v => (mOfFn fun i => g✝ i v) >>= f✝
case rfind
n : ℕ
f : Vector ℕ n →. ℕ
n✝ : ℕ
f✝ : Vector ℕ (n✝ + 1) → ℕ
a✝ : Partrec' ↑f✝
a_ih✝ : _root_.Partrec ↑f✝
⊢ _root_.Partrec fun v => Nat.rfind fun n => Part.some (decide (f✝ (n ::ᵥ v) = 0))

Next tactic:
case prim n f hf => exact hf.to_prim.to_comp
theorem to_part {n f} (pf : @Partrec' n f) : _root_.Partrec f := by
  induction pf
  

Proof state:
n✝ : ℕ
f✝ : Vector ℕ n✝ →. ℕ
n : ℕ
f : Vector ℕ n → ℕ
hf : Primrec' f
⊢ _root_.Partrec ↑f

Next tactic:
case prim n f hf => exact hf.to_prim.to_comp
theorem to_part {n f} (pf : @Partrec' n f) : _root_.Partrec f := by
  induction pf
  case prim n f hf => 

Proof state:
n✝ : ℕ
f✝ : Vector ℕ n✝ →. ℕ
n : ℕ
f : Vector ℕ n → ℕ
hf : Primrec' f
⊢ _root_.Partrec ↑f

Next tactic:
exact hf.to_prim.to_comp
theorem to_part {n f} (pf : @Partrec' n f) : _root_.Partrec f := by
  induction pf
  case prim n f hf => exact hf.to_prim.to_comp
  

Proof state:
case comp
n : ℕ
f : Vector ℕ n →. ℕ
m✝ n✝ : ℕ
f✝ : Vector ℕ n✝ →. ℕ
g✝ : Fin n✝ → Vector ℕ m✝ →. ℕ
a✝¹ : Partrec' f✝
a✝ : ∀ (i : Fin n✝), Partrec' (g✝ i)
a_ih✝¹ : _root_.Partrec f✝
a_ih✝ : ∀ (i : Fin n✝), _root_.Partrec (g✝ i)
⊢ _root_.Partrec fun v => (mOfFn fun i => g✝ i v) >>= f✝
case rfind
n : ℕ
f : Vector ℕ n →. ℕ
n✝ : ℕ
f✝ : Vector ℕ (n✝ + 1) → ℕ
a✝ : Partrec' ↑f✝
a_ih✝ : _root_.Partrec ↑f✝
⊢ _root_.Partrec fun v => Nat.rfind fun n => Part.some (decide (f✝ (n ::ᵥ v) = 0))

Next tactic:
case comp m n f g _ _ hf hg => exact (Partrec.vector_mOfFn fun i => hg i).bind (hf.comp snd)
theorem to_part {n f} (pf : @Partrec' n f) : _root_.Partrec f := by
  induction pf
  case prim n f hf => exact hf.to_prim.to_comp
  

Proof state:
n✝ : ℕ
f✝ : Vector ℕ n✝ →. ℕ
m n : ℕ
f : Vector ℕ n →. ℕ
g : Fin n → Vector ℕ m →. ℕ
a✝¹ : Partrec' f
a✝ : ∀ (i : Fin n), Partrec' (g i)
hf : _root_.Partrec f
hg : ∀ (i : Fin n), _root_.Partrec (g i)
⊢ _root_.Partrec fun v => (mOfFn fun i => g i v) >>= f

Next tactic:
case comp m n f g _ _ hf hg => exact (Partrec.vector_mOfFn fun i => hg i).bind (hf.comp snd)
theorem to_part {n f} (pf : @Partrec' n f) : _root_.Partrec f := by
  induction pf
  case prim n f hf => exact hf.to_prim.to_comp
  case comp m n f g _ _ hf hg => 

Proof state:
n✝ : ℕ
f✝ : Vector ℕ n✝ →. ℕ
m n : ℕ
f : Vector ℕ n →. ℕ
g : Fin n → Vector ℕ m →. ℕ
a✝¹ : Partrec' f
a✝ : ∀ (i : Fin n), Partrec' (g i)
hf : _root_.Partrec f
hg : ∀ (i : Fin n), _root_.Partrec (g i)
⊢ _root_.Partrec fun v => (mOfFn fun i => g i v) >>= f

Next tactic:
exact (Partrec.vector_mOfFn fun i => hg i).bind (hf.comp snd)
theorem to_part {n f} (pf : @Partrec' n f) : _root_.Partrec f := by
  induction pf
  case prim n f hf => exact hf.to_prim.to_comp
  case comp m n f g _ _ hf hg => exact (Partrec.vector_mOfFn fun i => hg i).bind (hf.comp snd)
  

Proof state:
case rfind
n : ℕ
f : Vector ℕ n →. ℕ
n✝ : ℕ
f✝ : Vector ℕ (n✝ + 1) → ℕ
a✝ : Partrec' ↑f✝
a_ih✝ : _root_.Partrec ↑f✝
⊢ _root_.Partrec fun v => Nat.rfind fun n => Part.some (decide (f✝ (n ::ᵥ v) = 0))

Next tactic:
case rfind n f _ hf =>
    have := hf.comp (vector_cons.comp snd fst)
    have :=
      ((Primrec.eq.comp _root_.Primrec.id (_root_.Primrec.const 0)).to_comp.comp
        this).to₂.partrec₂
    exact _root_.Partrec.rfind this
theorem to_part {n f} (pf : @Partrec' n f) : _root_.Partrec f := by
  induction pf
  case prim n f hf => exact hf.to_prim.to_comp
  case comp m n f g _ _ hf hg => exact (Partrec.vector_mOfFn fun i => hg i).bind (hf.comp snd)
  

Proof state:
n✝ : ℕ
f✝ : Vector ℕ n✝ →. ℕ
n : ℕ
f : Vector ℕ (n + 1) → ℕ
a✝ : Partrec' ↑f
hf : _root_.Partrec ↑f
⊢ _root_.Partrec fun v => Nat.rfind fun n_1 => Part.some (decide (f (n_1 ::ᵥ v) = 0))

Next tactic:
case rfind n f _ hf =>
    have := hf.comp (vector_cons.comp snd fst)
    have :=
      ((Primrec.eq.comp _root_.Primrec.id (_root_.Primrec.const 0)).to_comp.comp
        this).to₂.partrec₂
    exact _root_.Partrec.rfind this
theorem to_part {n f} (pf : @Partrec' n f) : _root_.Partrec f := by
  induction pf
  case prim n f hf => exact hf.to_prim.to_comp
  case comp m n f g _ _ hf hg => exact (Partrec.vector_mOfFn fun i => hg i).bind (hf.comp snd)
  case rfind n f _ hf =>
    

Proof state:
n✝ : ℕ
f✝ : Vector ℕ n✝ →. ℕ
n : ℕ
f : Vector ℕ (n + 1) → ℕ
a✝ : Partrec' ↑f
hf : _root_.Partrec ↑f
⊢ _root_.Partrec fun v => Nat.rfind fun n_1 => Part.some (decide (f (n_1 ::ᵥ v) = 0))

Next tactic:
have := hf.comp (vector_cons.comp snd fst)
theorem to_part {n f} (pf : @Partrec' n f) : _root_.Partrec f := by
  induction pf
  case prim n f hf => exact hf.to_prim.to_comp
  case comp m n f g _ _ hf hg => exact (Partrec.vector_mOfFn fun i => hg i).bind (hf.comp snd)
  case rfind n f _ hf =>
    have := hf.comp (vector_cons.comp snd fst)
    

Proof state:
n✝ : ℕ
f✝ : Vector ℕ n✝ →. ℕ
n : ℕ
f : Vector ℕ (n + 1) → ℕ
a✝ : Partrec' ↑f
hf : _root_.Partrec ↑f
this : _root_.Partrec fun a => ↑f (a.2 ::ᵥ a.1)
⊢ _root_.Partrec fun v => Nat.rfind fun n_1 => Part.some (decide (f (n_1 ::ᵥ v) = 0))

Next tactic:
have :=
      ((Primrec.eq.comp _root_.Primrec.id (_root_.Primrec.const 0)).to_comp.comp
        this).to₂.partrec₂
theorem to_part {n f} (pf : @Partrec' n f) : _root_.Partrec f := by
  induction pf
  case prim n f hf => exact hf.to_prim.to_comp
  case comp m n f g _ _ hf hg => exact (Partrec.vector_mOfFn fun i => hg i).bind (hf.comp snd)
  case rfind n f _ hf =>
    have := hf.comp (vector_cons.comp snd fst)
    have :=
      ((Primrec.eq.comp _root_.Primrec.id (_root_.Primrec.const 0)).to_comp.comp
        this).to₂.partrec₂
    

Proof state:
n✝ : ℕ
f✝ : Vector ℕ n✝ →. ℕ
n : ℕ
f : Vector ℕ (n + 1) → ℕ
a✝ : Partrec' ↑f
hf : _root_.Partrec ↑f
this✝ : _root_.Partrec fun a => ↑f (a.2 ::ᵥ a.1)
this : Partrec₂ fun a => ↑fun b => decide ((fun a => id a = 0) (f ((a, b).2 ::ᵥ (a, b).1)))
⊢ _root_.Partrec fun v => Nat.rfind fun n_1 => Part.some (decide (f (n_1 ::ᵥ v) = 0))

Next tactic:
exact _root_.Partrec.rfind this
theorem tail {n f} (hf : @Partrec' n f) : @Partrec' n.succ fun v => f v.tail :=
  (hf.comp _ fun i => @prim _ _ <| Nat.Primrec'.get i.succ).of_eq fun v => by
    

Proof state:
n : ℕ
f : Vector ℕ n →. ℕ
hf : Partrec' f
v : Vector ℕ (succ n)
⊢ (mOfFn fun i => (↑fun v => Vector.get v (Fin.succ i)) v) >>= f = f (Vector.tail v)

Next tactic:
simp
theorem tail {n f} (hf : @Partrec' n f) : @Partrec' n.succ fun v => f v.tail :=
  (hf.comp _ fun i => @prim _ _ <| Nat.Primrec'.get i.succ).of_eq fun v => by
    simp; 

Proof state:
n : ℕ
f : Vector ℕ n →. ℕ
hf : Partrec' f
v : Vector ℕ (succ n)
⊢ f (ofFn fun i => Vector.get v (Fin.succ i)) = f (Vector.tail v)

Next tactic:
rw [← ofFn_get v.tail]
theorem tail {n f} (hf : @Partrec' n f) : @Partrec' n.succ fun v => f v.tail :=
  (hf.comp _ fun i => @prim _ _ <| Nat.Primrec'.get i.succ).of_eq fun v => by
    simp; rw [← ofFn_get v.tail]; 

Proof state:
n : ℕ
f : Vector ℕ n →. ℕ
hf : Partrec' f
v : Vector ℕ (succ n)
⊢ f (ofFn fun i => Vector.get v (Fin.succ i)) = f (ofFn (Vector.get (Vector.tail v)))

Next tactic:
congr
theorem tail {n f} (hf : @Partrec' n f) : @Partrec' n.succ fun v => f v.tail :=
  (hf.comp _ fun i => @prim _ _ <| Nat.Primrec'.get i.succ).of_eq fun v => by
    simp; rw [← ofFn_get v.tail]; congr; 

Proof state:
case e_a.e_a
n : ℕ
f : Vector ℕ n →. ℕ
hf : Partrec' f
v : Vector ℕ (succ n)
⊢ (fun i => Vector.get v (Fin.succ i)) = Vector.get (Vector.tail v)

Next tactic:
funext i
theorem tail {n f} (hf : @Partrec' n f) : @Partrec' n.succ fun v => f v.tail :=
  (hf.comp _ fun i => @prim _ _ <| Nat.Primrec'.get i.succ).of_eq fun v => by
    simp; rw [← ofFn_get v.tail]; congr; funext i; 

Proof state:
case e_a.e_a.h
n : ℕ
f : Vector ℕ n →. ℕ
hf : Partrec' f
v : Vector ℕ (succ n)
i : Fin n
⊢ Vector.get v (Fin.succ i) = Vector.get (Vector.tail v) i

Next tactic:
simp
protected theorem bind {n f g} (hf : @Partrec' n f) (hg : @Partrec' (n + 1) g) :
    @Partrec' n fun v => (f v).bind fun a => g (a ::ᵥ v) :=
  (@comp n (n + 1) g (fun i => Fin.cases f (fun i v => some (v.get i)) i) hg fun i => by
        

Proof state:
n : ℕ
f : Vector ℕ n →. ℕ
g : Vector ℕ (n + 1) →. ℕ
hf : Partrec' f
hg : Partrec' g
i : Fin (n + 1)
⊢ Partrec' ((fun i => Fin.cases f (fun i v => ↑(some (Vector.get v i))) i) i)

Next tactic:
refine' Fin.cases _ (fun i => _) i
protected theorem bind {n f g} (hf : @Partrec' n f) (hg : @Partrec' (n + 1) g) :
    @Partrec' n fun v => (f v).bind fun a => g (a ::ᵥ v) :=
  (@comp n (n + 1) g (fun i => Fin.cases f (fun i v => some (v.get i)) i) hg fun i => by
        refine' Fin.cases _ (fun i => _) i <;> 

Proof state:
case refine'_1
n : ℕ
f : Vector ℕ n →. ℕ
g : Vector ℕ (n + 1) →. ℕ
hf : Partrec' f
hg : Partrec' g
i : Fin (n + 1)
⊢ Partrec' ((fun i => Fin.cases f (fun i v => ↑(some (Vector.get v i))) i) 0)

Next tactic:
simp [*]
protected theorem bind {n f g} (hf : @Partrec' n f) (hg : @Partrec' (n + 1) g) :
    @Partrec' n fun v => (f v).bind fun a => g (a ::ᵥ v) :=
  (@comp n (n + 1) g (fun i => Fin.cases f (fun i v => some (v.get i)) i) hg fun i => by
        refine' Fin.cases _ (fun i => _) i <;> 

Proof state:
case refine'_2
n : ℕ
f : Vector ℕ n →. ℕ
g : Vector ℕ (n + 1) →. ℕ
hf : Partrec' f
hg : Partrec' g
i✝ : Fin (n + 1)
i : Fin n
⊢ Partrec' ((fun i => Fin.cases f (fun i v => ↑(some (Vector.get v i))) i) (Fin.succ i))

Next tactic:
simp [*]
protected theorem bind {n f g} (hf : @Partrec' n f) (hg : @Partrec' (n + 1) g) :
    @Partrec' n fun v => (f v).bind fun a => g (a ::ᵥ v) :=
  (@comp n (n + 1) g (fun i => Fin.cases f (fun i v => some (v.get i)) i) hg fun i => by
        refine' Fin.cases _ (fun i => _) i <;> simp [*]
        

Proof state:
case refine'_2
n : ℕ
f : Vector ℕ n →. ℕ
g : Vector ℕ (n + 1) →. ℕ
hf : Partrec' f
hg : Partrec' g
i✝ : Fin (n + 1)
i : Fin n
⊢ Partrec' fun v => Part.some (Vector.get v i)

Next tactic:
exact prim (Nat.Primrec'.get _)
protected theorem bind {n f g} (hf : @Partrec' n f) (hg : @Partrec' (n + 1) g) :
    @Partrec' n fun v => (f v).bind fun a => g (a ::ᵥ v) :=
  (@comp n (n + 1) g (fun i => Fin.cases f (fun i v => some (v.get i)) i) hg fun i => by
        refine' Fin.cases _ (fun i => _) i <;> simp [*]
        exact prim (Nat.Primrec'.get _)).of_eq
    fun v => by 

Proof state:
n : ℕ
f : Vector ℕ n →. ℕ
g : Vector ℕ (n + 1) →. ℕ
hf : Partrec' f
hg : Partrec' g
v : Vector ℕ n
⊢ (mOfFn fun i => Fin.cases f (fun i v => ↑(some (Vector.get v i))) i v) >>= g = Part.bind (f v) fun a => g (a ::ᵥ v)

Next tactic:
simp [mOfFn, Part.bind_assoc, pure]
protected theorem map {n f} {g : Vector ℕ (n + 1) → ℕ} (hf : @Partrec' n f)
    (hg : @Partrec' (n + 1) g) : @Partrec' n fun v => (f v).map fun a => g (a ::ᵥ v) := by
  

Proof state:
n : ℕ
f : Vector ℕ n →. ℕ
g : Vector ℕ (n + 1) → ℕ
hf : Partrec' f
hg : Partrec' ↑g
⊢ Partrec' fun v => Part.map (fun a => g (a ::ᵥ v)) (f v)

Next tactic:
simp [(Part.bind_some_eq_map _ _).symm]
protected theorem map {n f} {g : Vector ℕ (n + 1) → ℕ} (hf : @Partrec' n f)
    (hg : @Partrec' (n + 1) g) : @Partrec' n fun v => (f v).map fun a => g (a ::ᵥ v) := by
  simp [(Part.bind_some_eq_map _ _).symm]; 

Proof state:
n : ℕ
f : Vector ℕ n →. ℕ
g : Vector ℕ (n + 1) → ℕ
hf : Partrec' f
hg : Partrec' ↑g
⊢ Partrec' fun v => Part.bind (f v) (Part.some ∘ fun a => g (a ::ᵥ v))

Next tactic:
exact hf.bind hg
protected theorem cons {n m} {f : Vector ℕ n → ℕ} {g} (hf : @Partrec' n f) (hg : @Vec n m g) :
    Vec fun v => f v ::ᵥ g v := fun i =>
  Fin.cases (by 

Proof state:
n m : ℕ
f : Vector ℕ n → ℕ
g : Vector ℕ n → Vector ℕ m
hf : Partrec' ↑f
hg : Vec g
i : Fin (succ m)
⊢ Partrec' fun v => ↑(some (Vector.get ((fun v => f v ::ᵥ g v) v) 0))

Next tactic:
simpa using hf
protected theorem cons {n m} {f : Vector ℕ n → ℕ} {g} (hf : @Partrec' n f) (hg : @Vec n m g) :
    Vec fun v => f v ::ᵥ g v := fun i =>
  Fin.cases (by simpa using hf) (fun i => by 

Proof state:
n m : ℕ
f : Vector ℕ n → ℕ
g : Vector ℕ n → Vector ℕ m
hf : Partrec' ↑f
hg : Vec g
i✝ : Fin (succ m)
i : Fin m
⊢ Partrec' fun v => ↑(some (Vector.get ((fun v => f v ::ᵥ g v) v) (Fin.succ i)))

Next tactic:
simp only [hg i, get_cons_succ]
theorem comp' {n m f g} (hf : @Partrec' m f) (hg : @Vec n m g) : Partrec' fun v => f (g v) :=
  (hf.comp _ hg).of_eq fun v => by 

Proof state:
n m : ℕ
f : Vector ℕ m →. ℕ
g : Vector ℕ n → Vector ℕ m
hf : Partrec' f
hg : Vec g
v : Vector ℕ n
⊢ (mOfFn fun i => ↑(some (Vector.get (g v) i))) >>= f = f (g v)

Next tactic:
simp
theorem comp₁ {n} (f : ℕ →. ℕ) {g : Vector ℕ n → ℕ} (hf : @Partrec' 1 fun v => f v.head)
    (hg : @Partrec' n g) : @Partrec' n fun v => f (g v) := by
  

Proof state:
n : ℕ
f : ℕ →. ℕ
g : Vector ℕ n → ℕ
hf : Partrec' fun v => f (Vector.head v)
hg : Partrec' ↑g
⊢ Partrec' fun v => f (g v)

Next tactic:
simpa using hf.comp' (Partrec'.cons hg Partrec'.nil)
theorem rfindOpt {n} {f : Vector ℕ (n + 1) → ℕ} (hf : @Partrec' (n + 1) f) :
    @Partrec' n fun v => Nat.rfindOpt fun a => ofNat (Option ℕ) (f (a ::ᵥ v)) :=
  ((rfind <|
        (of_prim (Primrec.nat_sub.comp (_root_.Primrec.const 1) Primrec.vector_head)).comp₁
          (fun n => Part.some (1 - n)) hf).bind
    ((prim Nat.Primrec'.pred).comp₁ Nat.pred hf)).of_eq
    fun v =>
    Part.ext fun b => by
      

Proof state:
n : ℕ
f : Vector ℕ (n + 1) → ℕ
hf : Partrec' ↑f
v : Vector ℕ n
b : ℕ
⊢ (b ∈ Part.bind (Nat.rfind fun n_1 => Part.some (decide (1 - f (n_1 ::ᵥ v) = 0))) fun a => ↑pred (f (a ::ᵥ v))) ↔
    b ∈ Nat.rfindOpt fun a => ofNat (Option ℕ) (f (a ::ᵥ v))

Next tactic:
simp only [Nat.rfindOpt, exists_prop, tsub_eq_zero_iff_le, PFun.coe_val, Part.mem_bind_iff,
        Part.mem_some_iff, Option.mem_def, Part.mem_coe]
theorem rfindOpt {n} {f : Vector ℕ (n + 1) → ℕ} (hf : @Partrec' (n + 1) f) :
    @Partrec' n fun v => Nat.rfindOpt fun a => ofNat (Option ℕ) (f (a ::ᵥ v)) :=
  ((rfind <|
        (of_prim (Primrec.nat_sub.comp (_root_.Primrec.const 1) Primrec.vector_head)).comp₁
          (fun n => Part.some (1 - n)) hf).bind
    ((prim Nat.Primrec'.pred).comp₁ Nat.pred hf)).of_eq
    fun v =>
    Part.ext fun b => by
      simp only [Nat.rfindOpt, exists_prop, tsub_eq_zero_iff_le, PFun.coe_val, Part.mem_bind_iff,
        Part.mem_some_iff, Option.mem_def, Part.mem_coe]
      

Proof state:
n : ℕ
f : Vector ℕ (n + 1) → ℕ
hf : Partrec' ↑f
v : Vector ℕ n
b : ℕ
⊢ (∃ a ∈ Nat.rfind fun n_1 => Part.some (decide (1 ≤ f (n_1 ::ᵥ v))), b = pred (f (a ::ᵥ v))) ↔
    ∃ a ∈ Nat.rfind fun n_1 => ↑(some (Option.isSome (ofNat (Option ℕ) (f (n_1 ::ᵥ v))))),
      ofNat (Option ℕ) (f (a ::ᵥ v)) = some b

Next tactic:
refine'
        exists_congr fun a => (and_congr (iff_of_eq _) Iff.rfl).trans (and_congr_right fun h => _)
theorem rfindOpt {n} {f : Vector ℕ (n + 1) → ℕ} (hf : @Partrec' (n + 1) f) :
    @Partrec' n fun v => Nat.rfindOpt fun a => ofNat (Option ℕ) (f (a ::ᵥ v)) :=
  ((rfind <|
        (of_prim (Primrec.nat_sub.comp (_root_.Primrec.const 1) Primrec.vector_head)).comp₁
          (fun n => Part.some (1 - n)) hf).bind
    ((prim Nat.Primrec'.pred).comp₁ Nat.pred hf)).of_eq
    fun v =>
    Part.ext fun b => by
      simp only [Nat.rfindOpt, exists_prop, tsub_eq_zero_iff_le, PFun.coe_val, Part.mem_bind_iff,
        Part.mem_some_iff, Option.mem_def, Part.mem_coe]
      refine'
        exists_congr fun a => (and_congr (iff_of_eq _) Iff.rfl).trans (and_congr_right fun h => _)
      · 

Proof state:
case refine'_1
n : ℕ
f : Vector ℕ (n + 1) → ℕ
hf : Partrec' ↑f
v : Vector ℕ n
b a : ℕ
⊢ (a ∈ Nat.rfind fun n_1 => Part.some (decide (1 ≤ f (n_1 ::ᵥ v)))) =
    (a ∈ Nat.rfind fun n_1 => ↑(some (Option.isSome (ofNat (Option ℕ) (f (n_1 ::ᵥ v))))))

Next tactic:
congr
theorem rfindOpt {n} {f : Vector ℕ (n + 1) → ℕ} (hf : @Partrec' (n + 1) f) :
    @Partrec' n fun v => Nat.rfindOpt fun a => ofNat (Option ℕ) (f (a ::ᵥ v)) :=
  ((rfind <|
        (of_prim (Primrec.nat_sub.comp (_root_.Primrec.const 1) Primrec.vector_head)).comp₁
          (fun n => Part.some (1 - n)) hf).bind
    ((prim Nat.Primrec'.pred).comp₁ Nat.pred hf)).of_eq
    fun v =>
    Part.ext fun b => by
      simp only [Nat.rfindOpt, exists_prop, tsub_eq_zero_iff_le, PFun.coe_val, Part.mem_bind_iff,
        Part.mem_some_iff, Option.mem_def, Part.mem_coe]
      refine'
        exists_congr fun a => (and_congr (iff_of_eq _) Iff.rfl).trans (and_congr_right fun h => _)
      · congr
        

Proof state:
case refine'_1.e_a.e_p
n : ℕ
f : Vector ℕ (n + 1) → ℕ
hf : Partrec' ↑f
v : Vector ℕ n
b a : ℕ
⊢ (fun n_1 => Part.some (decide (1 ≤ f (n_1 ::ᵥ v)))) = fun n_1 =>
    ↑(some (Option.isSome (ofNat (Option ℕ) (f (n_1 ::ᵥ v)))))

Next tactic:
funext n
theorem rfindOpt {n} {f : Vector ℕ (n + 1) → ℕ} (hf : @Partrec' (n + 1) f) :
    @Partrec' n fun v => Nat.rfindOpt fun a => ofNat (Option ℕ) (f (a ::ᵥ v)) :=
  ((rfind <|
        (of_prim (Primrec.nat_sub.comp (_root_.Primrec.const 1) Primrec.vector_head)).comp₁
          (fun n => Part.some (1 - n)) hf).bind
    ((prim Nat.Primrec'.pred).comp₁ Nat.pred hf)).of_eq
    fun v =>
    Part.ext fun b => by
      simp only [Nat.rfindOpt, exists_prop, tsub_eq_zero_iff_le, PFun.coe_val, Part.mem_bind_iff,
        Part.mem_some_iff, Option.mem_def, Part.mem_coe]
      refine'
        exists_congr fun a => (and_congr (iff_of_eq _) Iff.rfl).trans (and_congr_right fun h => _)
      · congr
        funext n
        

Proof state:
case refine'_1.e_a.e_p.h
n✝ : ℕ
f : Vector ℕ (n✝ + 1) → ℕ
hf : Partrec' ↑f
v : Vector ℕ n✝
b a n : ℕ
⊢ Part.some (decide (1 ≤ f (n ::ᵥ v))) = ↑(some (Option.isSome (ofNat (Option ℕ) (f (n ::ᵥ v)))))

Next tactic:
cases f (n ::ᵥ v)
theorem rfindOpt {n} {f : Vector ℕ (n + 1) → ℕ} (hf : @Partrec' (n + 1) f) :
    @Partrec' n fun v => Nat.rfindOpt fun a => ofNat (Option ℕ) (f (a ::ᵥ v)) :=
  ((rfind <|
        (of_prim (Primrec.nat_sub.comp (_root_.Primrec.const 1) Primrec.vector_head)).comp₁
          (fun n => Part.some (1 - n)) hf).bind
    ((prim Nat.Primrec'.pred).comp₁ Nat.pred hf)).of_eq
    fun v =>
    Part.ext fun b => by
      simp only [Nat.rfindOpt, exists_prop, tsub_eq_zero_iff_le, PFun.coe_val, Part.mem_bind_iff,
        Part.mem_some_iff, Option.mem_def, Part.mem_coe]
      refine'
        exists_congr fun a => (and_congr (iff_of_eq _) Iff.rfl).trans (and_congr_right fun h => _)
      · congr
        funext n
        cases f (n ::ᵥ v) <;> 

Proof state:
case refine'_1.e_a.e_p.h.zero
n✝ : ℕ
f : Vector ℕ (n✝ + 1) → ℕ
hf : Partrec' ↑f
v : Vector ℕ n✝
b a n : ℕ
⊢ Part.some (decide (1 ≤ zero)) = ↑(some (Option.isSome (ofNat (Option ℕ) zero)))

Next tactic:
simp [Nat.succ_le_succ]