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

Proof state:
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
⊢ Primrec fun p =>
    (fun p k' =>
        Code.recOn (ofNat (ℕ × Code) p.1.length).2 (some 0) (some p.2.succ) (some (unpair p.2).1) (some (unpair p.2).2)
          (fun cf cg x x => do
            let x ← Nat.Partrec.Code.lup p.1 ((ofNat (ℕ × Code) p.1.length).1, cf) p.2
            let y ← Nat.Partrec.Code.lup p.1 ((ofNat (ℕ × Code) p.1.length).1, cg) p.2
            some (Nat.pair x y))
          (fun cf cg x x => do
            let x ← Nat.Partrec.Code.lup p.1 ((ofNat (ℕ × Code) p.1.length).1, cg) p.2
            Nat.Partrec.Code.lup p.1 ((ofNat (ℕ × Code) p.1.length).1, cf) x)
          (fun cf cg x x =>
            let z := (unpair p.2).1;
            Nat.casesOn (unpair p.2).2 (Nat.Partrec.Code.lup p.1 ((ofNat (ℕ × Code) p.1.length).1, cf) z) fun y => do
              let i ← Nat.Partrec.Code.lup p.1 (k', (ofNat (ℕ × Code) p.1.length).2) (Nat.pair z y)
              Nat.Partrec.Code.lup p.1 ((ofNat (ℕ × Code) p.1.length).1, cg) (Nat.pair z (Nat.pair y i)))
          fun cf x =>
          let z := (unpair p.2).1;
          let m := (unpair p.2).2;
          do
          let x ← Nat.Partrec.Code.lup p.1 ((ofNat (ℕ × Code) p.1.length).1, cf) (Nat.pair z m)
          Nat.casesOn x (some m) fun x =>
              Nat.Partrec.Code.lup p.1 (k', (ofNat (ℕ × Code) p.1.length).2) (Nat.pair z (m + 1)))
      p.1 p.2

Tactic:
have k' := Primrec.snd (α := List (List (Option ℕ)) × ℕ) (β := ℕ)

Result:
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
⊢ Primrec fun p =>
    (fun p k' =>
        Code.recOn (ofNat (ℕ × Code) p.1.length).2 (some 0) (some p.2.succ) (some (unpair p.2).1) (some (unpair p.2).2)
          (fun cf cg x x => do
            let x ← Nat.Partrec.Code.lup p.1 ((ofNat (ℕ × Code) p.1.length).1, cf) p.2
            let y ← Nat.Partrec.Code.lup p.1 ((ofNat (ℕ × Code) p.1.length).1, cg) p.2
            some (Nat.pair x y))
          (fun cf cg x x => do
            let x ← Nat.Partrec.Code.lup p.1 ((ofNat (ℕ × Code) p.1.length).1, cg) p.2
            Nat.Partrec.Code.lup p.1 ((ofNat (ℕ × Code) p.1.length).1, cf) x)
          (fun cf cg x x =>
            let z := (unpair p.2).1;
            Nat.casesOn (unpair p.2).2 (Nat.Partrec.Code.lup p.1 ((ofNat (ℕ × Code) p.1.length).1, cf) z) fun y => do
              let i ← Nat.Partrec.Code.lup p.1 (k', (ofNat (ℕ × Code) p.1.length).2) (Nat.pair z y)
              Nat.Partrec.Code.lup p.1 ((ofNat (ℕ × Code) p.1.length).1, cg) (Nat.pair z (Nat.pair y i)))
          fun cf x =>
          let z := (unpair p.2).1;
          let m := (unpair p.2).2;
          do
          let x ← Nat.Partrec.Code.lup p.1 ((ofNat (ℕ × Code) p.1.length).1, cf) (Nat.pair z m)
          Nat.casesOn x (some m) fun x =>
              Nat.Partrec.Code.lup p.1 (k', (ofNat (ℕ × Code) p.1.length).2) (Nat.pair z (m + 1)))
      p.1 p.2

Proof state:
case hrf
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
z : Primrec fun a => (unpair a.1.1.2).1
m : Primrec fun a => (unpair a.1.1.2).2
h₁ :
  Primrec fun a =>
    Nat.Partrec.Code.lup
      (a.1.1.1, ((ofNat (ℕ × Code) a.1.1.1.length).1, a.2.1), Nat.pair (unpair a.1.1.2).1 (unpair a.1.1.2).2).1
      (a.1.1.1, ((ofNat (ℕ × Code) a.1.1.1.length).1, a.2.1), Nat.pair (unpair a.1.1.2).1 (unpair a.1.1.2).2).2.1
      (a.1.1.1, ((ofNat (ℕ × Code) a.1.1.1.length).1, a.2.1), Nat.pair (unpair a.1.1.2).1 (unpair a.1.1.2).2).2.2
⊢ Primrec fun a =>
    let z := (unpair a.1.1.2).1;
    let m := (unpair a.1.1.2).2;
    do
    let x ← Nat.Partrec.Code.lup a.1.1.1 ((ofNat (ℕ × Code) a.1.1.1.length).1, a.2.1) (Nat.pair z m)
    Nat.casesOn x (some m) fun x =>
        Nat.Partrec.Code.lup a.1.1.1 (a.1.2, (ofNat (ℕ × Code) a.1.1.1.length).2) (Nat.pair z (m + 1))

Tactic:
refine Primrec.option_bind h₁ (?_ : Primrec _)

Result:
case hrf
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
z : Primrec fun a => (unpair a.1.1.2).1
m : Primrec fun a => (unpair a.1.1.2).2
h₁ :
  Primrec fun a =>
    Nat.Partrec.Code.lup
      (a.1.1.1, ((ofNat (ℕ × Code) a.1.1.1.length).1, a.2.1), Nat.pair (unpair a.1.1.2).1 (unpair a.1.1.2).2).1
      (a.1.1.1, ((ofNat (ℕ × Code) a.1.1.1.length).1, a.2.1), Nat.pair (unpair a.1.1.2).1 (unpair a.1.1.2).2).2.1
      (a.1.1.1, ((ofNat (ℕ × Code) a.1.1.1.length).1, a.2.1), Nat.pair (unpair a.1.1.2).1 (unpair a.1.1.2).2).2.2
⊢ Primrec fun p =>
    (fun a x =>
        Nat.casesOn x (some (unpair a.1.1.2).2) fun x =>
          Nat.Partrec.Code.lup a.1.1.1 (a.1.2, (ofNat (ℕ × Code) a.1.1.1.length).2)
            (Nat.pair (unpair a.1.1.2).1 ((unpair a.1.1.2).2 + 1)))
      p.1 p.2

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
n : Primrec fun a => a.1.1.2
cf : Primrec fun a => a.2.1
cg : Primrec fun a => a.2.2.1
z : Primrec fun a => (unpair a.1.1.2).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:
refine
  Primrec.nat_casesOn (Primrec.snd.comp (Primrec.unpair.comp n))
    (hlup.comp <| L.pair <| (k.pair cf).pair z)
    (?_ : Primrec _)

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
cf : Primrec fun a => a.2.1
cg : Primrec fun a => a.2.2.1
z : Primrec fun a => (unpair a.1.1.2).1
⊢ Primrec fun p =>
    (fun a 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 (unpair a.1.1.2).1 y)
        Nat.Partrec.Code.lup a.1.1.1 ((ofNat (ℕ × Code) a.1.1.1.length).1, a.2.2.1)
            (Nat.pair (unpair a.1.1.2).1 (Nat.pair y i)))
      p.1 p.2