Theorem: Nat.Partrec.Code.rec_prim'
File: Mathlib/Computability/PartrecCode.lean

tactic: intros _ _ _ _ F
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
⊢ let PR := fun a cf cg hf hg => pr a (cf, cg, hf, hg);
  let CO := fun a cf cg hf hg => co a (cf, cg, hf, hg);
  let PC := fun a cf cg hf hg => pc a (cf, cg, hf, hg);
  let RF := fun a cf hf => rf a (cf, hf);
  let F := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR a) (CO a) (PC a) (RF a);
  Primrec fun a => F a (c a)

tactic: let G₁ : (α × List σ) × ℕ × ℕ → Option σ := fun p =>
  let a := p.1.1
  let IH := p.1.2
  let n := p.2.1
  let m := p.2.2
  (IH.get? m).bind fun s =>
    (IH.get? m.unpair.1).bind fun s₁ =>
      (IH.get? m.unpair.2).map fun s₂ =>
        cond n.bodd
          (cond n.div2.bodd (rf a (ofNat Code m, s))
            (pc a (ofNat Code m.unpair.1, ofNat Code m.unpair.2, s₁, s₂)))
          (cond n.div2.bodd (co a (ofNat Code m.unpair.1, ofNat Code m.unpair.2, s₁, s₂))
            (pr a (ofNat Code m.unpair.1, ofNat Code m.unpair.2, s₁, s₂)))
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
⊢ Primrec fun a => F a (c a)

tactic: have : Primrec G₁ := by
  refine' option_bind (list_get?.comp (snd.comp fst) (snd.comp snd)) _
  unfold Primrec₂
  refine'
    option_bind
      ((list_get?.comp (snd.comp fst)
        (fst.comp <| Primrec.unpair.comp (snd.comp snd))).comp fst) _
  unfold Primrec₂
  refine'
    option_map
      ((list_get?.comp (snd.comp fst)
        (snd.comp <| Primrec.unpair.comp (snd.comp snd))).comp <| fst.comp fst) _
  have a : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.1.1.1.1) :=
    fst.comp (fst.comp <| fst.comp <| fst.comp fst)
  have n : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.1.1.2.1) :=
    fst.comp (snd.comp <| fst.comp <| fst.comp fst)
  have m : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.1.1.2.2) :=
    snd.comp (snd.comp <| fst.comp <| fst.comp fst)
  have m₁ := fst.comp (Primrec.unpair.comp m)
  have m₂ := snd.comp (Primrec.unpair.comp m)
  have s : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.1.2) :=
    snd.comp (fst.comp fst)
  have s₁ : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.2) :=
    snd.comp fst
  have s₂ : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.2) :=
    snd
  unfold Primrec₂
  exact
    (nat_bodd.comp n).cond
      ((nat_bodd.comp <| nat_div2.comp n).cond (hrf.comp a (((Primrec.ofNat Code).comp m).pair s))
        (hpc.comp a
          (((Primrec.ofNat Code).comp m₁).pair <|
            ((Primrec.ofNat Code).comp m₂).pair <| s₁.pair s₂)))
      (Primrec.cond (nat_bodd.comp <| nat_div2.comp n)
        (hco.comp a
          (((Primrec.ofNat Code).comp m₁).pair <|
            ((Primrec.ofNat Code).comp m₂).pair <| s₁.pair s₂))
        (hpr.comp a
          (((Primrec.ofNat Code).comp m₁).pair <|
            ((Primrec.ofNat Code).comp m₂).pair <| s₁.pair s₂)))
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
⊢ Primrec fun a => F a (c a)

tactic: let G : α → List σ → Option σ := fun a IH =>
  IH.length.casesOn (some (z a)) fun n =>
    n.casesOn (some (s a)) fun n =>
      n.casesOn (some (l a)) fun n =>
        n.casesOn (some (r a)) fun n => G₁ ((a, IH), n, n.div2.div2)
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this : Primrec G₁
⊢ Primrec fun a => F a (c a)

