l3lab/ntp-mathlib huggingface dataset:
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.true
α : 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 true then 0 else 1) = 0) = true

Next tactic:
rfl
theorem nat_casesOn_right {f : α → ℕ} {g : α → σ} {h : α → ℕ →. σ} (hf : Computable f)
    (hg : Computable g) (hh : Partrec₂ h) : Partrec fun a => (f a).casesOn (some (g a)) (h a) :=
  (nat_rec hf hg (hh.comp fst (pred.comp <| hf.comp fst)).to₂).of_eq fun 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 : α → σ
h : α → ℕ →. σ
hf : Computable f
hg : Computable g
hh : Partrec₂ h
a : α
⊢ Nat.rec (↑g a) (fun y IH => Part.bind IH fun i => h (a, y, i).1 (Nat.pred (f (a, y, i).1))) (f a) =
    Nat.casesOn (f a) (Part.some (g a)) (h a)

Next tactic:
simp
theorem nat_casesOn_right {f : α → ℕ} {g : α → σ} {h : α → ℕ →. σ} (hf : Computable f)
    (hg : Computable g) (hh : Partrec₂ h) : Partrec fun a => (f a).casesOn (some (g a)) (h a) :=
  (nat_rec hf hg (hh.comp fst (pred.comp <| hf.comp fst)).to₂).of_eq fun a => 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 : α → σ
h : α → ℕ →. σ
hf : Computable f
hg : Computable g
hh : Partrec₂ h
a : α
⊢ Nat.rec (Part.some (g a)) (fun y IH => Part.bind IH fun i => h a (Nat.pred (f a))) (f a) =
    Nat.rec (Part.some (g a)) (fun n n_ih => h a n) (f a)

Next tactic:
cases' f a with n
theorem nat_casesOn_right {f : α → ℕ} {g : α → σ} {h : α → ℕ →. σ} (hf : Computable f)
    (hg : Computable g) (hh : Partrec₂ h) : Partrec fun a => (f a).casesOn (some (g a)) (h a) :=
  (nat_rec hf hg (hh.comp fst (pred.comp <| hf.comp fst)).to₂).of_eq fun a => by
    simp; cases' f a with n <;> 

Proof state:
case 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 : Computable g
hh : Partrec₂ h
a : α
⊢ Nat.rec (Part.some (g a)) (fun y IH => Part.bind IH fun i => h a (Nat.pred Nat.zero)) Nat.zero =
    Nat.rec (Part.some (g a)) (fun n n_ih => h a n) Nat.zero

Next tactic:
simp
theorem nat_casesOn_right {f : α → ℕ} {g : α → σ} {h : α → ℕ →. σ} (hf : Computable f)
    (hg : Computable g) (hh : Partrec₂ h) : Partrec fun a => (f a).casesOn (some (g a)) (h a) :=
  (nat_rec hf hg (hh.comp fst (pred.comp <| hf.comp fst)).to₂).of_eq fun a => by
    simp; cases' f a with n <;> 

Proof state:
case 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 : Computable g
hh : Partrec₂ h
a : α
n : ℕ
⊢ Nat.rec (Part.some (g a)) (fun y IH => Part.bind IH fun i => h a (Nat.pred (Nat.succ n))) (Nat.succ n) =
    Nat.rec (Part.some (g a)) (fun n n_ih => h a n) (Nat.succ n)

Next tactic:
simp
theorem nat_casesOn_right {f : α → ℕ} {g : α → σ} {h : α → ℕ →. σ} (hf : Computable f)
    (hg : Computable g) (hh : Partrec₂ h) : Partrec fun a => (f a).casesOn (some (g a)) (h a) :=
  (nat_rec hf hg (hh.comp fst (pred.comp <| hf.comp fst)).to₂).of_eq fun a => by
    simp; cases' f a with n <;> simp
    

Proof state:
case 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 : Computable g
hh : Partrec₂ h
a : α
n : ℕ
⊢ (Part.bind (Nat.rec (Part.some (g a)) (fun y IH => Part.bind IH fun i => h a n) n) fun i => h a n) = h a n

