l3lab/ntp-mathlib huggingface dataset:
protected theorem bind {f : α →. β} {g : α → β →. σ} (hf : Partrec f) (hg : Partrec₂ g) :
    Partrec fun a => (f a).bind (g a) :=
  (hg.comp (Nat.Partrec.some.pair hf)).of_eq fun n => by
    simp [Seq.seq]; cases' e : decode (α := α) n with a <;> 

Proof state:
case none
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α →. β
g : α → β →. σ
hf : Partrec f
hg : Partrec₂ g
n : ℕ
e : decode n = Option.none
⊢ (Part.bind (Part.bind ↑Option.none fun y => map (Nat.pair n) (map encode (f y))) fun n =>
      Part.bind ↑(Option.bind (decode (Nat.unpair n).1) fun a => Option.map (Prod.mk a) (decode (Nat.unpair n).2))
        fun a => map encode (g a.1 a.2)) =
    Part.bind ↑Option.none fun a => Part.bind (f a) fun y => map encode (g a y)

Next tactic:
simp [e, encodek]
protected theorem bind {f : α →. β} {g : α → β →. σ} (hf : Partrec f) (hg : Partrec₂ g) :
    Partrec fun a => (f a).bind (g a) :=
  (hg.comp (Nat.Partrec.some.pair hf)).of_eq fun n => by
    simp [Seq.seq]; cases' e : decode (α := α) n with a <;> 

Proof state:
case some
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α →. β
g : α → β →. σ
hf : Partrec f
hg : Partrec₂ g
n : ℕ
a : α
e : decode n = Option.some a
⊢ (Part.bind (Part.bind ↑(Option.some a) fun y => map (Nat.pair n) (map encode (f y))) fun n =>
      Part.bind ↑(Option.bind (decode (Nat.unpair n).1) fun a => Option.map (Prod.mk a) (decode (Nat.unpair n).2))
        fun a => map encode (g a.1 a.2)) =
    Part.bind ↑(Option.some a) fun a => Part.bind (f a) fun y => map encode (g a y)

Next tactic:
simp [e, encodek]
theorem map {f : α →. β} {g : α → β → σ} (hf : Partrec f) (hg : Computable₂ g) :
    Partrec fun a => (f a).map (g a) := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α →. β
g : α → β → σ
hf : Partrec f
hg : Computable₂ g
⊢ Partrec fun a => Part.map (g a) (f a)