tactic: have : Primrec₂ G := by
  unfold Primrec₂
  refine nat_casesOn
    (list_length.comp snd) (option_some_iff.2 (hz.comp fst)) ?_
  unfold Primrec₂
  refine nat_casesOn snd (option_some_iff.2 (hs.comp (fst.comp fst))) ?_
  unfold Primrec₂
  refine nat_casesOn snd (option_some_iff.2 (hl.comp (fst.comp <| fst.comp fst))) ?_
  unfold Primrec₂
  refine nat_casesOn snd (option_some_iff.2 (hr.comp (fst.comp <| fst.comp <| fst.comp fst))) ?_
  unfold Primrec₂
  exact this.comp <|
    ((fst.pair snd).comp <| fst.comp <| fst.comp <| fst.comp <| fst).pair <|
      snd.pair <| nat_div2.comp <| nat_div2.comp snd
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
⊢ Primrec fun a => F a (c a)

tactic: refine'
  ((nat_strong_rec (fun a n => F a (ofNat Code n)) this.to₂ fun a n => _).comp
    _root_.Primrec.id <| encode_iff.2 hc).of_eq fun a => by simp
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
⊢ Primrec fun a => F a (c a)

tactic: simp (config := { zeta := false })
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
⊢ G (a, List.map ((fun a n => F a (ofNat Code n)) a) (List.range n)).fst
      (a, List.map ((fun a n => F a (ofNat Code n)) a) (List.range n)).snd =
    some ((fun a n => F a (ofNat Code n)) a n)