Next tactic:
refine' ext fun b => ⟨fun H => _, fun H => _⟩
theorem nat_casesOn_right {f : α → ℕ} {g : α → σ} {h : α → ℕ →. σ} (hf : Computable f)
    (hg : Computable g) (hh : Partrec₂ h) : Partrec fun a => (f a).casesOn (some (g a)) (h a) :=
  (nat_rec hf hg (hh.comp fst (pred.comp <| hf.comp fst)).to₂).of_eq fun a => by
    simp; cases' f a with n <;> simp
    refine' ext fun b => ⟨fun H => _, fun H => _⟩
    · 

Proof state:
case succ.refine'_1
α : 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 : Computable g
hh : Partrec₂ h
a : α
n : ℕ
b : σ
H : b ∈ Part.bind (Nat.rec (Part.some (g a)) (fun y IH => Part.bind IH fun i => h a n) n) fun i => h a n
⊢ b ∈ h a n

Next tactic:
rcases mem_bind_iff.1 H with ⟨c, _, h₂⟩
theorem nat_casesOn_right {f : α → ℕ} {g : α → σ} {h : α → ℕ →. σ} (hf : Computable f)
    (hg : Computable g) (hh : Partrec₂ h) : Partrec fun a => (f a).casesOn (some (g a)) (h a) :=
  (nat_rec hf hg (hh.comp fst (pred.comp <| hf.comp fst)).to₂).of_eq fun a => by
    simp; cases' f a with n <;> simp
    refine' ext fun b => ⟨fun H => _, fun H => _⟩
    · rcases mem_bind_iff.1 H with ⟨c, _, h₂⟩
      

Proof state:
case succ.refine'_1.intro.intro
α : 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 : Computable g
hh : Partrec₂ h
a : α
n : ℕ
b : σ
H : b ∈ Part.bind (Nat.rec (Part.some (g a)) (fun y IH => Part.bind IH fun i => h a n) n) fun i => h a n
c : σ
left✝ : c ∈ Nat.rec (Part.some (g a)) (fun y IH => Part.bind IH fun i => h a n) n
h₂ : b ∈ h a n
⊢ b ∈ h a n

Next tactic:
exact h₂
theorem nat_casesOn_right {f : α → ℕ} {g : α → σ} {h : α → ℕ →. σ} (hf : Computable f)
    (hg : Computable g) (hh : Partrec₂ h) : Partrec fun a => (f a).casesOn (some (g a)) (h a) :=
  (nat_rec hf hg (hh.comp fst (pred.comp <| hf.comp fst)).to₂).of_eq fun a => by
    simp; cases' f a with n <;> simp
    refine' ext fun b => ⟨fun H => _, fun H => _⟩
    · rcases mem_bind_iff.1 H with ⟨c, _, h₂⟩
      exact h₂
    · 

Proof state:
case succ.refine'_2
α : 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 : Computable g
hh : Partrec₂ h
a : α
n : ℕ
b : σ
H : b ∈ h a n
⊢ b ∈ Part.bind (Nat.rec (Part.some (g a)) (fun y IH => Part.bind IH fun i => h a n) n) fun i => h a n

Next tactic:
have : ∀ m, (Nat.rec (motive := fun _ => Part σ)
          (Part.some (g a)) (fun y IH => IH.bind fun _ => h a n) m).Dom := by
        intro m
        induction m <;> simp [*, H.fst]
theorem nat_casesOn_right {f : α → ℕ} {g : α → σ} {h : α → ℕ →. σ} (hf : Computable f)
    (hg : Computable g) (hh : Partrec₂ h) : Partrec fun a => (f a).casesOn (some (g a)) (h a) :=
  (nat_rec hf hg (hh.comp fst (pred.comp <| hf.comp fst)).to₂).of_eq fun a => by
    simp; cases' f a with n <;> simp
    refine' ext fun b => ⟨fun H => _, fun H => _⟩
    · rcases mem_bind_iff.1 H with ⟨c, _, h₂⟩
      exact h₂
    · have : ∀ m, (Nat.rec (motive := fun _ => Part σ)
          (Part.some (g a)) (fun y IH => IH.bind fun _ => h a n) m).Dom := 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 : Computable g
hh : Partrec₂ h
a : α
n : ℕ
b : σ
H : b ∈ h a n
⊢ ∀ (m : ℕ), (Nat.rec (Part.some (g a)) (fun y IH => Part.bind IH fun x => h a n) m).Dom