Next tactic:
simpa [bind_some_eq_map] using @Partrec.bind _ _ _ _ _ _ _ (fun a => Part.some ∘ (g a)) hf hg
theorem nat_rec {f : α → ℕ} {g : α →. σ} {h : α → ℕ × σ →. σ} (hf : Computable f) (hg : Partrec g)
    (hh : Partrec₂ h) : Partrec fun a => (f a).rec (g a) fun y IH => IH.bind fun i => h a (y, i) :=
  (Nat.Partrec.prec' hf hg hh).of_eq fun n => by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α → ℕ
g : α →. σ
h : α → ℕ × σ →. σ
hf : Computable f
hg : Partrec g
hh : Partrec₂ h
n : ℕ
⊢ (Part.bind (Part.bind ↑(decode n) fun a => Part.map encode (↑f a)) fun n_1 =>
      Nat.rec (Part.bind ↑(decode n) fun a => Part.map encode (g a))
        (fun y IH => do
          let i ← IH
          Part.bind ↑(decode (Nat.pair n (Nat.pair y i))) fun a => Part.map encode ((fun p => h p.1 p.2) a))
        n_1) =
    Part.bind ↑(decode n) fun a =>
      Part.map encode ((fun a => Nat.rec (g a) (fun y IH => Part.bind IH fun i => h a (y, i)) (f a)) a)

Next tactic:
cases' e : decode (α := α) n with a
theorem nat_rec {f : α → ℕ} {g : α →. σ} {h : α → ℕ × σ →. σ} (hf : Computable f) (hg : Partrec g)
    (hh : Partrec₂ h) : Partrec fun a => (f a).rec (g a) fun y IH => IH.bind fun i => h a (y, i) :=
  (Nat.Partrec.prec' hf hg hh).of_eq fun n => by
    cases' e : decode (α := α) n with a <;> 

Proof state:
case none
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α → ℕ
g : α →. σ
h : α → ℕ × σ →. σ
hf : Computable f
hg : Partrec g
hh : Partrec₂ h
n : ℕ
e : decode n = Option.none
⊢ (Part.bind (Part.bind ↑Option.none fun a => Part.map encode (↑f a)) fun n_1 =>
      Nat.rec (Part.bind ↑Option.none fun a => Part.map encode (g a))
        (fun y IH => do
          let i ← IH
          Part.bind ↑(decode (Nat.pair n (Nat.pair y i))) fun a => Part.map encode ((fun p => h p.1 p.2) a))
        n_1) =
    Part.bind ↑Option.none fun a =>
      Part.map encode ((fun a => Nat.rec (g a) (fun y IH => Part.bind IH fun i => h a (y, i)) (f a)) a)

Next tactic:
simp [e]
theorem nat_rec {f : α → ℕ} {g : α →. σ} {h : α → ℕ × σ →. σ} (hf : Computable f) (hg : Partrec g)
    (hh : Partrec₂ h) : Partrec fun a => (f a).rec (g a) fun y IH => IH.bind fun i => h a (y, i) :=
  (Nat.Partrec.prec' hf hg hh).of_eq fun n => by
    cases' e : decode (α := α) n with a <;> 

Proof state:
case some
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α → ℕ
g : α →. σ
h : α → ℕ × σ →. σ
hf : Computable f
hg : Partrec g
hh : Partrec₂ h
n : ℕ
a : α
e : decode n = Option.some a
⊢ (Part.bind (Part.bind ↑(Option.some a) fun a => Part.map encode (↑f a)) fun n_1 =>
      Nat.rec (Part.bind ↑(Option.some a) fun a => Part.map encode (g a))
        (fun y IH => do
          let i ← IH
          Part.bind ↑(decode (Nat.pair n (Nat.pair y i))) fun a => Part.map encode ((fun p => h p.1 p.2) a))
        n_1) =
    Part.bind ↑(Option.some a) fun a =>
      Part.map encode ((fun a => Nat.rec (g a) (fun y IH => Part.bind IH fun i => h a (y, i)) (f a)) a)

Next tactic:
simp [e]
theorem nat_rec {f : α → ℕ} {g : α →. σ} {h : α → ℕ × σ →. σ} (hf : Computable f) (hg : Partrec g)
    (hh : Partrec₂ h) : Partrec fun a => (f a).rec (g a) fun y IH => IH.bind fun i => h a (y, i) :=
  (Nat.Partrec.prec' hf hg hh).of_eq fun n => by
    cases' e : decode (α := α) n with a <;> simp [e]
    

Proof state:
case some
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α → ℕ
g : α →. σ
h : α → ℕ × σ →. σ
hf : Computable f
hg : Partrec g
hh : Partrec₂ h
n : ℕ
a : α
e : decode n = Option.some a
⊢ Nat.rec (Part.map encode (g a))
      (fun y IH =>
        Part.bind IH fun i =>
          Part.bind ↑(Option.map (Prod.mk a ∘ Prod.mk y) (decode i)) fun a => Part.map encode (h a.1 a.2))
      (f a) =
    Part.map encode (Nat.rec (g a) (fun y IH => Part.bind IH fun i => h a (y, i)) (f a))

Next tactic:
induction' f a with m IH
theorem nat_rec {f : α → ℕ} {g : α →. σ} {h : α → ℕ × σ →. σ} (hf : Computable f) (hg : Partrec g)
    (hh : Partrec₂ h) : Partrec fun a => (f a).rec (g a) fun y IH => IH.bind fun i => h a (y, i) :=
  (Nat.Partrec.prec' hf hg hh).of_eq fun n => by
    cases' e : decode (α := α) n with a <;> simp [e]
    induction' f a with m IH <;> 

Proof state:
case some.zero
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α → ℕ
g : α →. σ
h : α → ℕ × σ →. σ
hf : Computable f
hg : Partrec g
hh : Partrec₂ h
n : ℕ
a : α
e : decode n = Option.some a
⊢ Nat.rec (Part.map encode (g a))
      (fun y IH =>
        Part.bind IH fun i =>
          Part.bind ↑(Option.map (Prod.mk a ∘ Prod.mk y) (decode i)) fun a => Part.map encode (h a.1 a.2))
      Nat.zero =
    Part.map encode (Nat.rec (g a) (fun y IH => Part.bind IH fun i => h a (y, i)) Nat.zero)

Next tactic:
simp
theorem nat_rec {f : α → ℕ} {g : α →. σ} {h : α → ℕ × σ →. σ} (hf : Computable f) (hg : Partrec g)
    (hh : Partrec₂ h) : Partrec fun a => (f a).rec (g a) fun y IH => IH.bind fun i => h a (y, i) :=
  (Nat.Partrec.prec' hf hg hh).of_eq fun n => by
    cases' e : decode (α := α) n with a <;> simp [e]
    induction' f a with m IH <;> 

Proof state:
case some.succ
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α → ℕ
g : α →. σ
h : α → ℕ × σ →. σ
hf : Computable f
hg : Partrec g
hh : Partrec₂ h
n : ℕ
a : α
e : decode n = Option.some a
m : ℕ
IH :
  Nat.rec (Part.map encode (g a))
      (fun y IH =>
        Part.bind IH fun i =>
          Part.bind ↑(Option.map (Prod.mk a ∘ Prod.mk y) (decode i)) fun a => Part.map encode (h a.1 a.2))
      m =
    Part.map encode (Nat.rec (g a) (fun y IH => Part.bind IH fun i => h a (y, i)) m)
⊢ Nat.rec (Part.map encode (g a))
      (fun y IH =>
        Part.bind IH fun i =>
          Part.bind ↑(Option.map (Prod.mk a ∘ Prod.mk y) (decode i)) fun a => Part.map encode (h a.1 a.2))
      (Nat.succ m) =
    Part.map encode (Nat.rec (g a) (fun y IH => Part.bind IH fun i => h a (y, i)) (Nat.succ m))

Next tactic:
simp
theorem nat_rec {f : α → ℕ} {g : α →. σ} {h : α → ℕ × σ →. σ} (hf : Computable f) (hg : Partrec g)
    (hh : Partrec₂ h) : Partrec fun a => (f a).rec (g a) fun y IH => IH.bind fun i => h a (y, i) :=
  (Nat.Partrec.prec' hf hg hh).of_eq fun n => by
    cases' e : decode (α := α) n with a <;> simp [e]
    induction' f a with m IH <;> simp
    

Proof state:
case some.succ
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α → ℕ
g : α →. σ
h : α → ℕ × σ →. σ
hf : Computable f
hg : Partrec g
hh : Partrec₂ h
n : ℕ
a : α
e : decode n = Option.some a
m : ℕ
IH :
  Nat.rec (Part.map encode (g a))
      (fun y IH =>
        Part.bind IH fun i =>
          Part.bind ↑(Option.map (Prod.mk a ∘ Prod.mk y) (decode i)) fun a => Part.map encode (h a.1 a.2))
      m =
    Part.map encode (Nat.rec (g a) (fun y IH => Part.bind IH fun i => h a (y, i)) m)
⊢ (Part.bind
      (Nat.rec (Part.map encode (g a))
        (fun y IH =>
          Part.bind IH fun i =>
            Part.bind ↑(Option.map (Prod.mk a ∘ Prod.mk y) (decode i)) fun a => Part.map encode (h a.1 a.2))
        m)
      fun i => Part.bind ↑(Option.map (Prod.mk a ∘ Prod.mk m) (decode i)) fun a => Part.map encode (h a.1 a.2)) =
    Part.bind (Nat.rec (g a) (fun y IH => Part.bind IH fun i => h a (y, i)) m) fun y => Part.map encode (h a (m, y))

Next tactic:
rw [IH, Part.bind_map]
theorem nat_rec {f : α → ℕ} {g : α →. σ} {h : α → ℕ × σ →. σ} (hf : Computable f) (hg : Partrec g)
    (hh : Partrec₂ h) : Partrec fun a => (f a).rec (g a) fun y IH => IH.bind fun i => h a (y, i) :=
  (Nat.Partrec.prec' hf hg hh).of_eq fun n => by
    cases' e : decode (α := α) n with a <;> simp [e]
    induction' f a with m IH <;> simp
    rw [IH, Part.bind_map]
    

Proof state:
case some.succ
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α → ℕ
g : α →. σ
h : α → ℕ × σ →. σ
hf : Computable f
hg : Partrec g
hh : Partrec₂ h
n : ℕ
a : α
e : decode n = Option.some a
m : ℕ
IH :
  Nat.rec (Part.map encode (g a))
      (fun y IH =>
        Part.bind IH fun i =>
          Part.bind ↑(Option.map (Prod.mk a ∘ Prod.mk y) (decode i)) fun a => Part.map encode (h a.1 a.2))
      m =
    Part.map encode (Nat.rec (g a) (fun y IH => Part.bind IH fun i => h a (y, i)) m)
⊢ (Part.bind (Nat.rec (g a) (fun y IH => Part.bind IH fun i => h a (y, i)) m) fun y =>
      Part.bind ↑(Option.map (Prod.mk a ∘ Prod.mk m) (decode (encode y))) fun a => Part.map encode (h a.1 a.2)) =
    Part.bind (Nat.rec (g a) (fun y IH => Part.bind IH fun i => h a (y, i)) m) fun y => Part.map encode (h a (m, y))

Next tactic:
congr
theorem nat_rec {f : α → ℕ} {g : α →. σ} {h : α → ℕ × σ →. σ} (hf : Computable f) (hg : Partrec g)
    (hh : Partrec₂ h) : Partrec fun a => (f a).rec (g a) fun y IH => IH.bind fun i => h a (y, i) :=
  (Nat.Partrec.prec' hf hg hh).of_eq fun n => by
    cases' e : decode (α := α) n with a <;> simp [e]
    induction' f a with m IH <;> simp
    rw [IH, Part.bind_map]
    congr; 

Proof state:
case some.succ.e_g
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α → ℕ
g : α →. σ
h : α → ℕ × σ →. σ
hf : Computable f
hg : Partrec g
hh : Partrec₂ h
n : ℕ
a : α
e : decode n = Option.some a
m : ℕ
IH :
  Nat.rec (Part.map encode (g a))
      (fun y IH =>
        Part.bind IH fun i =>
          Part.bind ↑(Option.map (Prod.mk a ∘ Prod.mk y) (decode i)) fun a => Part.map encode (h a.1 a.2))
      m =
    Part.map encode (Nat.rec (g a) (fun y IH => Part.bind IH fun i => h a (y, i)) m)
⊢ (fun y => Part.bind ↑(Option.map (Prod.mk a ∘ Prod.mk m) (decode (encode y))) fun a => Part.map encode (h a.1 a.2)) =
    fun y => Part.map encode (h a (m, y))

Next tactic:
funext s
theorem nat_rec {f : α → ℕ} {g : α →. σ} {h : α → ℕ × σ →. σ} (hf : Computable f) (hg : Partrec g)
    (hh : Partrec₂ h) : Partrec fun a => (f a).rec (g a) fun y IH => IH.bind fun i => h a (y, i) :=
  (Nat.Partrec.prec' hf hg hh).of_eq fun n => by
    cases' e : decode (α := α) n with a <;> simp [e]
    induction' f a with m IH <;> simp
    rw [IH, Part.bind_map]
    congr; funext s
    

Proof state:
case some.succ.e_g.h
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α → ℕ
g : α →. σ
h : α → ℕ × σ →. σ
hf : Computable f
hg : Partrec g
hh : Partrec₂ h
n : ℕ
a : α
e : decode n = Option.some a
m : ℕ
IH :
  Nat.rec (Part.map encode (g a))
      (fun y IH =>
        Part.bind IH fun i =>
          Part.bind ↑(Option.map (Prod.mk a ∘ Prod.mk y) (decode i)) fun a => Part.map encode (h a.1 a.2))
      m =
    Part.map encode (Nat.rec (g a) (fun y IH => Part.bind IH fun i => h a (y, i)) m)
s : σ
⊢ (Part.bind ↑(Option.map (Prod.mk a ∘ Prod.mk m) (decode (encode s))) fun a => Part.map encode (h a.1 a.2)) =
    Part.map encode (h a (m, s))

Next tactic:
simp [encodek]
nonrec theorem comp {f : β →. σ} {g : α → β} (hf : Partrec f) (hg : Computable g) :
    Partrec fun a => f (g a) :=
  (hf.comp hg).of_eq fun n => by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : β →. σ
g : α → β
hf : Partrec f
hg : Computable g
n : ℕ
⊢ (do
      let n ← Part.bind ↑(decode n) fun a => Part.map encode (↑g a)
      Part.bind ↑(decode n) fun a => Part.map encode (f a)) =
    Part.bind ↑(decode n) fun a => Part.map encode ((fun a => f (g a)) a)

Next tactic:
simp
nonrec theorem comp {f : β →. σ} {g : α → β} (hf : Partrec f) (hg : Computable g) :
    Partrec fun a => f (g a) :=
  (hf.comp hg).of_eq fun n => by simp; 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : β →. σ
g : α → β
hf : Partrec f
hg : Computable g
n : ℕ
⊢ (Part.bind (Part.bind ↑(decode n) fun a => Part.some (encode (g a))) fun n =>
      Part.bind ↑(decode n) fun a => Part.map encode (f a)) =
    Part.bind ↑(decode n) fun a => Part.map encode (f (g a))

Next tactic:
cases' e : decode (α := α) n with a
nonrec theorem comp {f : β →. σ} {g : α → β} (hf : Partrec f) (hg : Computable g) :
    Partrec fun a => f (g a) :=
  (hf.comp hg).of_eq fun n => by simp; cases' e : decode (α := α) n with a <;> 

Proof state:
case none
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : β →. σ
g : α → β
hf : Partrec f
hg : Computable g
n : ℕ
e : decode n = Option.none
⊢ (Part.bind (Part.bind ↑Option.none fun a => Part.some (encode (g a))) fun n =>
      Part.bind ↑(decode n) fun a => Part.map encode (f a)) =
    Part.bind ↑Option.none fun a => Part.map encode (f (g a))

Next tactic:
simp [e, encodek]
nonrec theorem comp {f : β →. σ} {g : α → β} (hf : Partrec f) (hg : Computable g) :
    Partrec fun a => f (g a) :=
  (hf.comp hg).of_eq fun n => by simp; cases' e : decode (α := α) n with a <;> 

Proof state:
case some
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : β →. σ
g : α → β
hf : Partrec f
hg : Computable g
n : ℕ
a : α
e : decode n = Option.some a
⊢ (Part.bind (Part.bind ↑(Option.some a) fun a => Part.some (encode (g a))) fun n =>
      Part.bind ↑(decode n) fun a => Part.map encode (f a)) =
    Part.bind ↑(Option.some a) fun a => Part.map encode (f (g a))

Next tactic:
simp [e, encodek]
theorem nat_iff {f : ℕ →. ℕ} : Partrec f ↔ Nat.Partrec f := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : ℕ →. ℕ
⊢ Partrec f ↔ Nat.Partrec f

Next tactic:
simp [Partrec, map_id']
theorem unpaired {f : ℕ → ℕ →. α} : Partrec (Nat.unpaired f) ↔ Partrec₂ f :=
  ⟨fun h => by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
σ : Type u_5
inst✝⁴ : Primcodable α
inst✝³ : Primcodable β
inst✝² : Primcodable γ
inst✝¹ : Primcodable δ
inst✝ : Primcodable σ
f : ℕ → ℕ →. α
h : Partrec (Nat.unpaired f)
⊢ Partrec₂ f

Next tactic:
simpa using Partrec.comp (g := fun p : ℕ × ℕ => (p.1, p.2)) h Primrec₂.pair.to_comp
theorem rfind {p : α → ℕ →. Bool} (hp : Partrec₂ p) : Partrec fun a => Nat.rfind (p a) :=
  (Nat.Partrec.rfind <|
        hp.map ((Primrec.dom_bool fun b => cond b 0 1).comp Primrec.snd).to₂.to_comp).of_eq
    fun n => by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
p : α → ℕ →. Bool
hp : Partrec₂ p
n : ℕ
⊢ (Nat.rfind fun n_1 =>
      (fun m => decide (m = 0)) <$>
        Part.bind ↑(decode (Nat.pair n n_1)) fun a =>
          Part.map encode ((fun a => Part.map (fun b => bif (a, b).2 then 0 else 1) (p a.1 a.2)) a)) =
    Part.bind ↑(decode n) fun a => Part.map encode ((fun a => Nat.rfind (p a)) a)

Next tactic:
cases' e : decode (α := α) n with a
theorem rfind {p : α → ℕ →. Bool} (hp : Partrec₂ p) : Partrec fun a => Nat.rfind (p a) :=
  (Nat.Partrec.rfind <|
        hp.map ((Primrec.dom_bool fun b => cond b 0 1).comp Primrec.snd).to₂.to_comp).of_eq
    fun n => by
    cases' e : decode (α := α) n with a <;> 

Proof state:
case none
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
p : α → ℕ →. Bool
hp : Partrec₂ p
n : ℕ
e : decode n = Option.none
⊢ (Nat.rfind fun n_1 =>
      (fun m => decide (m = 0)) <$>
        Part.bind ↑(decode (Nat.pair n n_1)) fun a =>
          Part.map encode ((fun a => Part.map (fun b => bif (a, b).2 then 0 else 1) (p a.1 a.2)) a)) =
    Part.bind ↑Option.none fun a => Part.map encode ((fun a => Nat.rfind (p a)) a)

Next tactic:
simp [e, Nat.rfind_zero_none, map_id']
theorem rfind {p : α → ℕ →. Bool} (hp : Partrec₂ p) : Partrec fun a => Nat.rfind (p a) :=
  (Nat.Partrec.rfind <|
        hp.map ((Primrec.dom_bool fun b => cond b 0 1).comp Primrec.snd).to₂.to_comp).of_eq
    fun n => by
    cases' e : decode (α := α) n with a <;> 

Proof state:
case some
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
p : α → ℕ →. Bool
hp : Partrec₂ p
n : ℕ
a : α
e : decode n = Option.some a
⊢ (Nat.rfind fun n_1 =>
      (fun m => decide (m = 0)) <$>
        Part.bind ↑(decode (Nat.pair n n_1)) fun a =>
          Part.map encode ((fun a => Part.map (fun b => bif (a, b).2 then 0 else 1) (p a.1 a.2)) a)) =
    Part.bind ↑(Option.some a) fun a => Part.map encode ((fun a => Nat.rfind (p a)) a)

Next tactic:
simp [e, Nat.rfind_zero_none, map_id']
theorem rfind {p : α → ℕ →. Bool} (hp : Partrec₂ p) : Partrec fun a => Nat.rfind (p a) :=
  (Nat.Partrec.rfind <|
        hp.map ((Primrec.dom_bool fun b => cond b 0 1).comp Primrec.snd).to₂.to_comp).of_eq
    fun n => by
    cases' e : decode (α := α) n with a <;> simp [e, Nat.rfind_zero_none, map_id']
    

Proof state:
case some
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
p : α → ℕ →. Bool
hp : Partrec₂ p
n : ℕ
a : α
e : decode n = Option.some a
⊢ (Nat.rfind fun n => Part.map (fun m => decide (m = 0)) (Part.map (fun b => bif b then 0 else 1) (p a n))) =
    Nat.rfind (p a)

Next tactic:
congr
theorem rfind {p : α → ℕ →. Bool} (hp : Partrec₂ p) : Partrec fun a => Nat.rfind (p a) :=
  (Nat.Partrec.rfind <|
        hp.map ((Primrec.dom_bool fun b => cond b 0 1).comp Primrec.snd).to₂.to_comp).of_eq
    fun n => by
    cases' e : decode (α := α) n with a <;> simp [e, Nat.rfind_zero_none, map_id']
    congr; 

Proof state:
case some.e_p
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
p : α → ℕ →. Bool
hp : Partrec₂ p
n : ℕ
a : α
e : decode n = Option.some a
⊢ (fun n => Part.map (fun m => decide (m = 0)) (Part.map (fun b => bif b then 0 else 1) (p a n))) = p a

Next tactic:
funext n
theorem rfind {p : α → ℕ →. Bool} (hp : Partrec₂ p) : Partrec fun a => Nat.rfind (p a) :=
  (Nat.Partrec.rfind <|
        hp.map ((Primrec.dom_bool fun b => cond b 0 1).comp Primrec.snd).to₂.to_comp).of_eq
    fun n => by
    cases' e : decode (α := α) n with a <;> simp [e, Nat.rfind_zero_none, map_id']
    congr; funext n
    

Proof state:
case some.e_p.h
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
p : α → ℕ →. Bool
hp : Partrec₂ p
n✝ : ℕ
a : α
e : decode n✝ = Option.some a
n : ℕ
⊢ Part.map (fun m => decide (m = 0)) (Part.map (fun b => bif b then 0 else 1) (p a n)) = p a n

Next tactic:
simp only [map_map, Function.comp]
theorem rfind {p : α → ℕ →. Bool} (hp : Partrec₂ p) : Partrec fun a => Nat.rfind (p a) :=
  (Nat.Partrec.rfind <|
        hp.map ((Primrec.dom_bool fun b => cond b 0 1).comp Primrec.snd).to₂.to_comp).of_eq
    fun n => by
    cases' e : decode (α := α) n with a <;> simp [e, Nat.rfind_zero_none, map_id']
    congr; funext n
    simp only [map_map, Function.comp]
    

Proof state:
case some.e_p.h
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
p : α → ℕ →. Bool
hp : Partrec₂ p
n✝ : ℕ
a : α
e : decode n✝ = Option.some a
n : ℕ
⊢ Part.map (fun x => decide ((bif x then 0 else 1) = 0)) (p a n) = p a n

Next tactic:
refine map_id' (fun b => ?_) _
theorem rfind {p : α → ℕ →. Bool} (hp : Partrec₂ p) : Partrec fun a => Nat.rfind (p a) :=
  (Nat.Partrec.rfind <|
        hp.map ((Primrec.dom_bool fun b => cond b 0 1).comp Primrec.snd).to₂.to_comp).of_eq
    fun n => by
    cases' e : decode (α := α) n with a <;> simp [e, Nat.rfind_zero_none, map_id']
    congr; funext n
    simp only [map_map, Function.comp]
    refine map_id' (fun b => ?_) _
    

Proof state:
case some.e_p.h
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
p : α → ℕ →. Bool
hp : Partrec₂ p
n✝ : ℕ
a : α
e : decode n✝ = Option.some a
n : ℕ
b : Bool
⊢ decide ((bif b then 0 else 1) = 0) = b

Next tactic:
cases b
theorem rfind {p : α → ℕ →. Bool} (hp : Partrec₂ p) : Partrec fun a => Nat.rfind (p a) :=
  (Nat.Partrec.rfind <|
        hp.map ((Primrec.dom_bool fun b => cond b 0 1).comp Primrec.snd).to₂.to_comp).of_eq
    fun n => by
    cases' e : decode (α := α) n with a <;> simp [e, Nat.rfind_zero_none, map_id']
    congr; funext n
    simp only [map_map, Function.comp]
    refine map_id' (fun b => ?_) _
    cases b <;> 

Proof state:
case some.e_p.h.false
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
p : α → ℕ →. Bool
hp : Partrec₂ p
n✝ : ℕ
a : α
e : decode n✝ = Option.some a
n : ℕ
⊢ decide ((bif false then 0 else 1) = 0) = false

Next tactic:
rfl