tactic: simp only []
state_before: case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
⊢ G a (List.map (fun n => F a (ofNat Code n)) (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n)))))) =
    some (F a (ofNat Code (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))

tactic: rw [List.length_map, List.length_range]
state_before: case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
⊢ Nat.rec (some (z a))
      (fun n_1 n_ih =>
        Nat.rec (some (s a))
          (fun n_2 n_ih =>
            Nat.rec (some (l a))
              (fun n_3 n_ih =>
                Nat.rec (some (r a))
                  (fun n_4 n_ih =>
                    Option.bind
                      (List.get?
                        (List.map
                          (fun n =>
                            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
                              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
                              (fun cf hf => rf a (cf, hf)) (ofNat Code n))
                          (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
                        (div2 (div2 n_4)))
                      fun s_1 =>
                      Option.bind
                        (List.get?
                          (List.map
                            (fun n =>
                              rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
                                (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
                                (fun cf hf => rf a (cf, hf)) (ofNat Code n))
                            (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
                          (unpair (div2 (div2 n_4))).fst)
                        fun s₁ =>
                        Option.map
                          (fun s₂ =>
                            bif bodd n_4 then
                              bif bodd (div2 n_4) then rf a (ofNat Code (div2 (div2 n_4)), s_1)
                              else
                                pc a
                                  (ofNat Code (unpair (div2 (div2 n_4))).fst, ofNat Code (unpair (div2 (div2 n_4))).snd,
                                    s₁, s₂)
                            else
                              bif bodd (div2 n_4) then
                                co a
                                  (ofNat Code (unpair (div2 (div2 n_4))).fst, ofNat Code (unpair (div2 (div2 n_4))).snd,
                                    s₁, s₂)
                              else
                                pr a
                                  (ofNat Code (unpair (div2 (div2 n_4))).fst, ofNat Code (unpair (div2 (div2 n_4))).snd,
                                    s₁, s₂))
                          (List.get?
                            (List.map
                              (fun n =>
                                rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
                                  (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
                                  (fun cf hf => rf a (cf, hf)) (ofNat Code n))
                              (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
                            (unpair (div2 (div2 n_4))).snd))
                  n_3)
              n_2)
          n_1)
      (List.length
        (List.map
          (fun n =>
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code n))
          (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))) =
    some
      (rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
        (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf))
        (ofNat Code (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))

tactic: let m := n.div2.div2
state_before: case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
⊢ Nat.rec (some (z a))
      (fun n_1 n_ih =>
        Nat.rec (some (s a))
          (fun n_2 n_ih =>
            Nat.rec (some (l a))
              (fun n_3 n_ih =>
                Nat.rec (some (r a))
                  (fun n_4 n_ih =>
                    Option.bind
                      (List.get?
                        (List.map
                          (fun n =>
                            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
                              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
                              (fun cf hf => rf a (cf, hf)) (ofNat Code n))
                          (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
                        (div2 (div2 n_4)))
                      fun s_1 =>
                      Option.bind
                        (List.get?
                          (List.map
                            (fun n =>
                              rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
                                (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
                                (fun cf hf => rf a (cf, hf)) (ofNat Code n))
                            (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
                          (unpair (div2 (div2 n_4))).fst)
                        fun s₁ =>
                        Option.map
                          (fun s₂ =>
                            bif bodd n_4 then
                              bif bodd (div2 n_4) then rf a (ofNat Code (div2 (div2 n_4)), s_1)
                              else
                                pc a
                                  (ofNat Code (unpair (div2 (div2 n_4))).fst, ofNat Code (unpair (div2 (div2 n_4))).snd,
                                    s₁, s₂)
                            else
                              bif bodd (div2 n_4) then
                                co a
                                  (ofNat Code (unpair (div2 (div2 n_4))).fst, ofNat Code (unpair (div2 (div2 n_4))).snd,
                                    s₁, s₂)
                              else
                                pr a
                                  (ofNat Code (unpair (div2 (div2 n_4))).fst, ofNat Code (unpair (div2 (div2 n_4))).snd,
                                    s₁, s₂))
                          (List.get?
                            (List.map
                              (fun n =>
                                rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
                                  (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
                                  (fun cf hf => rf a (cf, hf)) (ofNat Code n))
                              (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
                            (unpair (div2 (div2 n_4))).snd))
                  n_3)
              n_2)
          n_1)
      (Nat.succ (Nat.succ (Nat.succ (Nat.succ n)))) =
    some
      (rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
        (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf))
        (ofNat Code (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))

tactic: show
  G₁ ((a, (List.range (n + 4)).map fun n => F a (ofNat Code n)), n, m) =
    some (F a (ofNat Code (n + 4)))
state_before: case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
⊢ Nat.rec (some (z a))
      (fun n_1 n_ih =>
        Nat.rec (some (s a))
          (fun n_2 n_ih =>
            Nat.rec (some (l a))
              (fun n_3 n_ih =>
                Nat.rec (some (r a))
                  (fun n_4 n_ih =>
                    Option.bind
                      (List.get?
                        (List.map
                          (fun n =>
                            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
                              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
                              (fun cf hf => rf a (cf, hf)) (ofNat Code n))
                          (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
                        (div2 (div2 n_4)))
                      fun s_1 =>
                      Option.bind
                        (List.get?
                          (List.map
                            (fun n =>
                              rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
                                (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
                                (fun cf hf => rf a (cf, hf)) (ofNat Code n))
                            (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
                          (unpair (div2 (div2 n_4))).fst)
                        fun s₁ =>
                        Option.map
                          (fun s₂ =>
                            bif bodd n_4 then
                              bif bodd (div2 n_4) then rf a (ofNat Code (div2 (div2 n_4)), s_1)
                              else
                                pc a
                                  (ofNat Code (unpair (div2 (div2 n_4))).fst, ofNat Code (unpair (div2 (div2 n_4))).snd,
                                    s₁, s₂)
                            else
                              bif bodd (div2 n_4) then
                                co a
                                  (ofNat Code (unpair (div2 (div2 n_4))).fst, ofNat Code (unpair (div2 (div2 n_4))).snd,
                                    s₁, s₂)
                              else
                                pr a
                                  (ofNat Code (unpair (div2 (div2 n_4))).fst, ofNat Code (unpair (div2 (div2 n_4))).snd,
                                    s₁, s₂))
                          (List.get?
                            (List.map
                              (fun n =>
                                rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
                                  (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
                                  (fun cf hf => rf a (cf, hf)) (ofNat Code n))
                              (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
                            (unpair (div2 (div2 n_4))).snd))
                  n_3)
              n_2)
          n_1)
      (Nat.succ (Nat.succ (Nat.succ (Nat.succ n)))) =
    some
      (rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
        (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf))
        (ofNat Code (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))

tactic: have hm : m < n + 4 := by
  simp [Nat.div2_val]
  exact
    lt_of_le_of_lt (le_trans (Nat.div_le_self _ _) (Nat.div_le_self _ _))
      (Nat.succ_le_succ (Nat.le_add_right _ _))
state_before: case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
⊢ G₁ ((a, List.map (fun n => F a (ofNat Code n)) (List.range (n + 4))), n, m) = some (F a (ofNat Code (n + 4)))

tactic: have m1 : m.unpair.1 < n + 4 := lt_of_le_of_lt m.unpair_left_le hm
state_before: case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
⊢ G₁ ((a, List.map (fun n => F a (ofNat Code n)) (List.range (n + 4))), n, m) = some (F a (ofNat Code (n + 4)))

tactic: have m2 : m.unpair.2 < n + 4 := lt_of_le_of_lt m.unpair_right_le hm
state_before: case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
m1 : (unpair m).fst < n + 4
⊢ G₁ ((a, List.map (fun n => F a (ofNat Code n)) (List.range (n + 4))), n, m) = some (F a (ofNat Code (n + 4)))

tactic: simp [List.get?_map, List.get?_range, hm, m1, m2]
state_before: case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
m1 : (unpair m).fst < n + 4
m2 : (unpair m).snd < n + 4
⊢ G₁ ((a, List.map (fun n => F a (ofNat Code n)) (List.range (n + 4))), n, m) = some (F a (ofNat Code (n + 4)))

tactic: rw [show ofNat Code (n + 4) = ofNatCode (n + 4) from rfl]
state_before: case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
m1 : (unpair m).fst < n + 4
m2 : (unpair m).snd < n + 4
⊢ (bif bodd n then
      bif bodd (div2 n) then
        rf a
          (ofNat Code (div2 (div2 n)),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (div2 (div2 n))))
      else
        pc a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
    else
      bif bodd (div2 n) then
        co a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
      else
        pr a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))) =
    rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
      (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf)) (ofNat Code (n + 4))

tactic: simp [ofNatCode]
state_before: case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
m1 : (unpair m).fst < n + 4
m2 : (unpair m).snd < n + 4
⊢ (bif bodd n then
      bif bodd (div2 n) then
        rf a
          (ofNat Code (div2 (div2 n)),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (div2 (div2 n))))
      else
        pc a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
    else
      bif bodd (div2 n) then
        co a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
      else
        pr a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))) =
    rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
      (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf)) (ofNatCode (n + 4))

tactic: cases n.bodd <;> cases n.div2.bodd <;> rfl
state_before: case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
m1 : (unpair m).fst < n + 4
m2 : (unpair m).snd < n + 4
⊢ (bif bodd n then
      bif bodd (div2 n) then
        rf a
          (ofNat Code (div2 (div2 n)),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (div2 (div2 n))))
      else
        pc a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
    else
      bif bodd (div2 n) then
        co a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
      else
        pr a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))) =
    rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
      (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf))
      (match bodd n, bodd (div2 n) with
      | false, false => pair (ofNatCode (unpair (div2 (div2 n))).fst) (ofNatCode (unpair (div2 (div2 n))).snd)
      | false, true => comp (ofNatCode (unpair (div2 (div2 n))).fst) (ofNatCode (unpair (div2 (div2 n))).snd)
      | true, false => prec (ofNatCode (unpair (div2 (div2 n))).fst) (ofNatCode (unpair (div2 (div2 n))).snd)
      | true, true => rfind' (ofNatCode (div2 (div2 n))))

tactic: refine' option_bind (list_get?.comp (snd.comp fst) (snd.comp snd)) _
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
⊢ Primrec G₁

tactic: unfold Primrec₂
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
⊢ Primrec₂ fun p s =>
    Option.bind (List.get? p.fst.snd (unpair p.snd.snd).fst) fun s₁ =>
      Option.map
        (fun s₂ =>
          bif bodd p.snd.fst then
            bif bodd (div2 p.snd.fst) then rf p.fst.fst (ofNat Code p.snd.snd, s)
            else pc p.fst.fst (ofNat Code (unpair p.snd.snd).fst, ofNat Code (unpair p.snd.snd).snd, s₁, s₂)
          else
            bif bodd (div2 p.snd.fst) then
              co p.fst.fst (ofNat Code (unpair p.snd.snd).fst, ofNat Code (unpair p.snd.snd).snd, s₁, s₂)
            else pr p.fst.fst (ofNat Code (unpair p.snd.snd).fst, ofNat Code (unpair p.snd.snd).snd, s₁, s₂))
        (List.get? p.fst.snd (unpair p.snd.snd).snd)

tactic: refine'
  option_bind
    ((list_get?.comp (snd.comp fst)
      (fst.comp <| Primrec.unpair.comp (snd.comp snd))).comp fst) _
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
⊢ Primrec fun p =>
    (fun p s =>
        Option.bind (List.get? p.fst.snd (unpair p.snd.snd).fst) fun s₁ =>
          Option.map
            (fun s₂ =>
              bif bodd p.snd.fst then
                bif bodd (div2 p.snd.fst) then rf p.fst.fst (ofNat Code p.snd.snd, s)
                else pc p.fst.fst (ofNat Code (unpair p.snd.snd).fst, ofNat Code (unpair p.snd.snd).snd, s₁, s₂)
              else
                bif bodd (div2 p.snd.fst) then
                  co p.fst.fst (ofNat Code (unpair p.snd.snd).fst, ofNat Code (unpair p.snd.snd).snd, s₁, s₂)
                else pr p.fst.fst (ofNat Code (unpair p.snd.snd).fst, ofNat Code (unpair p.snd.snd).snd, s₁, s₂))
            (List.get? p.fst.snd (unpair p.snd.snd).snd))
      p.fst p.snd

tactic: unfold Primrec₂
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
⊢ Primrec₂ fun p s₁ =>
    Option.map
      (fun s₂ =>
        bif bodd p.fst.snd.fst then
          bif bodd (div2 p.fst.snd.fst) then rf p.fst.fst.fst (ofNat Code p.fst.snd.snd, p.snd)
          else pc p.fst.fst.fst (ofNat Code (unpair p.fst.snd.snd).fst, ofNat Code (unpair p.fst.snd.snd).snd, s₁, s₂)
        else
          bif bodd (div2 p.fst.snd.fst) then
            co p.fst.fst.fst (ofNat Code (unpair p.fst.snd.snd).fst, ofNat Code (unpair p.fst.snd.snd).snd, s₁, s₂)
          else pr p.fst.fst.fst (ofNat Code (unpair p.fst.snd.snd).fst, ofNat Code (unpair p.fst.snd.snd).snd, s₁, s₂))
      (List.get? p.fst.fst.snd (unpair p.fst.snd.snd).snd)

tactic: refine'
  option_map
    ((list_get?.comp (snd.comp fst)
      (snd.comp <| Primrec.unpair.comp (snd.comp snd))).comp <| fst.comp fst) _
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
⊢ Primrec fun p =>
    (fun p s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd p.fst.snd.fst then
              bif bodd (div2 p.fst.snd.fst) then rf p.fst.fst.fst (ofNat Code p.fst.snd.snd, p.snd)
              else
                pc p.fst.fst.fst (ofNat Code (unpair p.fst.snd.snd).fst, ofNat Code (unpair p.fst.snd.snd).snd, s₁, s₂)
            else
              bif bodd (div2 p.fst.snd.fst) then
                co p.fst.fst.fst (ofNat Code (unpair p.fst.snd.snd).fst, ofNat Code (unpair p.fst.snd.snd).snd, s₁, s₂)
              else
                pr p.fst.fst.fst (ofNat Code (unpair p.fst.snd.snd).fst, ofNat Code (unpair p.fst.snd.snd).snd, s₁, s₂))
          (List.get? p.fst.fst.snd (unpair p.fst.snd.snd).snd))
      p.fst p.snd

tactic: have a : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.1.1.1.1) :=
  fst.comp (fst.comp <| fst.comp <| fst.comp fst)
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
⊢ Primrec₂ fun p s₂ =>
    bif bodd p.fst.fst.snd.fst then
      bif bodd (div2 p.fst.fst.snd.fst) then rf p.fst.fst.fst.fst (ofNat Code p.fst.fst.snd.snd, p.fst.snd)
      else
        pc p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
    else
      bif bodd (div2 p.fst.fst.snd.fst) then
        co p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
      else
        pr p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)

tactic: have n : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.1.1.2.1) :=
  fst.comp (snd.comp <| fst.comp <| fst.comp fst)
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
a : Primrec fun p => p.fst.fst.fst.fst.fst
⊢ Primrec₂ fun p s₂ =>
    bif bodd p.fst.fst.snd.fst then
      bif bodd (div2 p.fst.fst.snd.fst) then rf p.fst.fst.fst.fst (ofNat Code p.fst.fst.snd.snd, p.fst.snd)
      else
        pc p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
    else
      bif bodd (div2 p.fst.fst.snd.fst) then
        co p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
      else
        pr p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)

tactic: have m : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.1.1.2.2) :=
  snd.comp (snd.comp <| fst.comp <| fst.comp fst)
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
a : Primrec fun p => p.fst.fst.fst.fst.fst
n : Primrec fun p => p.fst.fst.fst.snd.fst
⊢ Primrec₂ fun p s₂ =>
    bif bodd p.fst.fst.snd.fst then
      bif bodd (div2 p.fst.fst.snd.fst) then rf p.fst.fst.fst.fst (ofNat Code p.fst.fst.snd.snd, p.fst.snd)
      else
        pc p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
    else
      bif bodd (div2 p.fst.fst.snd.fst) then
        co p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
      else
        pr p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)

tactic: have m₁ := fst.comp (Primrec.unpair.comp m)
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
a : Primrec fun p => p.fst.fst.fst.fst.fst
n : Primrec fun p => p.fst.fst.fst.snd.fst
m : Primrec fun p => p.fst.fst.fst.snd.snd
⊢ Primrec₂ fun p s₂ =>
    bif bodd p.fst.fst.snd.fst then
      bif bodd (div2 p.fst.fst.snd.fst) then rf p.fst.fst.fst.fst (ofNat Code p.fst.fst.snd.snd, p.fst.snd)
      else
        pc p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
    else
      bif bodd (div2 p.fst.fst.snd.fst) then
        co p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
      else
        pr p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)

tactic: have m₂ := snd.comp (Primrec.unpair.comp m)
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
a : Primrec fun p => p.fst.fst.fst.fst.fst
n : Primrec fun p => p.fst.fst.fst.snd.fst
m : Primrec fun p => p.fst.fst.fst.snd.snd
m₁ : Primrec fun a => (unpair a.fst.fst.fst.snd.snd).fst
⊢ Primrec₂ fun p s₂ =>
    bif bodd p.fst.fst.snd.fst then
      bif bodd (div2 p.fst.fst.snd.fst) then rf p.fst.fst.fst.fst (ofNat Code p.fst.fst.snd.snd, p.fst.snd)
      else
        pc p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
    else
      bif bodd (div2 p.fst.fst.snd.fst) then
        co p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
      else
        pr p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)

tactic: have s : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.1.2) :=
  snd.comp (fst.comp fst)
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
a : Primrec fun p => p.fst.fst.fst.fst.fst
n : Primrec fun p => p.fst.fst.fst.snd.fst
m : Primrec fun p => p.fst.fst.fst.snd.snd
m₁ : Primrec fun a => (unpair a.fst.fst.fst.snd.snd).fst
m₂ : Primrec fun a => (unpair a.fst.fst.fst.snd.snd).snd
⊢ Primrec₂ fun p s₂ =>
    bif bodd p.fst.fst.snd.fst then
      bif bodd (div2 p.fst.fst.snd.fst) then rf p.fst.fst.fst.fst (ofNat Code p.fst.fst.snd.snd, p.fst.snd)
      else
        pc p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
    else
      bif bodd (div2 p.fst.fst.snd.fst) then
        co p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
      else
        pr p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)

tactic: have s₁ : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.2) :=
  snd.comp fst
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s✝ : α → σ
hs : Primrec s✝
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s✝ a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
a : Primrec fun p => p.fst.fst.fst.fst.fst
n : Primrec fun p => p.fst.fst.fst.snd.fst
m : Primrec fun p => p.fst.fst.fst.snd.snd
m₁ : Primrec fun a => (unpair a.fst.fst.fst.snd.snd).fst
m₂ : Primrec fun a => (unpair a.fst.fst.fst.snd.snd).snd
s : Primrec fun p => p.fst.fst.snd
⊢ Primrec₂ fun p s₂ =>
    bif bodd p.fst.fst.snd.fst then
      bif bodd (div2 p.fst.fst.snd.fst) then rf p.fst.fst.fst.fst (ofNat Code p.fst.fst.snd.snd, p.fst.snd)
      else
        pc p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
    else
      bif bodd (div2 p.fst.fst.snd.fst) then
        co p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
      else
        pr p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)