Next tactic:
intro m
theorem nat_casesOn_right {f : α → ℕ} {g : α → σ} {h : α → ℕ →. σ} (hf : Computable f)
    (hg : Computable g) (hh : Partrec₂ h) : Partrec fun a => (f a).casesOn (some (g a)) (h a) :=
  (nat_rec hf hg (hh.comp fst (pred.comp <| hf.comp fst)).to₂).of_eq fun a => by
    simp; cases' f a with n <;> simp
    refine' ext fun b => ⟨fun H => _, fun H => _⟩
    · rcases mem_bind_iff.1 H with ⟨c, _, h₂⟩
      exact h₂
    · have : ∀ m, (Nat.rec (motive := fun _ => Part σ)
          (Part.some (g a)) (fun y IH => IH.bind fun _ => h a n) m).Dom := by
        intro m
        

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 : Computable g
hh : Partrec₂ h
a : α
n : ℕ
b : σ
H : b ∈ h a n
m : ℕ
⊢ (Nat.rec (Part.some (g a)) (fun y IH => Part.bind IH fun x => h a n) m).Dom

Next tactic:
induction m
theorem nat_casesOn_right {f : α → ℕ} {g : α → σ} {h : α → ℕ →. σ} (hf : Computable f)
    (hg : Computable g) (hh : Partrec₂ h) : Partrec fun a => (f a).casesOn (some (g a)) (h a) :=
  (nat_rec hf hg (hh.comp fst (pred.comp <| hf.comp fst)).to₂).of_eq fun a => by
    simp; cases' f a with n <;> simp
    refine' ext fun b => ⟨fun H => _, fun H => _⟩
    · rcases mem_bind_iff.1 H with ⟨c, _, h₂⟩
      exact h₂
    · have : ∀ m, (Nat.rec (motive := fun _ => Part σ)
          (Part.some (g a)) (fun y IH => IH.bind fun _ => h a n) m).Dom := by
        intro m
        induction m <;> 

Proof state:
case 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 : Computable g
hh : Partrec₂ h
a : α
n : ℕ
b : σ
H : b ∈ h a n
⊢ (Nat.rec (Part.some (g a)) (fun y IH => Part.bind IH fun x => h a n) Nat.zero).Dom

Next tactic:
simp [*, H.fst]
theorem nat_casesOn_right {f : α → ℕ} {g : α → σ} {h : α → ℕ →. σ} (hf : Computable f)
    (hg : Computable g) (hh : Partrec₂ h) : Partrec fun a => (f a).casesOn (some (g a)) (h a) :=
  (nat_rec hf hg (hh.comp fst (pred.comp <| hf.comp fst)).to₂).of_eq fun a => by
    simp; cases' f a with n <;> simp
    refine' ext fun b => ⟨fun H => _, fun H => _⟩
    · rcases mem_bind_iff.1 H with ⟨c, _, h₂⟩
      exact h₂
    · have : ∀ m, (Nat.rec (motive := fun _ => Part σ)
          (Part.some (g a)) (fun y IH => IH.bind fun _ => h a n) m).Dom := by
        intro m
        induction m <;> 

Proof state:
case 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 : Computable g
hh : Partrec₂ h
a : α
n : ℕ
b : σ
H : b ∈ h a n
n✝ : ℕ
n_ih✝ : (Nat.rec (Part.some (g a)) (fun y IH => Part.bind IH fun x => h a n) n✝).Dom
⊢ (Nat.rec (Part.some (g a)) (fun y IH => Part.bind IH fun x => h a n) (Nat.succ n✝)).Dom

Next tactic:
simp [*, H.fst]
theorem nat_casesOn_right {f : α → ℕ} {g : α → σ} {h : α → ℕ →. σ} (hf : Computable f)
    (hg : Computable g) (hh : Partrec₂ h) : Partrec fun a => (f a).casesOn (some (g a)) (h a) :=
  (nat_rec hf hg (hh.comp fst (pred.comp <| hf.comp fst)).to₂).of_eq fun a => by
    simp; cases' f a with n <;> simp
    refine' ext fun b => ⟨fun H => _, fun H => _⟩
    · rcases mem_bind_iff.1 H with ⟨c, _, h₂⟩
      exact h₂
    · have : ∀ m, (Nat.rec (motive := fun _ => Part σ)
          (Part.some (g a)) (fun y IH => IH.bind fun _ => h a n) m).Dom := by
        intro m
        induction m <;> simp [*, H.fst]
      

