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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
⊢ 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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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
  have h₁ := hrf.comp <| a.pair (((Primrec.ofNat Code).comp m).pair s)
  have h₂ := hpc.comp <| a.pair (((Primrec.ofNat Code).comp m₁).pair <|
    ((Primrec.ofNat Code).comp m₂).pair <| s₁.pair s₂)
  have h₃ := hco.comp <| a.pair
    (((Primrec.ofNat Code).comp m₁).pair <| ((Primrec.ofNat Code).comp m₂).pair <| s₁.pair s₂)
  have h₄ := hpr.comp <| a.pair
    (((Primrec.ofNat Code).comp m₁).pair <| ((Primrec.ofNat Code).comp m₂).pair <| s₁.pair s₂)
  unfold Primrec₂
  exact
    (nat_bodd.comp n).cond
      ((nat_bodd.comp <| nat_div2.comp n).cond h₁ h₂)
      (cond (nat_bodd.comp <| nat_div2.comp n) h₃ h₄)
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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) (pr a) (co a) (pc a) (rf a) (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) (pr a) (co a) (pc a) (rf a) (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) (pr a) (co a) (pc a) (rf a) (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) (pr a) (co a) (pc a) (rf a) (ofNat Code n))
          (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))) =
    some
      (rec (z a) (s a) (l a) (r a) (pr a) (co a) (pc a) (rf a)
        (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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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) (pr a) (co a) (pc a) (rf a) (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) (pr a) (co a) (pc a) (rf a) (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) (pr a) (co a) (pc a) (rf a) (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) (pr a) (co a) (pc a) (rf a)
        (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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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) (pr a) (co a) (pc a) (rf a) (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) (pr a) (co a) (pc a) (rf a) (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) (pr a) (co a) (pc a) (rf a) (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) (pr a) (co a) (pc a) (rf a)
        (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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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) (pr a) (co a) (pc a) (rf a) (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) (pr a) (co a) (pc a) (rf a) (ofNat Code (unpair (div2 (div2 n))).fst))
          (rec (z a) (s a) (l a) (r a) (pr a) (co a) (pc a) (rf a) (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) (pr a) (co a) (pc a) (rf a) (ofNat Code (unpair (div2 (div2 n))).fst))
          (rec (z a) (s a) (l a) (r a) (pr a) (co a) (pc a) (rf a) (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) (pr a) (co a) (pc a) (rf a) (ofNat Code (unpair (div2 (div2 n))).fst))
          (rec (z a) (s a) (l a) (r a) (pr a) (co a) (pc a) (rf a) (ofNat Code (unpair (div2 (div2 n))).snd))) =
    rec (z a) (s a) (l a) (r a) (pr a) (co a) (pc a) (rf a) (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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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) (pr a) (co a) (pc a) (rf a) (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) (pr a) (co a) (pc a) (rf a) (ofNat Code (unpair (div2 (div2 n))).fst))
          (rec (z a) (s a) (l a) (r a) (pr a) (co a) (pc a) (rf a) (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) (pr a) (co a) (pc a) (rf a) (ofNat Code (unpair (div2 (div2 n))).fst))
          (rec (z a) (s a) (l a) (r a) (pr a) (co a) (pc a) (rf a) (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) (pr a) (co a) (pc a) (rf a) (ofNat Code (unpair (div2 (div2 n))).fst))
          (rec (z a) (s a) (l a) (r a) (pr a) (co a) (pc a) (rf a) (ofNat Code (unpair (div2 (div2 n))).snd))) =
    rec (z a) (s a) (l a) (r a) (pr a) (co a) (pc a) (rf a) (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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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) (pr a) (co a) (pc a) (rf a) (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) (pr a) (co a) (pc a) (rf a) (ofNat Code (unpair (div2 (div2 n))).fst))
          (rec (z a) (s a) (l a) (r a) (pr a) (co a) (pc a) (rf a) (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) (pr a) (co a) (pc a) (rf a) (ofNat Code (unpair (div2 (div2 n))).fst))
          (rec (z a) (s a) (l a) (r a) (pr a) (co a) (pc a) (rf a) (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) (pr a) (co a) (pc a) (rf a) (ofNat Code (unpair (div2 (div2 n))).fst))
          (rec (z a) (s a) (l a) (r a) (pr a) (co a) (pc a) (rf a) (ofNat Code (unpair (div2 (div2 n))).snd))) =
    rec (z a) (s a) (l a) (r a) (pr a) (co a) (pc a) (rf a)
      (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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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: have h₁ := hrf.comp <| a.pair (((Primrec.ofNat Code).comp m).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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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: have h₂ := hpc.comp <| a.pair (((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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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
h₁ :
  Primrec fun a =>
    rf (a.fst.fst.fst.fst.fst, ofNat Code a.fst.fst.fst.snd.snd, a.fst.fst.snd).fst
      (a.fst.fst.fst.fst.fst, ofNat Code a.fst.fst.fst.snd.snd, a.fst.fst.snd).snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code a.fst.fst.fst.snd.snd, a.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 h₃ := hco.comp <| a.pair
  (((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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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
h₁ :
  Primrec fun a =>
    rf (a.fst.fst.fst.fst.fst, ofNat Code a.fst.fst.fst.snd.snd, a.fst.fst.snd).fst
      (a.fst.fst.fst.fst.fst, ofNat Code a.fst.fst.fst.snd.snd, a.fst.fst.snd).snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code a.fst.fst.fst.snd.snd, a.fst.fst.snd).snd.snd
h₂ :
  Primrec fun a =>
    pc
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
          ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
            ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
              ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
                ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.snd.snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
                ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.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 h₄ := hpr.comp <| a.pair
  (((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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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
h₁ :
  Primrec fun a =>
    rf (a.fst.fst.fst.fst.fst, ofNat Code a.fst.fst.fst.snd.snd, a.fst.fst.snd).fst
      (a.fst.fst.fst.fst.fst, ofNat Code a.fst.fst.fst.snd.snd, a.fst.fst.snd).snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code a.fst.fst.fst.snd.snd, a.fst.fst.snd).snd.snd
h₂ :
  Primrec fun a =>
    pc
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
          ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
            ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
              ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
                ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.snd.snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
                ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.snd.snd.snd
h₃ :
  Primrec fun a =>
    co
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
          ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
            ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
              ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
                ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.snd.snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
                ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.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: 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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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
h₁ :
  Primrec fun a =>
    rf (a.fst.fst.fst.fst.fst, ofNat Code a.fst.fst.fst.snd.snd, a.fst.fst.snd).fst
      (a.fst.fst.fst.fst.fst, ofNat Code a.fst.fst.fst.snd.snd, a.fst.fst.snd).snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code a.fst.fst.fst.snd.snd, a.fst.fst.snd).snd.snd
h₂ :
  Primrec fun a =>
    pc
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
          ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
            ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
              ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
                ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.snd.snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
                ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.snd.snd.snd
h₃ :
  Primrec fun a =>
    co
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
          ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
            ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
              ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
                ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.snd.snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
                ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.snd.snd.snd
h₄ :
  Primrec fun a =>
    pr
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
          ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
            ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
              ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
                ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.snd.snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
                ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.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: exact
  (nat_bodd.comp n).cond
    ((nat_bodd.comp <| nat_div2.comp n).cond h₁ h₂)
    (cond (nat_bodd.comp <| nat_div2.comp n) h₃ h₄)
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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
h₁ :
  Primrec fun a =>
    rf (a.fst.fst.fst.fst.fst, ofNat Code a.fst.fst.fst.snd.snd, a.fst.fst.snd).fst
      (a.fst.fst.fst.fst.fst, ofNat Code a.fst.fst.fst.snd.snd, a.fst.fst.snd).snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code a.fst.fst.fst.snd.snd, a.fst.fst.snd).snd.snd
h₂ :
  Primrec fun a =>
    pc
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
          ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
            ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
              ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
                ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.snd.snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
                ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.snd.snd.snd
h₃ :
  Primrec fun a =>
    co
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
          ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
            ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
              ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
                ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.snd.snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
                ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.snd.snd.snd
h₄ :
  Primrec fun a =>
    pr
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
          ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
            ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
              ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
                ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.snd.snd.fst
      (a.fst.fst.fst.fst.fst, ofNat Code (unpair a.fst.fst.fst.snd.snd).fst,
                ofNat Code (unpair a.fst.fst.fst.snd.snd).snd, a.fst.snd, a.snd).snd.snd.snd.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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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 fun a => pr a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
co : α → Code → Code → σ → σ → σ
hco : Primrec fun a => co a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
pc : α → Code → Code → σ → σ → σ
hpc : Primrec fun a => pc a.fst a.snd.fst a.snd.snd.fst a.snd.snd.snd.fst a.snd.snd.snd.snd
rf : α → Code → σ → σ
hrf : Primrec fun a => rf a.fst a.snd.fst a.snd.snd
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