tactic: have s₂ : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.2) :=
  snd
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s✝ : α → σ
hs : Primrec s✝
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s✝ a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
a : Primrec fun p => p.fst.fst.fst.fst.fst
n : Primrec fun p => p.fst.fst.fst.snd.fst
m : Primrec fun p => p.fst.fst.fst.snd.snd
m₁ : Primrec fun a => (unpair a.fst.fst.fst.snd.snd).fst
m₂ : Primrec fun a => (unpair a.fst.fst.fst.snd.snd).snd
s : Primrec fun p => p.fst.fst.snd
s₁ : Primrec fun p => p.fst.snd
⊢ Primrec₂ fun p s₂ =>
    bif bodd p.fst.fst.snd.fst then
      bif bodd (div2 p.fst.fst.snd.fst) then rf p.fst.fst.fst.fst (ofNat Code p.fst.fst.snd.snd, p.fst.snd)
      else
        pc p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
    else
      bif bodd (div2 p.fst.fst.snd.fst) then
        co p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
      else
        pr p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)

tactic: unfold Primrec₂
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s✝ : α → σ
hs : Primrec s✝
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s✝ a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
a : Primrec fun p => p.fst.fst.fst.fst.fst
n : Primrec fun p => p.fst.fst.fst.snd.fst
m : Primrec fun p => p.fst.fst.fst.snd.snd
m₁ : Primrec fun a => (unpair a.fst.fst.fst.snd.snd).fst
m₂ : Primrec fun a => (unpair a.fst.fst.fst.snd.snd).snd
s : Primrec fun p => p.fst.fst.snd
s₁ : Primrec fun p => p.fst.snd
s₂ : Primrec fun p => p.snd
⊢ Primrec₂ fun p s₂ =>
    bif bodd p.fst.fst.snd.fst then
      bif bodd (div2 p.fst.fst.snd.fst) then rf p.fst.fst.fst.fst (ofNat Code p.fst.fst.snd.snd, p.fst.snd)
      else
        pc p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
    else
      bif bodd (div2 p.fst.fst.snd.fst) then
        co p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
      else
        pr p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)