Proof state:
case succ.refine'_2
α : 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 : Computable g
hh : Partrec₂ h
a : α
n : ℕ
b : σ
H : b ∈ h a n
this : ∀ (m : ℕ), (Nat.rec (Part.some (g a)) (fun y IH => Part.bind IH fun x => h a n) m).Dom
⊢ b ∈ Part.bind (Nat.rec (Part.some (g a)) (fun y IH => Part.bind IH fun i => h a n) n) fun i => h a n

Next tactic:
exact ⟨⟨this n, H.fst⟩, H.snd⟩
theorem bind_decode₂_iff {f : α →. σ} :
    Partrec f ↔ Nat.Partrec fun n => Part.bind (decode₂ α n) fun a => (f a).map encode :=
  ⟨fun hf =>
    nat_iff.1 <|
      (Computable.ofOption Primrec.decode₂.to_comp).bind <|
        (map hf (Computable.encode.comp snd).to₂).comp snd,
    fun h =>
    map_encode_iff.1 <| by 

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

Next tactic:
simpa [encodek₂] using (nat_iff.2 h).comp (@Computable.encode α _)
theorem vector_mOfFn :
    ∀ {n} {f : Fin n → α →. σ},
      (∀ i, Partrec (f i)) → Partrec fun a : α => Vector.mOfFn fun i => f i a
  | 0, _, _ => const _
  | n + 1, f, hf => by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
n : ℕ
f : Fin (n + 1) → α →. σ
hf : ∀ (i : Fin (n + 1)), Partrec (f i)
⊢ Partrec fun a => Vector.mOfFn fun i => f i a

Next tactic:
simp only [Vector.mOfFn, Nat.add_eq, Nat.add_zero, pure_eq_some, bind_eq_bind]
theorem vector_mOfFn :
    ∀ {n} {f : Fin n → α →. σ},
      (∀ i, Partrec (f i)) → Partrec fun a : α => Vector.mOfFn fun i => f i a
  | 0, _, _ => const _
  | n + 1, f, hf => by
    simp only [Vector.mOfFn, Nat.add_eq, Nat.add_zero, pure_eq_some, bind_eq_bind]
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
n : ℕ
f : Fin (n + 1) → α →. σ
hf : ∀ (i : Fin (n + 1)), Partrec (f i)
⊢ Partrec fun a =>
    Part.bind (f 0 a) fun a_1 => Part.bind (Vector.mOfFn fun i => f (Fin.succ i) a) fun v => Part.some (a_1 ::ᵥ v)

Next tactic:
exact
      (hf 0).bind
        (Partrec.bind ((vector_mOfFn fun i => hf i.succ).comp fst)
          (Primrec.vector_cons.to_comp.comp (snd.comp fst) snd))
theorem bind_decode_iff {f : α → β → Option σ} :
    (Computable₂ fun a n => (decode (α := β) n).bind (f a)) ↔ Computable₂ f :=
  ⟨fun hf =>
    Nat.Partrec.of_eq
      (((Partrec.nat_iff.2
        (Nat.Partrec.ppred.comp <| Nat.Partrec.of_primrec <| Primcodable.prim (α := β))).comp
            snd).bind
        (Computable.comp hf fst).to₂.partrec₂)
      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 : α → β → Option σ
hf : Computable₂ fun a n => Option.bind (decode n) (f a)
n : ℕ
⊢ (Part.bind ↑(decode n) fun a =>
      map encode
        ((fun a =>
            Part.bind
              (do
                let n ← (↑fun n => encode (decode n)) a.2
                ↑(Nat.ppred n))
              ↑fun b => (fun a n => Option.bind (decode n) (f a)) (a, b).1.1 (a, b).1.2)
          a)) =
    Part.bind ↑(decode n) fun a => map encode ((↑fun p => f p.1 p.2) a)

Next tactic:
simp
theorem bind_decode_iff {f : α → β → Option σ} :
    (Computable₂ fun a n => (decode (α := β) n).bind (f a)) ↔ Computable₂ f :=
  ⟨fun hf =>
    Nat.Partrec.of_eq
      (((Partrec.nat_iff.2
        (Nat.Partrec.ppred.comp <| Nat.Partrec.of_primrec <| Primcodable.prim (α := β))).comp
            snd).bind
        (Computable.comp hf fst).to₂.partrec₂)
      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 : α → β → Option σ
