-- Mathlib/Computability/PartrecCode.lean
theorem hG : Primrec G

Proof state:
case hpr
a : Primrec fun a => ofNat (ℕ × Code) a.length
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) a.1.length).1
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) a.1.1.length).1
n✝ : Primrec fun a => a.1.2
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) a.1.1.length).2
L : Primrec fun a => a.1.1.1
k : Primrec fun a => (ofNat (ℕ × Code) a.1.1.1.length).1
n : Primrec fun a => a.1.1.2
cf : Primrec fun a => a.2.1
⊢ Primrec fun a => do
    let x ← Nat.Partrec.Code.lup a.1.1.1 ((ofNat (ℕ × Code) a.1.1.1.length).1, a.2.1) a.1.1.2
    let y ← Nat.Partrec.Code.lup a.1.1.1 ((ofNat (ℕ × Code) a.1.1.1.length).1, a.2.2.1) a.1.1.2
    some (Nat.pair x y)

Tactic:
have cg := (Primrec.fst.comp Primrec.snd).comp
  (Primrec.snd (α := (List (List (Option ℕ)) × ℕ) × ℕ)
    (β := Code × Code × Option ℕ × Option ℕ))

Result:
case hpr
a : Primrec fun a => ofNat (ℕ × Code) a.length
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) a.1.length).1
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) a.1.1.length).1
n✝ : Primrec fun a => a.1.2
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) a.1.1.length).2
L : Primrec fun a => a.1.1.1
k : Primrec fun a => (ofNat (ℕ × Code) a.1.1.1.length).1
n : Primrec fun a => a.1.1.2
cf : Primrec fun a => a.2.1
cg : Primrec fun a => a.2.2.1
⊢ Primrec fun a => do
    let x ← Nat.Partrec.Code.lup a.1.1.1 ((ofNat (ℕ × Code) a.1.1.1.length).1, a.2.1) a.1.1.2
    let y ← Nat.Partrec.Code.lup a.1.1.1 ((ofNat (ℕ × Code) a.1.1.1.length).1, a.2.2.1) a.1.1.2
    some (Nat.pair x y)

Proof state:
case hco
a : Primrec fun a => ofNat (ℕ × Code) a.length
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) a.1.length).1
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) a.1.1.length).1
n✝ : Primrec fun a => a.1.2
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) a.1.1.length).2
L : Primrec fun a => a.1.1.1
k : Primrec fun a => (ofNat (ℕ × Code) a.1.1.1.length).1
n : Primrec fun a => a.1.1.2
cf : Primrec fun a => a.2.1
cg : Primrec fun a => a.2.2.1
⊢ Primrec fun a => do
    let x ← Nat.Partrec.Code.lup a.1.1.1 ((ofNat (ℕ × Code) a.1.1.1.length).1, a.2.2.1) a.1.1.2
    Nat.Partrec.Code.lup a.1.1.1 ((ofNat (ℕ × Code) a.1.1.1.length).1, a.2.1) x

Tactic:
refine Primrec.option_bind (hlup.comp <| L.pair <| (k.pair cg).pair n) ?_

Result:
case hco
a : Primrec fun a => ofNat (ℕ × Code) a.length
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) a.1.length).1
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) a.1.1.length).1
n✝ : Primrec fun a => a.1.2
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) a.1.1.length).2
L : Primrec fun a => a.1.1.1
k : Primrec fun a => (ofNat (ℕ × Code) a.1.1.1.length).1
n : Primrec fun a => a.1.1.2
cf : Primrec fun a => a.2.1
cg : Primrec fun a => a.2.2.1
⊢ Primrec₂ fun a x => Nat.Partrec.Code.lup a.1.1.1 ((ofNat (ℕ × Code) a.1.1.1.length).1, a.2.1) x

Proof state:
case hpc
a : Primrec fun a => ofNat (ℕ × Code) a.length
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) a.1.length).1
n✝ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) a.1.1.length).1
n : Primrec fun a => a.1.2
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) a.1.1.length).2
L : Primrec fun a => a.1.1.1
k : Primrec fun a => (ofNat (ℕ × Code) a.1.1.1.length).1
⊢ Primrec fun a =>
    let z := (unpair a.1.1.2).1;
    Nat.casesOn (unpair a.1.1.2).2 (Nat.Partrec.Code.lup a.1.1.1 ((ofNat (ℕ × Code) a.1.1.1.length).1, a.2.1) z)
      fun y => do
      let i ← Nat.Partrec.Code.lup a.1.1.1 (a.1.2, (ofNat (ℕ × Code) a.1.1.1.length).2) (Nat.pair z y)
      Nat.Partrec.Code.lup a.1.1.1 ((ofNat (ℕ × Code) a.1.1.1.length).1, a.2.2.1) (Nat.pair z (Nat.pair y i))

Tactic:
have n := n.comp (Primrec.fst (β := Code × Code × Option ℕ × Option ℕ))

Result:
case hpc
a : Primrec fun a => ofNat (ℕ × Code) a.length
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) a.1.length).1
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) a.1.1.length).1
n✝ : Primrec fun a => a.1.2
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) a.1.1.length).2
L : Primrec fun a => a.1.1.1
k : Primrec fun a => (ofNat (ℕ × Code) a.1.1.1.length).1
n : Primrec fun a => a.1.1.2
⊢ Primrec fun a =>
    let z := (unpair a.1.1.2).1;
    Nat.casesOn (unpair a.1.1.2).2 (Nat.Partrec.Code.lup a.1.1.1 ((ofNat (ℕ × Code) a.1.1.1.length).1, a.2.1) z)
      fun y => do
      let i ← Nat.Partrec.Code.lup a.1.1.1 (a.1.2, (ofNat (ℕ × Code) a.1.1.1.length).2) (Nat.pair z y)
      Nat.Partrec.Code.lup a.1.1.1 ((ofNat (ℕ × Code) a.1.1.1.length).1, a.2.2.1) (Nat.pair z (Nat.pair y i))

Proof state:
case hpr
a : Primrec fun a => ofNat (ℕ × Code) a.length
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) a.1.length).1
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) a.1.1.length).1
n✝ : Primrec fun a => a.1.2
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) a.1.1.length).2
L : Primrec fun a => a.1.1.1
k : Primrec fun a => (ofNat (ℕ × Code) a.1.1.1.length).1
n : Primrec fun a => a.1.1.2
cf : Primrec fun a => a.2.1
cg : Primrec fun a => a.2.2.1
⊢ Primrec₂ fun p => Nat.pair p.2

Tactic:
unfold Primrec₂

Result:
case hpr
a : Primrec fun a => ofNat (ℕ × Code) a.length
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) a.1.length).1
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) a.1.1.length).1
n✝ : Primrec fun a => a.1.2
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) a.1.1.length).2
L : Primrec fun a => a.1.1.1
k : Primrec fun a => (ofNat (ℕ × Code) a.1.1.1.length).1
n : Primrec fun a => a.1.1.2
cf : Primrec fun a => a.2.1
cg : Primrec fun a => a.2.2.1
⊢ Primrec fun p => (fun p => Nat.pair p.2) p.1 p.2