tactic: exact
  (nat_bodd.comp n).cond
    ((nat_bodd.comp <| nat_div2.comp n).cond (hrf.comp a (((Primrec.ofNat Code).comp m).pair s))
      (hpc.comp a
        (((Primrec.ofNat Code).comp m₁).pair <|
          ((Primrec.ofNat Code).comp m₂).pair <| s₁.pair s₂)))
    (Primrec.cond (nat_bodd.comp <| nat_div2.comp n)
      (hco.comp a
        (((Primrec.ofNat Code).comp m₁).pair <|
          ((Primrec.ofNat Code).comp m₂).pair <| s₁.pair s₂))
      (hpr.comp a
        (((Primrec.ofNat Code).comp m₁).pair <|
          ((Primrec.ofNat Code).comp m₂).pair <| s₁.pair s₂)))
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s✝ : α → σ
hs : Primrec s✝
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s✝ a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
a : Primrec fun p => p.fst.fst.fst.fst.fst
n : Primrec fun p => p.fst.fst.fst.snd.fst
m : Primrec fun p => p.fst.fst.fst.snd.snd
m₁ : Primrec fun a => (unpair a.fst.fst.fst.snd.snd).fst
m₂ : Primrec fun a => (unpair a.fst.fst.fst.snd.snd).snd
s : Primrec fun p => p.fst.fst.snd
s₁ : Primrec fun p => p.fst.snd
s₂ : Primrec fun p => p.snd
⊢ Primrec fun p =>
    (fun p s₂ =>
        bif bodd p.fst.fst.snd.fst then
          bif bodd (div2 p.fst.fst.snd.fst) then rf p.fst.fst.fst.fst (ofNat Code p.fst.fst.snd.snd, p.fst.snd)
          else
            pc p.fst.fst.fst.fst
              (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
        else
          bif bodd (div2 p.fst.fst.snd.fst) then
            co p.fst.fst.fst.fst
              (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
          else
            pr p.fst.fst.fst.fst
              (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂))
      p.fst p.snd

tactic: unfold Primrec₂
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
⊢ Primrec₂ G

tactic: refine nat_casesOn
  (list_length.comp snd) (option_some_iff.2 (hz.comp fst)) ?_
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
⊢ Primrec fun p => G p.fst p.snd

tactic: unfold Primrec₂
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
⊢ Primrec₂ fun p n =>
    (fun n =>
        Nat.casesOn n (some (s p.fst)) fun n =>
          Nat.casesOn n (some (l p.fst)) fun n =>
            Nat.casesOn n (some (r p.fst)) fun n => G₁ ((p.fst, p.snd), n, div2 (div2 n)))
      n

tactic: refine nat_casesOn snd (option_some_iff.2 (hs.comp (fst.comp fst))) ?_
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
⊢ Primrec fun p =>
    (fun p n =>
        (fun n =>
            Nat.casesOn n (some (s p.fst)) fun n =>
              Nat.casesOn n (some (l p.fst)) fun n =>
                Nat.casesOn n (some (r p.fst)) fun n => G₁ ((p.fst, p.snd), n, div2 (div2 n)))
          n)
      p.fst p.snd

tactic: unfold Primrec₂
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
⊢ Primrec₂ fun p n =>
    (fun n =>
        Nat.casesOn n (some (l p.fst.fst)) fun n =>
          Nat.casesOn n (some (r p.fst.fst)) fun n => G₁ ((p.fst.fst, p.fst.snd), n, div2 (div2 n)))
      n

tactic: refine nat_casesOn snd (option_some_iff.2 (hl.comp (fst.comp <| fst.comp fst))) ?_
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
⊢ Primrec fun p =>
    (fun p n =>
        (fun n =>
            Nat.casesOn n (some (l p.fst.fst)) fun n =>
              Nat.casesOn n (some (r p.fst.fst)) fun n => G₁ ((p.fst.fst, p.fst.snd), n, div2 (div2 n)))
          n)
      p.fst p.snd

tactic: unfold Primrec₂
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
⊢ Primrec₂ fun p n =>
    (fun n => Nat.casesOn n (some (r p.fst.fst.fst)) fun n => G₁ ((p.fst.fst.fst, p.fst.fst.snd), n, div2 (div2 n))) n

tactic: refine nat_casesOn snd (option_some_iff.2 (hr.comp (fst.comp <| fst.comp <| fst.comp fst))) ?_
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
⊢ Primrec fun p =>
    (fun p n =>
        (fun n => Nat.casesOn n (some (r p.fst.fst.fst)) fun n => G₁ ((p.fst.fst.fst, p.fst.fst.snd), n, div2 (div2 n)))
          n)
      p.fst p.snd

tactic: unfold Primrec₂
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
⊢ Primrec₂ fun p n => (fun n => G₁ ((p.fst.fst.fst.fst, p.fst.fst.fst.snd), n, div2 (div2 n))) n

tactic: exact this.comp <|
  ((fst.pair snd).comp <| fst.comp <| fst.comp <| fst.comp <| fst).pair <|
    snd.pair <| nat_div2.comp <| nat_div2.comp snd
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
⊢ Primrec fun p => (fun p n => (fun n => G₁ ((p.fst.fst.fst.fst, p.fst.fst.fst.snd), n, div2 (div2 n))) n) p.fst p.snd

tactic: simp
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
⊢ F (id a) (ofNat Code (encode (c a))) = F a (c a)

tactic: cases' n with n
state_before: case succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
⊢ G a (List.map (fun n => F a (ofNat Code n)) (List.range (Nat.succ (Nat.succ (Nat.succ n))))) =
    some (F a (ofNat Code (Nat.succ (Nat.succ (Nat.succ n)))))

tactic: simp (config := { zeta := false }) [ofNatCode_eq, ofNatCode]
state_before: case succ.succ.succ.zero
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
⊢ G a (List.map (fun n => F a (ofNat Code n)) (List.range (Nat.succ (Nat.succ (Nat.succ Nat.zero))))) =
    some (F a (ofNat Code (Nat.succ (Nat.succ (Nat.succ Nat.zero)))))

tactic: rfl
state_before: case succ.succ.succ.zero
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
⊢ G a [F a zero, F a succ, F a left] = some (F a (ofNatCode (Nat.succ (Nat.succ (Nat.succ 0)))))

tactic: simp [Nat.div2_val]
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
⊢ m < n + 4

tactic: exact
  lt_of_le_of_lt (le_trans (Nat.div_le_self _ _) (Nat.div_le_self _ _))
    (Nat.succ_le_succ (Nat.le_add_right _ _))
state_before: α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
⊢ n / 2 / 2 < n + 4