hf : Computable₂ fun a n => Option.bind (decode n) (f a)
n : ℕ
⊢ (Part.bind ↑(Option.bind (decode (Nat.unpair n).1) fun a => Option.some (a, (Nat.unpair n).2)) fun a =>
      Part.bind ↑(Nat.ppred (encode (decode a.2))) fun y => Part.some (encode (Option.bind (decode a.2) (f a.1)))) =
    Part.bind ↑(Option.bind (decode (Nat.unpair n).1) fun a => Option.map (Prod.mk a) (decode (Nat.unpair n).2))
      fun a => Part.some (encode (f a.1 a.2))

Next tactic:
cases decode (α := α) n.unpair.1
theorem bind_decode_iff {f : α → β → Option σ} :
    (Computable₂ fun a n => (decode (α := β) n).bind (f a)) ↔ Computable₂ f :=
  ⟨fun hf =>
    Nat.Partrec.of_eq
      (((Partrec.nat_iff.2
        (Nat.Partrec.ppred.comp <| Nat.Partrec.of_primrec <| Primcodable.prim (α := β))).comp
            snd).bind
        (Computable.comp hf fst).to₂.partrec₂)
      fun n => by
        simp; cases decode (α := α) n.unpair.1 <;> 

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 : α → β → Option σ
hf : Computable₂ fun a n => Option.bind (decode n) (f a)
n : ℕ
⊢ (Part.bind ↑(Option.bind Option.none fun a => Option.some (a, (Nat.unpair n).2)) fun a =>
      Part.bind ↑(Nat.ppred (encode (decode a.2))) fun y => Part.some (encode (Option.bind (decode a.2) (f a.1)))) =
    Part.bind ↑(Option.bind Option.none fun a => Option.map (Prod.mk a) (decode (Nat.unpair n).2)) fun a =>
      Part.some (encode (f a.1 a.2))

Next tactic:
simp
theorem bind_decode_iff {f : α → β → Option σ} :
    (Computable₂ fun a n => (decode (α := β) n).bind (f a)) ↔ Computable₂ f :=
  ⟨fun hf =>
    Nat.Partrec.of_eq
      (((Partrec.nat_iff.2
        (Nat.Partrec.ppred.comp <| Nat.Partrec.of_primrec <| Primcodable.prim (α := β))).comp
            snd).bind
        (Computable.comp hf fst).to₂.partrec₂)
      fun n => by
        simp; cases decode (α := α) n.unpair.1 <;> 

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 : α → β → Option σ
hf : Computable₂ fun a n => Option.bind (decode n) (f a)
n : ℕ
val✝ : α
⊢ (Part.bind ↑(Option.bind (Option.some val✝) fun a => Option.some (a, (Nat.unpair n).2)) fun a =>
      Part.bind ↑(Nat.ppred (encode (decode a.2))) fun y => Part.some (encode (Option.bind (decode a.2) (f a.1)))) =
    Part.bind ↑(Option.bind (Option.some val✝) fun a => Option.map (Prod.mk a) (decode (Nat.unpair n).2)) fun a =>
      Part.some (encode (f a.1 a.2))

Next tactic:
simp
theorem bind_decode_iff {f : α → β → Option σ} :
    (Computable₂ fun a n => (decode (α := β) n).bind (f a)) ↔ Computable₂ f :=
  ⟨fun hf =>
    Nat.Partrec.of_eq
      (((Partrec.nat_iff.2
        (Nat.Partrec.ppred.comp <| Nat.Partrec.of_primrec <| Primcodable.prim (α := β))).comp
            snd).bind
        (Computable.comp hf fst).to₂.partrec₂)
      fun n => by
        simp; cases decode (α := α) n.unpair.1 <;> simp;
          

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 : α → β → Option σ
hf : Computable₂ fun a n => Option.bind (decode n) (f a)
n : ℕ
val✝ : α
⊢ (Part.bind ↑(Nat.ppred (encode (decode (Nat.unpair n).2))) fun y =>
      Part.some (encode (Option.bind (decode (Nat.unpair n).2) (f val✝)))) =
    Part.bind ↑(Option.map (Prod.mk val✝) (decode (Nat.unpair n).2)) fun a => Part.some (encode (f a.1 a.2))

Next tactic:
cases decode (α := β) n.unpair.2
theorem bind_decode_iff {f : α → β → Option σ} :
    (Computable₂ fun a n => (decode (α := β) n).bind (f a)) ↔ Computable₂ f :=
  ⟨fun hf =>
    Nat.Partrec.of_eq
      (((Partrec.nat_iff.2
        (Nat.Partrec.ppred.comp <| Nat.Partrec.of_primrec <| Primcodable.prim (α := β))).comp
            snd).bind
        (Computable.comp hf fst).to₂.partrec₂)
      fun n => by
        simp; cases decode (α := α) n.unpair.1 <;> simp;
          cases decode (α := β) n.unpair.2 <;> 

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

Next tactic:
simp
theorem bind_decode_iff {f : α → β → Option σ} :
    (Computable₂ fun a n => (decode (α := β) n).bind (f a)) ↔ Computable₂ f :=
  ⟨fun hf =>
    Nat.Partrec.of_eq
      (((Partrec.nat_iff.2
        (Nat.Partrec.ppred.comp <| Nat.Partrec.of_primrec <| Primcodable.prim (α := β))).comp
            snd).bind
        (Computable.comp hf fst).to₂.partrec₂)
      fun n => by
        simp; cases decode (α := α) n.unpair.1 <;> simp;
          cases decode (α := β) n.unpair.2 <;> 

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

Next tactic:
simp
theorem bind_decode_iff {f : α → β → Option σ} :
    (Computable₂ fun a n => (decode (α := β) n).bind (f a)) ↔ Computable₂ f :=
  ⟨fun hf =>
    Nat.Partrec.of_eq
      (((Partrec.nat_iff.2
        (Nat.Partrec.ppred.comp <| Nat.Partrec.of_primrec <| Primcodable.prim (α := β))).comp
            snd).bind
        (Computable.comp hf fst).to₂.partrec₂)
      fun n => by
        simp; cases decode (α := α) n.unpair.1 <;> simp;
          cases decode (α := β) n.unpair.2 <;> simp,
    fun hf => by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α → β → Option σ
hf : Computable₂ f
⊢ Computable₂ fun a n => Option.bind (decode n) (f a)

Next tactic:
have :
      Partrec fun a : α × ℕ =>
        (encode (decode (α := β) a.2)).casesOn (some Option.none)
          fun n => Part.map (f a.1) (decode (α := β) n) :=
      Partrec.nat_casesOn_right
        (h := fun (a : α × ℕ) (n : ℕ) ↦ map (fun b ↦ f a.1 b) (Part.ofOption (decode n)))
        (Primrec.encdec.to_comp.comp snd) (const Option.none)
        ((ofOption (Computable.decode.comp snd)).map (hf.comp (fst.comp <| fst.comp fst) snd).to₂)
theorem bind_decode_iff {f : α → β → Option σ} :
    (Computable₂ fun a n => (decode (α := β) n).bind (f a)) ↔ Computable₂ f :=
  ⟨fun hf =>
    Nat.Partrec.of_eq
      (((Partrec.nat_iff.2
        (Nat.Partrec.ppred.comp <| Nat.Partrec.of_primrec <| Primcodable.prim (α := β))).comp
            snd).bind
        (Computable.comp hf fst).to₂.partrec₂)
      fun n => by
        simp; cases decode (α := α) n.unpair.1 <;> simp;
          cases decode (α := β) n.unpair.2 <;> simp,
    fun hf => by
    have :
      Partrec fun a : α × ℕ =>
        (encode (decode (α := β) a.2)).casesOn (some Option.none)
          fun n => Part.map (f a.1) (decode (α := β) n) :=
      Partrec.nat_casesOn_right
        (h := fun (a : α × ℕ) (n : ℕ) ↦ map (fun b ↦ f a.1 b) (Part.ofOption (decode n)))
        (Primrec.encdec.to_comp.comp snd) (const Option.none)
        ((ofOption (Computable.decode.comp snd)).map (hf.comp (fst.comp <| fst.comp fst) snd).to₂)
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
inst✝³ : Primcodable α
inst✝² : Primcodable β
inst✝¹ : Primcodable γ
inst✝ : Primcodable σ
f : α → β → Option σ
hf : Computable₂ f
this : Partrec fun a => Nat.casesOn (encode (decode a.2)) (Part.some Option.none) fun n => map (f a.1) ↑(decode n)
⊢ Computable₂ fun a n => Option.bind (decode n) (f a)

Next tactic:
refine' this.of_eq fun a => _