[GOAL]
f : ℕ →. ℕ
hf : Partrec f
⊢ Partrec₂ fun a m =>
    Part.map (fun x => x + m) (Nat.rfind fun n => (fun m => decide (m = 0)) <$> f (Nat.pair a (n + m)))
[PROOFSTEP]
refine'
  Partrec.map ((@Partrec₂.unpaired' fun a b : ℕ => Nat.rfind fun n => (fun m => m = 0) <$> f (Nat.pair a (n + b))).1 _)
    (Primrec.nat_add.comp Primrec.snd <| Primrec.snd.comp Primrec.fst).to_comp.to₂
[GOAL]
f : ℕ →. ℕ
hf : Partrec f
⊢ Partrec (unpaired fun a b => Nat.rfind fun n => (fun m => decide (m = 0)) <$> f (Nat.pair a (n + b)))
[PROOFSTEP]
have :
  Nat.Partrec
    (fun a =>
      Nat.rfind
        (fun n =>
          (fun m => decide (m = 0)) <$>
            Nat.unpaired (fun a b => f (Nat.pair (Nat.unpair a).1 (b + (Nat.unpair a).2))) (Nat.pair a n))) :=
  rfind
    (Partrec₂.unpaired'.2
      ((Partrec.nat_iff.2 hf).comp
        (Primrec₂.pair.comp (Primrec.fst.comp <| Primrec.unpair.comp Primrec.fst)
            (Primrec.nat_add.comp Primrec.snd (Primrec.snd.comp <| Primrec.unpair.comp Primrec.fst))).to_comp))
[GOAL]
f : ℕ →. ℕ
hf : Partrec f
this :
  Partrec fun a =>
    Nat.rfind fun n =>
      (fun m => decide (m = 0)) <$>
        unpaired (fun a b => f (Nat.pair (unpair a).fst (b + (unpair a).snd))) (Nat.pair a n)
⊢ Partrec (unpaired fun a b => Nat.rfind fun n => (fun m => decide (m = 0)) <$> f (Nat.pair a (n + b)))
[PROOFSTEP]
simp at this 
[GOAL]
f : ℕ →. ℕ
hf : Partrec f
this :
  Partrec fun a =>
    Nat.rfind fun n => Part.map (fun m => decide (m = 0)) (f (Nat.pair (unpair a).fst (n + (unpair a).snd)))
⊢ Partrec (unpaired fun a b => Nat.rfind fun n => (fun m => decide (m = 0)) <$> f (Nat.pair a (n + b)))
[PROOFSTEP]
exact this
[GOAL]
x✝ : Code.const 0 = Code.const 0
⊢ 0 = 0
[PROOFSTEP]
simp
[GOAL]
n₁ n₂ : ℕ
h : Code.const (n₁ + 1) = Code.const (n₂ + 1)
⊢ n₁ + 1 = n₂ + 1
[PROOFSTEP]
dsimp [Nat.add_one, Nat.Partrec.Code.const] at h 
[GOAL]
n₁ n₂ : ℕ
h : comp succ (Code.const n₁) = comp succ (Code.const n₂)
⊢ n₁ + 1 = n₂ + 1
[PROOFSTEP]
injection h with h₁ h₂
[GOAL]
n₁ n₂ : ℕ
h₁ : succ = succ
h₂ : Code.const n₁ = Code.const n₂
⊢ n₁ + 1 = n₂ + 1
[PROOFSTEP]
simp only [const_inj h₂]
[GOAL]
n : ℕ
m : ℕ := div2 (div2 n)
⊢ m < n + 4
[PROOFSTEP]
simp [Nat.div2_val]
[GOAL]
n : ℕ
m : ℕ := div2 (div2 n)
⊢ n / 2 / 2 < n + 4
[PROOFSTEP]
exact lt_of_le_of_lt (le_trans (Nat.div_le_self _ _) (Nat.div_le_self _ _)) (Nat.succ_le_succ (Nat.le_add_right _ _))
[GOAL]
⊢ encodeCode (ofNatCode 0) = 0
[PROOFSTEP]
simp [ofNatCode, encodeCode]
[GOAL]
⊢ encodeCode (ofNatCode 1) = 1
[PROOFSTEP]
simp [ofNatCode, encodeCode]
[GOAL]
⊢ encodeCode (ofNatCode 2) = 2
[PROOFSTEP]
simp [ofNatCode, encodeCode]
[GOAL]
⊢ encodeCode (ofNatCode 3) = 3
[PROOFSTEP]
simp [ofNatCode, encodeCode]
[GOAL]
n : ℕ
⊢ encodeCode (ofNatCode (n + 4)) = n + 4
[PROOFSTEP]
let m := n.div2.div2
[GOAL]
n : ℕ
m : ℕ := div2 (div2 n)
⊢ encodeCode (ofNatCode (n + 4)) = n + 4
[PROOFSTEP]
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 _ _))
[GOAL]
n : ℕ
m : ℕ := div2 (div2 n)
⊢ m < n + 4
[PROOFSTEP]
simp [Nat.div2_val]
[GOAL]
n : ℕ
m : ℕ := div2 (div2 n)
⊢ n / 2 / 2 < n + 4
[PROOFSTEP]
exact lt_of_le_of_lt (le_trans (Nat.div_le_self _ _) (Nat.div_le_self _ _)) (Nat.succ_le_succ (Nat.le_add_right _ _))
[GOAL]
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
⊢ encodeCode (ofNatCode (n + 4)) = n + 4
[PROOFSTEP]
have _m1 : m.unpair.1 < n + 4 := lt_of_le_of_lt m.unpair_left_le hm
[GOAL]
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
_m1 : (unpair m).fst < n + 4
⊢ encodeCode (ofNatCode (n + 4)) = n + 4
[PROOFSTEP]
have _m2 : m.unpair.2 < n + 4 := lt_of_le_of_lt m.unpair_right_le hm
[GOAL]
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
_m1 : (unpair m).fst < n + 4
_m2 : (unpair m).snd < n + 4
⊢ encodeCode (ofNatCode (n + 4)) = n + 4
[PROOFSTEP]
have IH := encode_ofNatCode m
[GOAL]
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
_m1 : (unpair m).fst < n + 4
_m2 : (unpair m).snd < n + 4
IH : encodeCode (ofNatCode m) = m
⊢ encodeCode (ofNatCode (n + 4)) = n + 4
[PROOFSTEP]
have IH1 := encode_ofNatCode m.unpair.1
[GOAL]
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
_m1 : (unpair m).fst < n + 4
_m2 : (unpair m).snd < n + 4
IH : encodeCode (ofNatCode m) = m
IH1 : encodeCode (ofNatCode (unpair m).fst) = (unpair m).fst
⊢ encodeCode (ofNatCode (n + 4)) = n + 4
[PROOFSTEP]
have IH2 := encode_ofNatCode m.unpair.2
[GOAL]
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
_m1 : (unpair m).fst < n + 4
_m2 : (unpair m).snd < n + 4
IH : encodeCode (ofNatCode m) = m
IH1 : encodeCode (ofNatCode (unpair m).fst) = (unpair m).fst
IH2 : encodeCode (ofNatCode (unpair m).snd) = (unpair m).snd
⊢ encodeCode (ofNatCode (n + 4)) = n + 4
[PROOFSTEP]
conv_rhs => rw [← Nat.bit_decomp n, ← Nat.bit_decomp n.div2]
[GOAL]
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
_m1 : (unpair m).fst < n + 4
_m2 : (unpair m).snd < n + 4
IH : encodeCode (ofNatCode m) = m
IH1 : encodeCode (ofNatCode (unpair m).fst) = (unpair m).fst
IH2 : encodeCode (ofNatCode (unpair m).snd) = (unpair m).snd
| n + 4
[PROOFSTEP]
rw [← Nat.bit_decomp n, ← Nat.bit_decomp n.div2]
[GOAL]
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
_m1 : (unpair m).fst < n + 4
_m2 : (unpair m).snd < n + 4
IH : encodeCode (ofNatCode m) = m
IH1 : encodeCode (ofNatCode (unpair m).fst) = (unpair m).fst
IH2 : encodeCode (ofNatCode (unpair m).snd) = (unpair m).snd
| n + 4
[PROOFSTEP]
rw [← Nat.bit_decomp n, ← Nat.bit_decomp n.div2]
[GOAL]
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
_m1 : (unpair m).fst < n + 4
_m2 : (unpair m).snd < n + 4
IH : encodeCode (ofNatCode m) = m
IH1 : encodeCode (ofNatCode (unpair m).fst) = (unpair m).fst
IH2 : encodeCode (ofNatCode (unpair m).snd) = (unpair m).snd
| n + 4
[PROOFSTEP]
rw [← Nat.bit_decomp n, ← Nat.bit_decomp n.div2]
[GOAL]
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
_m1 : (unpair m).fst < n + 4
_m2 : (unpair m).snd < n + 4
IH : encodeCode (ofNatCode m) = m
IH1 : encodeCode (ofNatCode (unpair m).fst) = (unpair m).fst
IH2 : encodeCode (ofNatCode (unpair m).snd) = (unpair m).snd
⊢ encodeCode (ofNatCode (n + 4)) = bit (bodd n) (bit (bodd (div2 n)) (div2 (div2 n))) + 4
[PROOFSTEP]
simp [encodeCode, ofNatCode]
[GOAL]
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
_m1 : (unpair m).fst < n + 4
_m2 : (unpair m).snd < n + 4
IH : encodeCode (ofNatCode m) = m
IH1 : encodeCode (ofNatCode (unpair m).fst) = (unpair m).fst
IH2 : encodeCode (ofNatCode (unpair m).snd) = (unpair m).snd
⊢ encodeCode
      (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)))) =
    bit (bodd n) (bit (bodd (div2 n)) (div2 (div2 n))) + 4
[PROOFSTEP]
cases n.bodd
[GOAL]
case false
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
_m1 : (unpair m).fst < n + 4
_m2 : (unpair m).snd < n + 4
IH : encodeCode (ofNatCode m) = m
IH1 : encodeCode (ofNatCode (unpair m).fst) = (unpair m).fst
IH2 : encodeCode (ofNatCode (unpair m).snd) = (unpair m).snd
⊢ encodeCode
      (match false, 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)))) =
    bit false (bit (bodd (div2 n)) (div2 (div2 n))) + 4
[PROOFSTEP]
cases n.div2.bodd
[GOAL]
case true
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
_m1 : (unpair m).fst < n + 4
_m2 : (unpair m).snd < n + 4
IH : encodeCode (ofNatCode m) = m
IH1 : encodeCode (ofNatCode (unpair m).fst) = (unpair m).fst
IH2 : encodeCode (ofNatCode (unpair m).snd) = (unpair m).snd
⊢ encodeCode
      (match true, 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)))) =
    bit true (bit (bodd (div2 n)) (div2 (div2 n))) + 4
[PROOFSTEP]
cases n.div2.bodd
[GOAL]
case false.false
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
_m1 : (unpair m).fst < n + 4
_m2 : (unpair m).snd < n + 4
IH : encodeCode (ofNatCode m) = m
IH1 : encodeCode (ofNatCode (unpair m).fst) = (unpair m).fst
IH2 : encodeCode (ofNatCode (unpair m).snd) = (unpair m).snd
⊢ encodeCode
      (match false, false 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)))) =
    bit false (bit false (div2 (div2 n))) + 4
[PROOFSTEP]
simp [encodeCode, ofNatCode, IH, IH1, IH2, Nat.bit_val]
[GOAL]
case false.true
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
_m1 : (unpair m).fst < n + 4
_m2 : (unpair m).snd < n + 4
IH : encodeCode (ofNatCode m) = m
IH1 : encodeCode (ofNatCode (unpair m).fst) = (unpair m).fst
IH2 : encodeCode (ofNatCode (unpair m).snd) = (unpair m).snd
⊢ encodeCode
      (match false, true 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)))) =
    bit false (bit true (div2 (div2 n))) + 4
[PROOFSTEP]
simp [encodeCode, ofNatCode, IH, IH1, IH2, Nat.bit_val]
[GOAL]
case true.false
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
_m1 : (unpair m).fst < n + 4
_m2 : (unpair m).snd < n + 4
IH : encodeCode (ofNatCode m) = m
IH1 : encodeCode (ofNatCode (unpair m).fst) = (unpair m).fst
IH2 : encodeCode (ofNatCode (unpair m).snd) = (unpair m).snd
⊢ encodeCode
      (match true, false 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)))) =
    bit true (bit false (div2 (div2 n))) + 4
[PROOFSTEP]
simp [encodeCode, ofNatCode, IH, IH1, IH2, Nat.bit_val]
[GOAL]
case true.true
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
_m1 : (unpair m).fst < n + 4
_m2 : (unpair m).snd < n + 4
IH : encodeCode (ofNatCode m) = m
IH1 : encodeCode (ofNatCode (unpair m).fst) = (unpair m).fst
IH2 : encodeCode (ofNatCode (unpair m).snd) = (unpair m).snd
⊢ encodeCode
      (match true, true 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)))) =
    bit true (bit true (div2 (div2 n))) + 4
[PROOFSTEP]
simp [encodeCode, ofNatCode, IH, IH1, IH2, Nat.bit_val]
[GOAL]
c : Code
⊢ ofNatCode (encodeCode c) = c
[PROOFSTEP]
induction c
[GOAL]
case zero
⊢ ofNatCode (encodeCode zero) = zero
[PROOFSTEP]
try {rfl
}
[GOAL]
case zero
⊢ ofNatCode (encodeCode zero) = zero
[PROOFSTEP]
{rfl
}
[GOAL]
case zero
⊢ ofNatCode (encodeCode zero) = zero
[PROOFSTEP]
rfl
[GOAL]
case succ
⊢ ofNatCode (encodeCode succ) = succ
[PROOFSTEP]
try {rfl
}
[GOAL]
case succ
⊢ ofNatCode (encodeCode succ) = succ
[PROOFSTEP]
{rfl
}
[GOAL]
case succ
⊢ ofNatCode (encodeCode succ) = succ
[PROOFSTEP]
rfl
[GOAL]
case left
⊢ ofNatCode (encodeCode left) = left
[PROOFSTEP]
try {rfl
}
[GOAL]
case left
⊢ ofNatCode (encodeCode left) = left
[PROOFSTEP]
{rfl
}
[GOAL]
case left
⊢ ofNatCode (encodeCode left) = left
[PROOFSTEP]
rfl
[GOAL]
case right
⊢ ofNatCode (encodeCode right) = right
[PROOFSTEP]
try {rfl
}
[GOAL]
case right
⊢ ofNatCode (encodeCode right) = right
[PROOFSTEP]
{rfl
}
[GOAL]
case right
⊢ ofNatCode (encodeCode right) = right
[PROOFSTEP]
rfl
[GOAL]
case pair
a✝¹ a✝ : Code
a_ih✝¹ : ofNatCode (encodeCode a✝¹) = a✝¹
a_ih✝ : ofNatCode (encodeCode a✝) = a✝
⊢ ofNatCode (encodeCode (pair a✝¹ a✝)) = pair a✝¹ a✝
[PROOFSTEP]
try {rfl
}
[GOAL]
case pair
a✝¹ a✝ : Code
a_ih✝¹ : ofNatCode (encodeCode a✝¹) = a✝¹
a_ih✝ : ofNatCode (encodeCode a✝) = a✝
⊢ ofNatCode (encodeCode (pair a✝¹ a✝)) = pair a✝¹ a✝
[PROOFSTEP]
{rfl
}
[GOAL]
case pair
a✝¹ a✝ : Code
a_ih✝¹ : ofNatCode (encodeCode a✝¹) = a✝¹
a_ih✝ : ofNatCode (encodeCode a✝) = a✝
⊢ ofNatCode (encodeCode (pair a✝¹ a✝)) = pair a✝¹ a✝
[PROOFSTEP]
rfl
[GOAL]
case comp
a✝¹ a✝ : Code
a_ih✝¹ : ofNatCode (encodeCode a✝¹) = a✝¹
a_ih✝ : ofNatCode (encodeCode a✝) = a✝
⊢ ofNatCode (encodeCode (comp a✝¹ a✝)) = comp a✝¹ a✝
[PROOFSTEP]
try {rfl
}
[GOAL]
case comp
a✝¹ a✝ : Code
a_ih✝¹ : ofNatCode (encodeCode a✝¹) = a✝¹
a_ih✝ : ofNatCode (encodeCode a✝) = a✝
⊢ ofNatCode (encodeCode (comp a✝¹ a✝)) = comp a✝¹ a✝
[PROOFSTEP]
{rfl
}
[GOAL]
case comp
a✝¹ a✝ : Code
a_ih✝¹ : ofNatCode (encodeCode a✝¹) = a✝¹
a_ih✝ : ofNatCode (encodeCode a✝) = a✝
⊢ ofNatCode (encodeCode (comp a✝¹ a✝)) = comp a✝¹ a✝
[PROOFSTEP]
rfl
[GOAL]
case prec
a✝¹ a✝ : Code
a_ih✝¹ : ofNatCode (encodeCode a✝¹) = a✝¹
a_ih✝ : ofNatCode (encodeCode a✝) = a✝
⊢ ofNatCode (encodeCode (prec a✝¹ a✝)) = prec a✝¹ a✝
[PROOFSTEP]
try {rfl
}
[GOAL]
case prec
a✝¹ a✝ : Code
a_ih✝¹ : ofNatCode (encodeCode a✝¹) = a✝¹
a_ih✝ : ofNatCode (encodeCode a✝) = a✝
⊢ ofNatCode (encodeCode (prec a✝¹ a✝)) = prec a✝¹ a✝
[PROOFSTEP]
{rfl
}
[GOAL]
case prec
a✝¹ a✝ : Code
a_ih✝¹ : ofNatCode (encodeCode a✝¹) = a✝¹
a_ih✝ : ofNatCode (encodeCode a✝) = a✝
⊢ ofNatCode (encodeCode (prec a✝¹ a✝)) = prec a✝¹ a✝
[PROOFSTEP]
rfl
[GOAL]
case rfind'
a✝ : Code
a_ih✝ : ofNatCode (encodeCode a✝) = a✝
⊢ ofNatCode (encodeCode (rfind' a✝)) = rfind' a✝
[PROOFSTEP]
try {rfl
}
[GOAL]
case rfind'
a✝ : Code
a_ih✝ : ofNatCode (encodeCode a✝) = a✝
⊢ ofNatCode (encodeCode (rfind' a✝)) = rfind' a✝
[PROOFSTEP]
{rfl
}
[GOAL]
case rfind'
a✝ : Code
a_ih✝ : ofNatCode (encodeCode a✝) = a✝
⊢ ofNatCode (encodeCode (rfind' a✝)) = rfind' a✝
[PROOFSTEP]
rfl
[GOAL]
case pair
a✝¹ a✝ : Code
a_ih✝¹ : ofNatCode (encodeCode a✝¹) = a✝¹
a_ih✝ : ofNatCode (encodeCode a✝) = a✝
⊢ ofNatCode (encodeCode (pair a✝¹ a✝)) = pair a✝¹ a✝
[PROOFSTEP]
simp [encodeCode, ofNatCode, Nat.div2_val, *]
[GOAL]
case comp
a✝¹ a✝ : Code
a_ih✝¹ : ofNatCode (encodeCode a✝¹) = a✝¹
a_ih✝ : ofNatCode (encodeCode a✝) = a✝
⊢ ofNatCode (encodeCode (comp a✝¹ a✝)) = comp a✝¹ a✝
[PROOFSTEP]
simp [encodeCode, ofNatCode, Nat.div2_val, *]
[GOAL]
case prec
a✝¹ a✝ : Code
a_ih✝¹ : ofNatCode (encodeCode a✝¹) = a✝¹
a_ih✝ : ofNatCode (encodeCode a✝) = a✝
⊢ ofNatCode (encodeCode (prec a✝¹ a✝)) = prec a✝¹ a✝
[PROOFSTEP]
simp [encodeCode, ofNatCode, Nat.div2_val, *]
[GOAL]
case rfind'
a✝ : Code
a_ih✝ : ofNatCode (encodeCode a✝) = a✝
⊢ ofNatCode (encodeCode (rfind' a✝)) = rfind' a✝
[PROOFSTEP]
simp [encodeCode, ofNatCode, Nat.div2_val, *]
[GOAL]
cf cg : Code
⊢ encode cf < encode (pair cf cg) ∧ encode cg < encode (pair cf cg)
[PROOFSTEP]
simp [encodeCode_eq, encodeCode]
[GOAL]
cf cg : Code
⊢ encodeCode cf < 2 * (2 * Nat.pair (encodeCode cf) (encodeCode cg)) + 4 ∧
    encodeCode cg < 2 * (2 * Nat.pair (encodeCode cf) (encodeCode cg)) + 4
[PROOFSTEP]
have := Nat.mul_le_mul_right (Nat.pair cf.encodeCode cg.encodeCode) (by decide : 1 ≤ 2 * 2)
[GOAL]
cf cg : Code
⊢ 1 ≤ 2 * 2
[PROOFSTEP]
decide
[GOAL]
cf cg : Code
this : 1 * Nat.pair (encodeCode cf) (encodeCode cg) ≤ 2 * 2 * Nat.pair (encodeCode cf) (encodeCode cg)
⊢ encodeCode cf < 2 * (2 * Nat.pair (encodeCode cf) (encodeCode cg)) + 4 ∧
    encodeCode cg < 2 * (2 * Nat.pair (encodeCode cf) (encodeCode cg)) + 4
[PROOFSTEP]
rw [one_mul, mul_assoc] at this 
[GOAL]
cf cg : Code
this : Nat.pair (encodeCode cf) (encodeCode cg) ≤ 2 * (2 * Nat.pair (encodeCode cf) (encodeCode cg))
⊢ encodeCode cf < 2 * (2 * Nat.pair (encodeCode cf) (encodeCode cg)) + 4 ∧
    encodeCode cg < 2 * (2 * Nat.pair (encodeCode cf) (encodeCode cg)) + 4
[PROOFSTEP]
have := lt_of_le_of_lt this (lt_add_of_pos_right _ (by decide : 0 < 4))
[GOAL]
cf cg : Code
this : Nat.pair (encodeCode cf) (encodeCode cg) ≤ 2 * (2 * Nat.pair (encodeCode cf) (encodeCode cg))
⊢ 0 < 4
[PROOFSTEP]
decide
[GOAL]
cf cg : Code
this✝ : Nat.pair (encodeCode cf) (encodeCode cg) ≤ 2 * (2 * Nat.pair (encodeCode cf) (encodeCode cg))
this : Nat.pair (encodeCode cf) (encodeCode cg) < 2 * (2 * Nat.pair (encodeCode cf) (encodeCode cg)) + 4
⊢ encodeCode cf < 2 * (2 * Nat.pair (encodeCode cf) (encodeCode cg)) + 4 ∧
    encodeCode cg < 2 * (2 * Nat.pair (encodeCode cf) (encodeCode cg)) + 4
[PROOFSTEP]
exact ⟨lt_of_le_of_lt (Nat.left_le_pair _ _) this, lt_of_le_of_lt (Nat.right_le_pair _ _) this⟩
[GOAL]
cf cg : Code
⊢ encode cf < encode (comp cf cg) ∧ encode cg < encode (comp cf cg)
[PROOFSTEP]
suffices
[GOAL]
cf cg : Code
this : ?m.354291
⊢ encode cf < encode (comp cf cg) ∧ encode cg < encode (comp cf cg)
case this cf cg : Code ⊢ ?m.354291
[PROOFSTEP]
exact (encode_lt_pair cf cg).imp (fun h => lt_trans h this) fun h => lt_trans h this
[GOAL]
case this
cf cg : Code
⊢ encode (pair cf cg) < encode (comp cf cg)
[PROOFSTEP]
change _
[GOAL]
case this
cf cg : Code
⊢ encode (pair cf cg) < encode (comp cf cg)
[PROOFSTEP]
simp [encodeCode_eq, encodeCode]
[GOAL]
cf cg : Code
⊢ encode cf < encode (prec cf cg) ∧ encode cg < encode (prec cf cg)
[PROOFSTEP]
suffices
[GOAL]
cf cg : Code
this : ?m.356899
⊢ encode cf < encode (prec cf cg) ∧ encode cg < encode (prec cf cg)
case this cf cg : Code ⊢ ?m.356899
[PROOFSTEP]
exact (encode_lt_pair cf cg).imp (fun h => lt_trans h this) fun h => lt_trans h this
[GOAL]
case this
cf cg : Code
⊢ encode (pair cf cg) < encode (prec cf cg)
[PROOFSTEP]
change _
[GOAL]
case this
cf cg : Code
⊢ encode (pair cf cg) < encode (prec cf cg)
[PROOFSTEP]
simp [encodeCode_eq, encodeCode]
[GOAL]
cf : Code
⊢ encode cf < encode (rfind' cf)
[PROOFSTEP]
simp [encodeCode_eq, encodeCode]
[GOAL]
cf : Code
⊢ encodeCode cf < 2 * (2 * encodeCode cf + 1) + 1 + 4
[PROOFSTEP]
have := Nat.mul_le_mul_right cf.encodeCode (by decide : 1 ≤ 2 * 2)
[GOAL]
cf : Code
⊢ 1 ≤ 2 * 2
[PROOFSTEP]
decide
[GOAL]
cf : Code
this : 1 * encodeCode cf ≤ 2 * 2 * encodeCode cf
⊢ encodeCode cf < 2 * (2 * encodeCode cf + 1) + 1 + 4
[PROOFSTEP]
rw [one_mul, mul_assoc] at this 
[GOAL]
cf : Code
this : encodeCode cf ≤ 2 * (2 * encodeCode cf)
⊢ encodeCode cf < 2 * (2 * encodeCode cf + 1) + 1 + 4
[PROOFSTEP]
refine' lt_of_le_of_lt (le_trans this _) (lt_add_of_pos_right _ (by decide : 0 < 4))
[GOAL]
cf : Code
this : encodeCode cf ≤ 2 * (2 * encodeCode cf)
⊢ 0 < 4
[PROOFSTEP]
decide
[GOAL]
cf : Code
this : encodeCode cf ≤ 2 * (2 * encodeCode cf)
⊢ 2 * (2 * encodeCode cf) ≤ 2 * (2 * encodeCode cf + 1) + 1
[PROOFSTEP]
exact
  le_of_lt
    (Nat.lt_succ_of_le <| Nat.mul_le_mul_left _ <| le_of_lt <| Nat.lt_succ_of_le <| Nat.mul_le_mul_left _ <| le_rfl)
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
⊢ let PR := fun a cf cg hf hg => pr a (cf, cg, hf, hg);
  let CO := fun a cf cg hf hg => co a (cf, cg, hf, hg);
  let PC := fun a cf cg hf hg => pc a (cf, cg, hf, hg);
  let RF := fun a cf hf => rf a (cf, hf);
  let F := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR a) (CO a) (PC a) (RF a);
  Primrec fun a => F a (c a)
[PROOFSTEP]
intros _ _ _ _ F
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
⊢ Primrec fun a => F a (c a)
[PROOFSTEP]
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₂)))
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
⊢ Primrec fun a => F a (c a)
[PROOFSTEP]
have : Primrec G₁ := by
  refine' option_bind (list_get?.comp (snd.comp fst) (snd.comp snd)) _
  unfold Primrec₂
  refine' option_bind ((list_get?.comp (snd.comp fst) (fst.comp <| Primrec.unpair.comp (snd.comp snd))).comp fst) _
  unfold Primrec₂
  refine'
    option_map ((list_get?.comp (snd.comp fst) (snd.comp <| Primrec.unpair.comp (snd.comp snd))).comp <| fst.comp fst) _
  have a : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.1.1.1.1) :=
    fst.comp (fst.comp <| fst.comp <| fst.comp fst)
  have n : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.1.1.2.1) :=
    fst.comp (snd.comp <| fst.comp <| fst.comp fst)
  have m : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.1.1.2.2) :=
    snd.comp (snd.comp <| fst.comp <| fst.comp fst)
  have m₁ := fst.comp (Primrec.unpair.comp m)
  have m₂ := snd.comp (Primrec.unpair.comp m)
  have s : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.1.2) := snd.comp (fst.comp fst)
  have s₁ : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.2) := snd.comp fst
  have s₂ : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.2) := snd
  unfold Primrec₂
  exact
    (nat_bodd.comp n).cond
      ((nat_bodd.comp <| nat_div2.comp n).cond (hrf.comp a (((Primrec.ofNat Code).comp m).pair s))
        (hpc.comp a (((Primrec.ofNat Code).comp m₁).pair <| ((Primrec.ofNat Code).comp m₂).pair <| s₁.pair s₂)))
      (Primrec.cond (nat_bodd.comp <| nat_div2.comp n)
        (hco.comp a (((Primrec.ofNat Code).comp m₁).pair <| ((Primrec.ofNat Code).comp m₂).pair <| s₁.pair s₂))
        (hpr.comp a (((Primrec.ofNat Code).comp m₁).pair <| ((Primrec.ofNat Code).comp m₂).pair <| s₁.pair s₂)))
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
⊢ Primrec G₁
[PROOFSTEP]
refine' option_bind (list_get?.comp (snd.comp fst) (snd.comp snd)) _
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
⊢ Primrec₂ fun p s =>
    Option.bind (List.get? p.fst.snd (unpair p.snd.snd).fst) fun s₁ =>
      Option.map
        (fun s₂ =>
          bif bodd p.snd.fst then
            bif bodd (div2 p.snd.fst) then rf p.fst.fst (ofNat Code p.snd.snd, s)
            else pc p.fst.fst (ofNat Code (unpair p.snd.snd).fst, ofNat Code (unpair p.snd.snd).snd, s₁, s₂)
          else
            bif bodd (div2 p.snd.fst) then
              co p.fst.fst (ofNat Code (unpair p.snd.snd).fst, ofNat Code (unpair p.snd.snd).snd, s₁, s₂)
            else pr p.fst.fst (ofNat Code (unpair p.snd.snd).fst, ofNat Code (unpair p.snd.snd).snd, s₁, s₂))
        (List.get? p.fst.snd (unpair p.snd.snd).snd)
[PROOFSTEP]
unfold Primrec₂
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
⊢ Primrec fun p =>
    (fun p s =>
        Option.bind (List.get? p.fst.snd (unpair p.snd.snd).fst) fun s₁ =>
          Option.map
            (fun s₂ =>
              bif bodd p.snd.fst then
                bif bodd (div2 p.snd.fst) then rf p.fst.fst (ofNat Code p.snd.snd, s)
                else pc p.fst.fst (ofNat Code (unpair p.snd.snd).fst, ofNat Code (unpair p.snd.snd).snd, s₁, s₂)
              else
                bif bodd (div2 p.snd.fst) then
                  co p.fst.fst (ofNat Code (unpair p.snd.snd).fst, ofNat Code (unpair p.snd.snd).snd, s₁, s₂)
                else pr p.fst.fst (ofNat Code (unpair p.snd.snd).fst, ofNat Code (unpair p.snd.snd).snd, s₁, s₂))
            (List.get? p.fst.snd (unpair p.snd.snd).snd))
      p.fst p.snd
[PROOFSTEP]
refine' option_bind ((list_get?.comp (snd.comp fst) (fst.comp <| Primrec.unpair.comp (snd.comp snd))).comp fst) _
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
⊢ Primrec₂ fun p s₁ =>
    Option.map
      (fun s₂ =>
        bif bodd p.fst.snd.fst then
          bif bodd (div2 p.fst.snd.fst) then rf p.fst.fst.fst (ofNat Code p.fst.snd.snd, p.snd)
          else pc p.fst.fst.fst (ofNat Code (unpair p.fst.snd.snd).fst, ofNat Code (unpair p.fst.snd.snd).snd, s₁, s₂)
        else
          bif bodd (div2 p.fst.snd.fst) then
            co p.fst.fst.fst (ofNat Code (unpair p.fst.snd.snd).fst, ofNat Code (unpair p.fst.snd.snd).snd, s₁, s₂)
          else pr p.fst.fst.fst (ofNat Code (unpair p.fst.snd.snd).fst, ofNat Code (unpair p.fst.snd.snd).snd, s₁, s₂))
      (List.get? p.fst.fst.snd (unpair p.fst.snd.snd).snd)
[PROOFSTEP]
unfold Primrec₂
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
⊢ Primrec fun p =>
    (fun p s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd p.fst.snd.fst then
              bif bodd (div2 p.fst.snd.fst) then rf p.fst.fst.fst (ofNat Code p.fst.snd.snd, p.snd)
              else
                pc p.fst.fst.fst (ofNat Code (unpair p.fst.snd.snd).fst, ofNat Code (unpair p.fst.snd.snd).snd, s₁, s₂)
            else
              bif bodd (div2 p.fst.snd.fst) then
                co p.fst.fst.fst (ofNat Code (unpair p.fst.snd.snd).fst, ofNat Code (unpair p.fst.snd.snd).snd, s₁, s₂)
              else
                pr p.fst.fst.fst (ofNat Code (unpair p.fst.snd.snd).fst, ofNat Code (unpair p.fst.snd.snd).snd, s₁, s₂))
          (List.get? p.fst.fst.snd (unpair p.fst.snd.snd).snd))
      p.fst p.snd
[PROOFSTEP]
refine'
  option_map ((list_get?.comp (snd.comp fst) (snd.comp <| Primrec.unpair.comp (snd.comp snd))).comp <| fst.comp fst) _
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
⊢ Primrec₂ fun p s₂ =>
    bif bodd p.fst.fst.snd.fst then
      bif bodd (div2 p.fst.fst.snd.fst) then rf p.fst.fst.fst.fst (ofNat Code p.fst.fst.snd.snd, p.fst.snd)
      else
        pc p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
    else
      bif bodd (div2 p.fst.fst.snd.fst) then
        co p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
      else
        pr p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
[PROOFSTEP]
have a : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.1.1.1.1) :=
  fst.comp (fst.comp <| fst.comp <| fst.comp fst)
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
a : Primrec fun p => p.fst.fst.fst.fst.fst
⊢ Primrec₂ fun p s₂ =>
    bif bodd p.fst.fst.snd.fst then
      bif bodd (div2 p.fst.fst.snd.fst) then rf p.fst.fst.fst.fst (ofNat Code p.fst.fst.snd.snd, p.fst.snd)
      else
        pc p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
    else
      bif bodd (div2 p.fst.fst.snd.fst) then
        co p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
      else
        pr p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
[PROOFSTEP]
have n : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.1.1.2.1) :=
  fst.comp (snd.comp <| fst.comp <| fst.comp fst)
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
a : Primrec fun p => p.fst.fst.fst.fst.fst
n : Primrec fun p => p.fst.fst.fst.snd.fst
⊢ Primrec₂ fun p s₂ =>
    bif bodd p.fst.fst.snd.fst then
      bif bodd (div2 p.fst.fst.snd.fst) then rf p.fst.fst.fst.fst (ofNat Code p.fst.fst.snd.snd, p.fst.snd)
      else
        pc p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
    else
      bif bodd (div2 p.fst.fst.snd.fst) then
        co p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
      else
        pr p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
[PROOFSTEP]
have m : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.1.1.2.2) :=
  snd.comp (snd.comp <| fst.comp <| fst.comp fst)
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
a : Primrec fun p => p.fst.fst.fst.fst.fst
n : Primrec fun p => p.fst.fst.fst.snd.fst
m : Primrec fun p => p.fst.fst.fst.snd.snd
⊢ Primrec₂ fun p s₂ =>
    bif bodd p.fst.fst.snd.fst then
      bif bodd (div2 p.fst.fst.snd.fst) then rf p.fst.fst.fst.fst (ofNat Code p.fst.fst.snd.snd, p.fst.snd)
      else
        pc p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
    else
      bif bodd (div2 p.fst.fst.snd.fst) then
        co p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
      else
        pr p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
[PROOFSTEP]
have m₁ := fst.comp (Primrec.unpair.comp m)
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
a : Primrec fun p => p.fst.fst.fst.fst.fst
n : Primrec fun p => p.fst.fst.fst.snd.fst
m : Primrec fun p => p.fst.fst.fst.snd.snd
m₁ : Primrec fun a => (unpair a.fst.fst.fst.snd.snd).fst
⊢ Primrec₂ fun p s₂ =>
    bif bodd p.fst.fst.snd.fst then
      bif bodd (div2 p.fst.fst.snd.fst) then rf p.fst.fst.fst.fst (ofNat Code p.fst.fst.snd.snd, p.fst.snd)
      else
        pc p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
    else
      bif bodd (div2 p.fst.fst.snd.fst) then
        co p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
      else
        pr p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
[PROOFSTEP]
have m₂ := snd.comp (Primrec.unpair.comp m)
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
a : Primrec fun p => p.fst.fst.fst.fst.fst
n : Primrec fun p => p.fst.fst.fst.snd.fst
m : Primrec fun p => p.fst.fst.fst.snd.snd
m₁ : Primrec fun a => (unpair a.fst.fst.fst.snd.snd).fst
m₂ : Primrec fun a => (unpair a.fst.fst.fst.snd.snd).snd
⊢ Primrec₂ fun p s₂ =>
    bif bodd p.fst.fst.snd.fst then
      bif bodd (div2 p.fst.fst.snd.fst) then rf p.fst.fst.fst.fst (ofNat Code p.fst.fst.snd.snd, p.fst.snd)
      else
        pc p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
    else
      bif bodd (div2 p.fst.fst.snd.fst) then
        co p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
      else
        pr p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
[PROOFSTEP]
have s : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.1.2) := snd.comp (fst.comp fst)
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s✝ : α → σ
hs : Primrec s✝
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s✝ a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
a : Primrec fun p => p.fst.fst.fst.fst.fst
n : Primrec fun p => p.fst.fst.fst.snd.fst
m : Primrec fun p => p.fst.fst.fst.snd.snd
m₁ : Primrec fun a => (unpair a.fst.fst.fst.snd.snd).fst
m₂ : Primrec fun a => (unpair a.fst.fst.fst.snd.snd).snd
s : Primrec fun p => p.fst.fst.snd
⊢ Primrec₂ fun p s₂ =>
    bif bodd p.fst.fst.snd.fst then
      bif bodd (div2 p.fst.fst.snd.fst) then rf p.fst.fst.fst.fst (ofNat Code p.fst.fst.snd.snd, p.fst.snd)
      else
        pc p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
    else
      bif bodd (div2 p.fst.fst.snd.fst) then
        co p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
      else
        pr p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
[PROOFSTEP]
have s₁ : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.2) := snd.comp fst
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s✝ : α → σ
hs : Primrec s✝
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s✝ a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
a : Primrec fun p => p.fst.fst.fst.fst.fst
n : Primrec fun p => p.fst.fst.fst.snd.fst
m : Primrec fun p => p.fst.fst.fst.snd.snd
m₁ : Primrec fun a => (unpair a.fst.fst.fst.snd.snd).fst
m₂ : Primrec fun a => (unpair a.fst.fst.fst.snd.snd).snd
s : Primrec fun p => p.fst.fst.snd
s₁ : Primrec fun p => p.fst.snd
⊢ Primrec₂ fun p s₂ =>
    bif bodd p.fst.fst.snd.fst then
      bif bodd (div2 p.fst.fst.snd.fst) then rf p.fst.fst.fst.fst (ofNat Code p.fst.fst.snd.snd, p.fst.snd)
      else
        pc p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
    else
      bif bodd (div2 p.fst.fst.snd.fst) then
        co p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
      else
        pr p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
[PROOFSTEP]
have s₂ : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.2) := snd
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s✝ : α → σ
hs : Primrec s✝
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s✝ a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
a : Primrec fun p => p.fst.fst.fst.fst.fst
n : Primrec fun p => p.fst.fst.fst.snd.fst
m : Primrec fun p => p.fst.fst.fst.snd.snd
m₁ : Primrec fun a => (unpair a.fst.fst.fst.snd.snd).fst
m₂ : Primrec fun a => (unpair a.fst.fst.fst.snd.snd).snd
s : Primrec fun p => p.fst.fst.snd
s₁ : Primrec fun p => p.fst.snd
s₂ : Primrec fun p => p.snd
⊢ Primrec₂ fun p s₂ =>
    bif bodd p.fst.fst.snd.fst then
      bif bodd (div2 p.fst.fst.snd.fst) then rf p.fst.fst.fst.fst (ofNat Code p.fst.fst.snd.snd, p.fst.snd)
      else
        pc p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
    else
      bif bodd (div2 p.fst.fst.snd.fst) then
        co p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
      else
        pr p.fst.fst.fst.fst
          (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
[PROOFSTEP]
unfold Primrec₂
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s✝ : α → σ
hs : Primrec s✝
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s✝ a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
a : Primrec fun p => p.fst.fst.fst.fst.fst
n : Primrec fun p => p.fst.fst.fst.snd.fst
m : Primrec fun p => p.fst.fst.fst.snd.snd
m₁ : Primrec fun a => (unpair a.fst.fst.fst.snd.snd).fst
m₂ : Primrec fun a => (unpair a.fst.fst.fst.snd.snd).snd
s : Primrec fun p => p.fst.fst.snd
s₁ : Primrec fun p => p.fst.snd
s₂ : Primrec fun p => p.snd
⊢ Primrec fun p =>
    (fun p s₂ =>
        bif bodd p.fst.fst.snd.fst then
          bif bodd (div2 p.fst.fst.snd.fst) then rf p.fst.fst.fst.fst (ofNat Code p.fst.fst.snd.snd, p.fst.snd)
          else
            pc p.fst.fst.fst.fst
              (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
        else
          bif bodd (div2 p.fst.fst.snd.fst) then
            co p.fst.fst.fst.fst
              (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂)
          else
            pr p.fst.fst.fst.fst
              (ofNat Code (unpair p.fst.fst.snd.snd).fst, ofNat Code (unpair p.fst.fst.snd.snd).snd, p.snd, s₂))
      p.fst p.snd
[PROOFSTEP]
exact
  (nat_bodd.comp n).cond
    ((nat_bodd.comp <| nat_div2.comp n).cond (hrf.comp a (((Primrec.ofNat Code).comp m).pair s))
      (hpc.comp a (((Primrec.ofNat Code).comp m₁).pair <| ((Primrec.ofNat Code).comp m₂).pair <| s₁.pair s₂)))
    (Primrec.cond (nat_bodd.comp <| nat_div2.comp n)
      (hco.comp a (((Primrec.ofNat Code).comp m₁).pair <| ((Primrec.ofNat Code).comp m₂).pair <| s₁.pair s₂))
      (hpr.comp a (((Primrec.ofNat Code).comp m₁).pair <| ((Primrec.ofNat Code).comp m₂).pair <| s₁.pair s₂)))
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this : Primrec G₁
⊢ Primrec fun a => F a (c a)
[PROOFSTEP]
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)
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
⊢ Primrec fun a => F a (c a)
[PROOFSTEP]
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
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
⊢ Primrec₂ G
[PROOFSTEP]
unfold Primrec₂
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
⊢ Primrec fun p => G p.fst p.snd
[PROOFSTEP]
refine nat_casesOn (list_length.comp snd) (option_some_iff.2 (hz.comp fst)) ?_
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
⊢ Primrec₂ fun p n =>
    (fun n =>
        Nat.casesOn n (some (s p.fst)) fun n =>
          Nat.casesOn n (some (l p.fst)) fun n =>
            Nat.casesOn n (some (r p.fst)) fun n => G₁ ((p.fst, p.snd), n, div2 (div2 n)))
      n
[PROOFSTEP]
unfold Primrec₂
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
⊢ Primrec fun p =>
    (fun p n =>
        (fun n =>
            Nat.casesOn n (some (s p.fst)) fun n =>
              Nat.casesOn n (some (l p.fst)) fun n =>
                Nat.casesOn n (some (r p.fst)) fun n => G₁ ((p.fst, p.snd), n, div2 (div2 n)))
          n)
      p.fst p.snd
[PROOFSTEP]
refine nat_casesOn snd (option_some_iff.2 (hs.comp (fst.comp fst))) ?_
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
⊢ Primrec₂ fun p n =>
    (fun n =>
        Nat.casesOn n (some (l p.fst.fst)) fun n =>
          Nat.casesOn n (some (r p.fst.fst)) fun n => G₁ ((p.fst.fst, p.fst.snd), n, div2 (div2 n)))
      n
[PROOFSTEP]
unfold Primrec₂
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
⊢ Primrec fun p =>
    (fun p n =>
        (fun n =>
            Nat.casesOn n (some (l p.fst.fst)) fun n =>
              Nat.casesOn n (some (r p.fst.fst)) fun n => G₁ ((p.fst.fst, p.fst.snd), n, div2 (div2 n)))
          n)
      p.fst p.snd
[PROOFSTEP]
refine nat_casesOn snd (option_some_iff.2 (hl.comp (fst.comp <| fst.comp fst))) ?_
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
⊢ Primrec₂ fun p n =>
    (fun n => Nat.casesOn n (some (r p.fst.fst.fst)) fun n => G₁ ((p.fst.fst.fst, p.fst.fst.snd), n, div2 (div2 n))) n
[PROOFSTEP]
unfold Primrec₂
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
⊢ Primrec fun p =>
    (fun p n =>
        (fun n => Nat.casesOn n (some (r p.fst.fst.fst)) fun n => G₁ ((p.fst.fst.fst, p.fst.fst.snd), n, div2 (div2 n)))
          n)
      p.fst p.snd
[PROOFSTEP]
refine nat_casesOn snd (option_some_iff.2 (hr.comp (fst.comp <| fst.comp <| fst.comp fst))) ?_
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
⊢ Primrec₂ fun p n => (fun n => G₁ ((p.fst.fst.fst.fst, p.fst.fst.fst.snd), n, div2 (div2 n))) n
[PROOFSTEP]
unfold Primrec₂
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
⊢ Primrec fun p => (fun p n => (fun n => G₁ ((p.fst.fst.fst.fst, p.fst.fst.fst.snd), n, div2 (div2 n))) n) p.fst p.snd
[PROOFSTEP]
exact
  this.comp <|
    ((fst.pair snd).comp <| fst.comp <| fst.comp <| fst.comp <| fst).pair <|
      snd.pair <| nat_div2.comp <| nat_div2.comp snd
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
⊢ Primrec fun a => F a (c a)
[PROOFSTEP]
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
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
⊢ F (id a) (ofNat Code (encode (c a))) = F a (c a)
[PROOFSTEP]
simp
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
⊢ G (a, List.map ((fun a n => F a (ofNat Code n)) a) (List.range n)).fst
      (a, List.map ((fun a n => F a (ofNat Code n)) a) (List.range n)).snd =
    some ((fun a n => F a (ofNat Code n)) a n)
[PROOFSTEP]
simp (config := { zeta := false })
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
⊢ G a (List.map (fun n => F a (ofNat Code n)) (List.range n)) = some (F a (ofNat Code n))
[PROOFSTEP]
iterate 4 cases' n with n; · simp (config := { zeta := false }) [ofNatCode_eq, ofNatCode]; rfl
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
⊢ G a (List.map (fun n => F a (ofNat Code n)) (List.range n)) = some (F a (ofNat Code n))
[PROOFSTEP]
cases' n with n
[GOAL]
case zero
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
⊢ G a (List.map (fun n => F a (ofNat Code n)) (List.range Nat.zero)) = some (F a (ofNat Code Nat.zero))
[PROOFSTEP]
simp (config := { zeta := false }) [ofNatCode_eq, ofNatCode]
[GOAL]
case zero
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
⊢ G a [] = some (F a zero)
[PROOFSTEP]
rfl
[GOAL]
case succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
⊢ G a (List.map (fun n => F a (ofNat Code n)) (List.range (Nat.succ n))) = some (F a (ofNat Code (Nat.succ n)))
[PROOFSTEP]
cases' n with n
[GOAL]
case succ.zero
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
⊢ G a (List.map (fun n => F a (ofNat Code n)) (List.range (Nat.succ Nat.zero))) =
    some (F a (ofNat Code (Nat.succ Nat.zero)))
[PROOFSTEP]
simp (config := { zeta := false }) [ofNatCode_eq, ofNatCode]
[GOAL]
case succ.zero
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
⊢ G a [F a zero] = some (F a succ)
[PROOFSTEP]
rfl
[GOAL]
case succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
⊢ G a (List.map (fun n => F a (ofNat Code n)) (List.range (Nat.succ (Nat.succ n)))) =
    some (F a (ofNat Code (Nat.succ (Nat.succ n))))
[PROOFSTEP]
cases' n with n
[GOAL]
case succ.succ.zero
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
⊢ G a (List.map (fun n => F a (ofNat Code n)) (List.range (Nat.succ (Nat.succ Nat.zero)))) =
    some (F a (ofNat Code (Nat.succ (Nat.succ Nat.zero))))
[PROOFSTEP]
simp (config := { zeta := false }) [ofNatCode_eq, ofNatCode]
[GOAL]
case succ.succ.zero
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
⊢ G a [F a zero, F a succ] = some (F a left)
[PROOFSTEP]
rfl
[GOAL]
case succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
⊢ G a (List.map (fun n => F a (ofNat Code n)) (List.range (Nat.succ (Nat.succ (Nat.succ n))))) =
    some (F a (ofNat Code (Nat.succ (Nat.succ (Nat.succ n)))))
[PROOFSTEP]
cases' n with n
[GOAL]
case succ.succ.succ.zero
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
⊢ G a (List.map (fun n => F a (ofNat Code n)) (List.range (Nat.succ (Nat.succ (Nat.succ Nat.zero))))) =
    some (F a (ofNat Code (Nat.succ (Nat.succ (Nat.succ Nat.zero)))))
[PROOFSTEP]
simp (config := { zeta := false }) [ofNatCode_eq, ofNatCode]
[GOAL]
case succ.succ.succ.zero
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
⊢ G a [F a zero, F a succ, F a left] = some (F a right)
[PROOFSTEP]
rfl
[GOAL]
case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
⊢ G a (List.map (fun n => F a (ofNat Code n)) (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n)))))) =
    some (F a (ofNat Code (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
[PROOFSTEP]
simp only []
[GOAL]
case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
⊢ Nat.rec (some (z a))
      (fun n_1 n_ih =>
        Nat.rec (some (s a))
          (fun n_2 n_ih =>
            Nat.rec (some (l a))
              (fun n_3 n_ih =>
                Nat.rec (some (r a))
                  (fun n_4 n_ih =>
                    Option.bind
                      (List.get?
                        (List.map
                          (fun n =>
                            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
                              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
                              (fun cf hf => rf a (cf, hf)) (ofNat Code n))
                          (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
                        (div2 (div2 n_4)))
                      fun s_1 =>
                      Option.bind
                        (List.get?
                          (List.map
                            (fun n =>
                              rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
                                (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
                                (fun cf hf => rf a (cf, hf)) (ofNat Code n))
                            (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
                          (unpair (div2 (div2 n_4))).fst)
                        fun s₁ =>
                        Option.map
                          (fun s₂ =>
                            bif bodd n_4 then
                              bif bodd (div2 n_4) then rf a (ofNat Code (div2 (div2 n_4)), s_1)
                              else
                                pc a
                                  (ofNat Code (unpair (div2 (div2 n_4))).fst, ofNat Code (unpair (div2 (div2 n_4))).snd,
                                    s₁, s₂)
                            else
                              bif bodd (div2 n_4) then
                                co a
                                  (ofNat Code (unpair (div2 (div2 n_4))).fst, ofNat Code (unpair (div2 (div2 n_4))).snd,
                                    s₁, s₂)
                              else
                                pr a
                                  (ofNat Code (unpair (div2 (div2 n_4))).fst, ofNat Code (unpair (div2 (div2 n_4))).snd,
                                    s₁, s₂))
                          (List.get?
                            (List.map
                              (fun n =>
                                rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
                                  (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
                                  (fun cf hf => rf a (cf, hf)) (ofNat Code n))
                              (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
                            (unpair (div2 (div2 n_4))).snd))
                  n_3)
              n_2)
          n_1)
      (List.length
        (List.map
          (fun n =>
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code n))
          (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))) =
    some
      (rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
        (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf))
        (ofNat Code (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
[PROOFSTEP]
rw [List.length_map, List.length_range]
[GOAL]
case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
⊢ Nat.rec (some (z a))
      (fun n_1 n_ih =>
        Nat.rec (some (s a))
          (fun n_2 n_ih =>
            Nat.rec (some (l a))
              (fun n_3 n_ih =>
                Nat.rec (some (r a))
                  (fun n_4 n_ih =>
                    Option.bind
                      (List.get?
                        (List.map
                          (fun n =>
                            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
                              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
                              (fun cf hf => rf a (cf, hf)) (ofNat Code n))
                          (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
                        (div2 (div2 n_4)))
                      fun s_1 =>
                      Option.bind
                        (List.get?
                          (List.map
                            (fun n =>
                              rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
                                (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
                                (fun cf hf => rf a (cf, hf)) (ofNat Code n))
                            (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
                          (unpair (div2 (div2 n_4))).fst)
                        fun s₁ =>
                        Option.map
                          (fun s₂ =>
                            bif bodd n_4 then
                              bif bodd (div2 n_4) then rf a (ofNat Code (div2 (div2 n_4)), s_1)
                              else
                                pc a
                                  (ofNat Code (unpair (div2 (div2 n_4))).fst, ofNat Code (unpair (div2 (div2 n_4))).snd,
                                    s₁, s₂)
                            else
                              bif bodd (div2 n_4) then
                                co a
                                  (ofNat Code (unpair (div2 (div2 n_4))).fst, ofNat Code (unpair (div2 (div2 n_4))).snd,
                                    s₁, s₂)
                              else
                                pr a
                                  (ofNat Code (unpair (div2 (div2 n_4))).fst, ofNat Code (unpair (div2 (div2 n_4))).snd,
                                    s₁, s₂))
                          (List.get?
                            (List.map
                              (fun n =>
                                rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
                                  (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
                                  (fun cf hf => rf a (cf, hf)) (ofNat Code n))
                              (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
                            (unpair (div2 (div2 n_4))).snd))
                  n_3)
              n_2)
          n_1)
      (Nat.succ (Nat.succ (Nat.succ (Nat.succ n)))) =
    some
      (rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
        (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf))
        (ofNat Code (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
[PROOFSTEP]
let m := n.div2.div2
[GOAL]
case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
⊢ Nat.rec (some (z a))
      (fun n_1 n_ih =>
        Nat.rec (some (s a))
          (fun n_2 n_ih =>
            Nat.rec (some (l a))
              (fun n_3 n_ih =>
                Nat.rec (some (r a))
                  (fun n_4 n_ih =>
                    Option.bind
                      (List.get?
                        (List.map
                          (fun n =>
                            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
                              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
                              (fun cf hf => rf a (cf, hf)) (ofNat Code n))
                          (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
                        (div2 (div2 n_4)))
                      fun s_1 =>
                      Option.bind
                        (List.get?
                          (List.map
                            (fun n =>
                              rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
                                (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
                                (fun cf hf => rf a (cf, hf)) (ofNat Code n))
                            (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
                          (unpair (div2 (div2 n_4))).fst)
                        fun s₁ =>
                        Option.map
                          (fun s₂ =>
                            bif bodd n_4 then
                              bif bodd (div2 n_4) then rf a (ofNat Code (div2 (div2 n_4)), s_1)
                              else
                                pc a
                                  (ofNat Code (unpair (div2 (div2 n_4))).fst, ofNat Code (unpair (div2 (div2 n_4))).snd,
                                    s₁, s₂)
                            else
                              bif bodd (div2 n_4) then
                                co a
                                  (ofNat Code (unpair (div2 (div2 n_4))).fst, ofNat Code (unpair (div2 (div2 n_4))).snd,
                                    s₁, s₂)
                              else
                                pr a
                                  (ofNat Code (unpair (div2 (div2 n_4))).fst, ofNat Code (unpair (div2 (div2 n_4))).snd,
                                    s₁, s₂))
                          (List.get?
                            (List.map
                              (fun n =>
                                rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
                                  (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
                                  (fun cf hf => rf a (cf, hf)) (ofNat Code n))
                              (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
                            (unpair (div2 (div2 n_4))).snd))
                  n_3)
              n_2)
          n_1)
      (Nat.succ (Nat.succ (Nat.succ (Nat.succ n)))) =
    some
      (rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
        (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf))
        (ofNat Code (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
[PROOFSTEP]
show G₁ ((a, (List.range (n + 4)).map fun n => F a (ofNat Code n)), n, m) = some (F a (ofNat Code (n + 4)))
[GOAL]
case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
⊢ G₁ ((a, List.map (fun n => F a (ofNat Code n)) (List.range (n + 4))), n, m) = some (F a (ofNat Code (n + 4)))
[PROOFSTEP]
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 _ _))
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
⊢ m < n + 4
[PROOFSTEP]
simp [Nat.div2_val]
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
⊢ n / 2 / 2 < n + 4
[PROOFSTEP]
exact lt_of_le_of_lt (le_trans (Nat.div_le_self _ _) (Nat.div_le_self _ _)) (Nat.succ_le_succ (Nat.le_add_right _ _))
[GOAL]
case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
⊢ G₁ ((a, List.map (fun n => F a (ofNat Code n)) (List.range (n + 4))), n, m) = some (F a (ofNat Code (n + 4)))
[PROOFSTEP]
have m1 : m.unpair.1 < n + 4 := lt_of_le_of_lt m.unpair_left_le hm
[GOAL]
case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
m1 : (unpair m).fst < n + 4
⊢ G₁ ((a, List.map (fun n => F a (ofNat Code n)) (List.range (n + 4))), n, m) = some (F a (ofNat Code (n + 4)))
[PROOFSTEP]
have m2 : m.unpair.2 < n + 4 := lt_of_le_of_lt m.unpair_right_le hm
[GOAL]
case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
m1 : (unpair m).fst < n + 4
m2 : (unpair m).snd < n + 4
⊢ G₁ ((a, List.map (fun n => F a (ofNat Code n)) (List.range (n + 4))), n, m) = some (F a (ofNat Code (n + 4)))
[PROOFSTEP]
simp [List.get?_map, List.get?_range, hm, m1, m2]
[GOAL]
case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
m1 : (unpair m).fst < n + 4
m2 : (unpair m).snd < n + 4
⊢ (bif bodd n then
      bif bodd (div2 n) then
        rf a
          (ofNat Code (div2 (div2 n)),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (div2 (div2 n))))
      else
        pc a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
    else
      bif bodd (div2 n) then
        co a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
      else
        pr a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))) =
    rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
      (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf)) (ofNat Code (n + 4))
[PROOFSTEP]
rw [show ofNat Code (n + 4) = ofNatCode (n + 4) from rfl]
[GOAL]
case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
m1 : (unpair m).fst < n + 4
m2 : (unpair m).snd < n + 4
⊢ (bif bodd n then
      bif bodd (div2 n) then
        rf a
          (ofNat Code (div2 (div2 n)),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (div2 (div2 n))))
      else
        pc a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
    else
      bif bodd (div2 n) then
        co a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
      else
        pr a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))) =
    rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
      (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf)) (ofNatCode (n + 4))
[PROOFSTEP]
simp [ofNatCode]
[GOAL]
case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
m1 : (unpair m).fst < n + 4
m2 : (unpair m).snd < n + 4
⊢ (bif bodd n then
      bif bodd (div2 n) then
        rf a
          (ofNat Code (div2 (div2 n)),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (div2 (div2 n))))
      else
        pc a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
    else
      bif bodd (div2 n) then
        co a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
      else
        pr a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))) =
    rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
      (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf))
      (match bodd n, bodd (div2 n) with
      | false, false => pair (ofNatCode (unpair (div2 (div2 n))).fst) (ofNatCode (unpair (div2 (div2 n))).snd)
      | false, true => comp (ofNatCode (unpair (div2 (div2 n))).fst) (ofNatCode (unpair (div2 (div2 n))).snd)
      | true, false => prec (ofNatCode (unpair (div2 (div2 n))).fst) (ofNatCode (unpair (div2 (div2 n))).snd)
      | true, true => rfind' (ofNatCode (div2 (div2 n))))
[PROOFSTEP]
cases n.bodd
[GOAL]
case succ.succ.succ.succ.false
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
m1 : (unpair m).fst < n + 4
m2 : (unpair m).snd < n + 4
⊢ (bif false then
      bif bodd (div2 n) then
        rf a
          (ofNat Code (div2 (div2 n)),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (div2 (div2 n))))
      else
        pc a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
    else
      bif bodd (div2 n) then
        co a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
      else
        pr a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))) =
    rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
      (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf))
      (match false, 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))))
[PROOFSTEP]
cases n.div2.bodd
[GOAL]
case succ.succ.succ.succ.true
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
m1 : (unpair m).fst < n + 4
m2 : (unpair m).snd < n + 4
⊢ (bif true then
      bif bodd (div2 n) then
        rf a
          (ofNat Code (div2 (div2 n)),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (div2 (div2 n))))
      else
        pc a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
    else
      bif bodd (div2 n) then
        co a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
      else
        pr a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))) =
    rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
      (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf))
      (match true, 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))))
[PROOFSTEP]
cases n.div2.bodd
[GOAL]
case succ.succ.succ.succ.false.false
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
m1 : (unpair m).fst < n + 4
m2 : (unpair m).snd < n + 4
⊢ (bif false then
      bif false then
        rf a
          (ofNat Code (div2 (div2 n)),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (div2 (div2 n))))
      else
        pc a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
    else
      bif false then
        co a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
      else
        pr a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))) =
    rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
      (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf))
      (match false, false 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))))
[PROOFSTEP]
rfl
[GOAL]
case succ.succ.succ.succ.false.true
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
m1 : (unpair m).fst < n + 4
m2 : (unpair m).snd < n + 4
⊢ (bif false then
      bif true then
        rf a
          (ofNat Code (div2 (div2 n)),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (div2 (div2 n))))
      else
        pc a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
    else
      bif true then
        co a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
      else
        pr a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))) =
    rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
      (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf))
      (match false, true 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))))
[PROOFSTEP]
rfl
[GOAL]
case succ.succ.succ.succ.true.false
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
m1 : (unpair m).fst < n + 4
m2 : (unpair m).snd < n + 4
⊢ (bif true then
      bif false then
        rf a
          (ofNat Code (div2 (div2 n)),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (div2 (div2 n))))
      else
        pc a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
    else
      bif false then
        co a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
      else
        pr a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))) =
    rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
      (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf))
      (match true, false 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))))
[PROOFSTEP]
rfl
[GOAL]
case succ.succ.succ.succ.true.true
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Primrec c
z : α → σ
hz : Primrec z
s : α → σ
hs : Primrec s
l : α → σ
hl : Primrec l
r : α → σ
hr : Primrec r
pr : α → Code × Code × σ × σ → σ
hpr : Primrec₂ pr
co : α → Code × Code × σ × σ → σ
hco : Primrec₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Primrec₂ pc
rf : α → Code × σ → σ
hrf : Primrec₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Primrec G₁
G : α → List σ → Option σ :=
  fun a IH =>
    Nat.casesOn (List.length IH) (some (z a)) fun n =>
      Nat.casesOn n (some (s a)) fun n =>
        Nat.casesOn n (some (l a)) fun n => Nat.casesOn n (some (r a)) fun n => G₁ ((a, IH), n, div2 (div2 n))
this : Primrec₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
m1 : (unpair m).fst < n + 4
m2 : (unpair m).snd < n + 4
⊢ (bif true then
      bif true then
        rf a
          (ofNat Code (div2 (div2 n)),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (div2 (div2 n))))
      else
        pc a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
    else
      bif true then
        co a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
      else
        pr a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))) =
    rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
      (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf))
      (match true, true 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))))
[PROOFSTEP]
rfl
[GOAL]
α : 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)
[PROOFSTEP]
intros F
[GOAL]
α : 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)
[PROOFSTEP]
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₂))
[GOAL]
α : 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)
[PROOFSTEP]
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₄)
[GOAL]
α : 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₁
[PROOFSTEP]
refine' option_bind (list_get?.comp (snd.comp fst) (snd.comp snd)) _
[GOAL]
α : 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)
[PROOFSTEP]
unfold Primrec₂
[GOAL]
α : 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
[PROOFSTEP]
refine' option_bind ((list_get?.comp (snd.comp fst) (fst.comp <| Primrec.unpair.comp (snd.comp snd))).comp fst) _
[GOAL]
α : 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)
[PROOFSTEP]
unfold Primrec₂
[GOAL]
α : 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
[PROOFSTEP]
refine'
  option_map ((list_get?.comp (snd.comp fst) (snd.comp <| Primrec.unpair.comp (snd.comp snd))).comp <| fst.comp fst) _
[GOAL]
α : 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₂
[PROOFSTEP]
have a : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.1.1.1.1) :=
  fst.comp (fst.comp <| fst.comp <| fst.comp fst)
[GOAL]
α : 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₂
[PROOFSTEP]
have n : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.1.1.2.1) :=
  fst.comp (snd.comp <| fst.comp <| fst.comp fst)
[GOAL]
α : 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₂
[PROOFSTEP]
have m : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.1.1.2.2) :=
  snd.comp (snd.comp <| fst.comp <| fst.comp fst)
[GOAL]
α : 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₂
[PROOFSTEP]
have m₁ := fst.comp (Primrec.unpair.comp m)
[GOAL]
α : 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₂
[PROOFSTEP]
have m₂ := snd.comp (Primrec.unpair.comp m)
[GOAL]
α : 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₂
[PROOFSTEP]
have s : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.1.2) := snd.comp (fst.comp fst)
[GOAL]
α : 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₂
[PROOFSTEP]
have s₁ : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.2) := snd.comp fst
[GOAL]
α : 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₂
[PROOFSTEP]
have s₂ : Primrec (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.2) := snd
[GOAL]
α : 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₂
[PROOFSTEP]
have h₁ := hrf.comp <| a.pair (((Primrec.ofNat Code).comp m).pair s)
[GOAL]
α : 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₂
[PROOFSTEP]
have h₂ := hpc.comp <| a.pair (((Primrec.ofNat Code).comp m₁).pair <| ((Primrec.ofNat Code).comp m₂).pair <| s₁.pair s₂)
[GOAL]
α : 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₂
[PROOFSTEP]
have h₃ := hco.comp <| a.pair (((Primrec.ofNat Code).comp m₁).pair <| ((Primrec.ofNat Code).comp m₂).pair <| s₁.pair s₂)
[GOAL]
α : 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₂
[PROOFSTEP]
have h₄ := hpr.comp <| a.pair (((Primrec.ofNat Code).comp m₁).pair <| ((Primrec.ofNat Code).comp m₂).pair <| s₁.pair s₂)
[GOAL]
α : 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₂
[PROOFSTEP]
unfold Primrec₂
[GOAL]
α : 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
[PROOFSTEP]
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₄)
[GOAL]
α : 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)
[PROOFSTEP]
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)
[GOAL]
α : 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)
[PROOFSTEP]
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
[GOAL]
α : 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
[PROOFSTEP]
unfold Primrec₂
[GOAL]
α : 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
[PROOFSTEP]
refine nat_casesOn (list_length.comp snd) (option_some_iff.2 (hz.comp fst)) ?_
[GOAL]
α : 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
[PROOFSTEP]
unfold Primrec₂
[GOAL]
α : 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
[PROOFSTEP]
refine nat_casesOn snd (option_some_iff.2 (hs.comp (fst.comp fst))) ?_
[GOAL]
α : 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
[PROOFSTEP]
unfold Primrec₂
[GOAL]
α : 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
[PROOFSTEP]
refine nat_casesOn snd (option_some_iff.2 (hl.comp (fst.comp <| fst.comp fst))) ?_
[GOAL]
α : 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
[PROOFSTEP]
unfold Primrec₂
[GOAL]
α : 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
[PROOFSTEP]
refine nat_casesOn snd (option_some_iff.2 (hr.comp (fst.comp <| fst.comp <| fst.comp fst))) ?_
[GOAL]
α : 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
[PROOFSTEP]
unfold Primrec₂
[GOAL]
α : 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
[PROOFSTEP]
exact
  this.comp <|
    ((fst.pair snd).comp <| fst.comp <| fst.comp <| fst.comp <| fst).pair <|
      snd.pair <| nat_div2.comp <| nat_div2.comp snd
[GOAL]
α : 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)
[PROOFSTEP]
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
[GOAL]
α : 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)
[PROOFSTEP]
simp
[GOAL]
α : 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)
[PROOFSTEP]
simp (config := { zeta := false })
[GOAL]
α : 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 n)) = some (F a (ofNat Code n))
[PROOFSTEP]
iterate 4 cases' n with n; · simp (config := { zeta := false }) [ofNatCode_eq, ofNatCode]; rfl
[GOAL]
α : 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 n)) = some (F a (ofNat Code n))
[PROOFSTEP]
cases' n with n
[GOAL]
case 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.zero)) = some (F a (ofNat Code Nat.zero))
[PROOFSTEP]
simp (config := { zeta := false }) [ofNatCode_eq, ofNatCode]
[GOAL]
case 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 [] = some (F a zero)
[PROOFSTEP]
rfl
[GOAL]
case 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 n))) = some (F a (ofNat Code (Nat.succ n)))
[PROOFSTEP]
cases' n with n
[GOAL]
case 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.zero))) =
    some (F a (ofNat Code (Nat.succ Nat.zero)))
[PROOFSTEP]
simp (config := { zeta := false }) [ofNatCode_eq, ofNatCode]
[GOAL]
case 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] = some (F a succ)
[PROOFSTEP]
rfl
[GOAL]
case 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 n)))) =
    some (F a (ofNat Code (Nat.succ (Nat.succ n))))
[PROOFSTEP]
cases' n with n
[GOAL]
case 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.zero)))) =
    some (F a (ofNat Code (Nat.succ (Nat.succ Nat.zero))))
[PROOFSTEP]
simp (config := { zeta := false }) [ofNatCode_eq, ofNatCode]
[GOAL]
case 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] = some (F a left)
[PROOFSTEP]
rfl
[GOAL]
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)))))
[PROOFSTEP]
cases' n with n
[GOAL]
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)))))
[PROOFSTEP]
simp (config := { zeta := false }) [ofNatCode_eq, ofNatCode]
[GOAL]
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 right)
[PROOFSTEP]
rfl
[GOAL]
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))))))
[PROOFSTEP]
simp only []
[GOAL]
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))))))
[PROOFSTEP]
rw [List.length_map, List.length_range]
[GOAL]
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))))))
[PROOFSTEP]
let m := n.div2.div2
[GOAL]
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))))))
[PROOFSTEP]
show G₁ ((a, (List.range (n + 4)).map fun n => F a (ofNat Code n)), n, m) = some (F a (ofNat Code (n + 4)))
[GOAL]
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)))
[PROOFSTEP]
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 _ _))
[GOAL]
α : 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
[PROOFSTEP]
simp [Nat.div2_val]
[GOAL]
α : 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
[PROOFSTEP]
exact lt_of_le_of_lt (le_trans (Nat.div_le_self _ _) (Nat.div_le_self _ _)) (Nat.succ_le_succ (Nat.le_add_right _ _))
[GOAL]
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)))
[PROOFSTEP]
have m1 : m.unpair.1 < n + 4 := lt_of_le_of_lt m.unpair_left_le hm
[GOAL]
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)))
[PROOFSTEP]
have m2 : m.unpair.2 < n + 4 := lt_of_le_of_lt m.unpair_right_le hm
[GOAL]
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)))
[PROOFSTEP]
simp [List.get?_map, List.get?_range, hm, m1, m2]
[GOAL]
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))
[PROOFSTEP]
rw [show ofNat Code (n + 4) = ofNatCode (n + 4) from rfl]
[GOAL]
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))
[PROOFSTEP]
simp [ofNatCode]
[GOAL]
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))))
[PROOFSTEP]
cases n.bodd
[GOAL]
case succ.succ.succ.succ.false
α : 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 false 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 false, 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))))
[PROOFSTEP]
cases n.div2.bodd
[GOAL]
case succ.succ.succ.succ.true
α : 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 true 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 true, 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))))
[PROOFSTEP]
cases n.div2.bodd
[GOAL]
case succ.succ.succ.succ.false.false
α : 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 false then
      bif false 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 false 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 false, false 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))))
[PROOFSTEP]
rfl
[GOAL]
case succ.succ.succ.succ.false.true
α : 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 false then
      bif true 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 true 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 false, true 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))))
[PROOFSTEP]
rfl
[GOAL]
case succ.succ.succ.succ.true.false
α : 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 true then
      bif false 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 false 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 true, false 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))))
[PROOFSTEP]
rfl
[GOAL]
case succ.succ.succ.succ.true.true
α : 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 true then
      bif true 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 true 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 true, true 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))))
[PROOFSTEP]
rfl
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
⊢ let PR := fun a cf cg hf hg => pr a (cf, cg, hf, hg);
  let CO := fun a cf cg hf hg => co a (cf, cg, hf, hg);
  let PC := fun a cf cg hf hg => pc a (cf, cg, hf, hg);
  let RF := fun a cf hf => rf a (cf, hf);
  let F := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR a) (CO a) (PC a) (RF a);
  Computable fun a => F a (c a)
[PROOFSTEP]
intros _ _ _ _ F
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
⊢ Computable fun a => F a (c a)
[PROOFSTEP]
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₂)))
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
⊢ Computable fun a => F a (c a)
[PROOFSTEP]
have : Computable G₁ := by
  refine' option_bind (list_get?.comp (snd.comp fst) (snd.comp snd)) _
  unfold Computable₂
  refine' option_bind ((list_get?.comp (snd.comp fst) (fst.comp <| Computable.unpair.comp (snd.comp snd))).comp fst) _
  unfold Computable₂
  refine'
    option_map
      ((list_get?.comp (snd.comp fst) (snd.comp <| Computable.unpair.comp (snd.comp snd))).comp <| fst.comp fst) _
  have a : Computable (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.1.1.1.1) :=
    fst.comp (fst.comp <| fst.comp <| fst.comp fst)
  have n : Computable (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.1.1.2.1) :=
    fst.comp (snd.comp <| fst.comp <| fst.comp fst)
  have m : Computable (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.1.1.2.2) :=
    snd.comp (snd.comp <| fst.comp <| fst.comp fst)
  have m₁ := fst.comp (Computable.unpair.comp m)
  have m₂ := snd.comp (Computable.unpair.comp m)
  have s : Computable (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.1.2) := snd.comp (fst.comp fst)
  have s₁ : Computable (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.2) := snd.comp fst
  have s₂ : Computable (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.2) := snd
  exact
    (nat_bodd.comp n).cond
      ((nat_bodd.comp <| nat_div2.comp n).cond (hrf.comp a (((Computable.ofNat Code).comp m).pair s))
        (hpc.comp a (((Computable.ofNat Code).comp m₁).pair <| ((Computable.ofNat Code).comp m₂).pair <| s₁.pair s₂)))
      (Computable.cond (nat_bodd.comp <| nat_div2.comp n)
        (hco.comp a (((Computable.ofNat Code).comp m₁).pair <| ((Computable.ofNat Code).comp m₂).pair <| s₁.pair s₂))
        (hpr.comp a (((Computable.ofNat Code).comp m₁).pair <| ((Computable.ofNat Code).comp m₂).pair <| s₁.pair s₂)))
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
⊢ Computable G₁
[PROOFSTEP]
refine' option_bind (list_get?.comp (snd.comp fst) (snd.comp snd)) _
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
⊢ Computable₂ 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)
[PROOFSTEP]
unfold Computable₂
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
⊢ Computable 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
[PROOFSTEP]
refine' option_bind ((list_get?.comp (snd.comp fst) (fst.comp <| Computable.unpair.comp (snd.comp snd))).comp fst) _
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
⊢ Computable₂ 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)
[PROOFSTEP]
unfold Computable₂
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
⊢ Computable 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
[PROOFSTEP]
refine'
  option_map ((list_get?.comp (snd.comp fst) (snd.comp <| Computable.unpair.comp (snd.comp snd))).comp <| fst.comp fst)
    _
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
⊢ Computable₂ 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₂)
[PROOFSTEP]
have a : Computable (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.1.1.1.1) :=
  fst.comp (fst.comp <| fst.comp <| fst.comp fst)
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
a : Computable fun p => p.fst.fst.fst.fst.fst
⊢ Computable₂ 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₂)
[PROOFSTEP]
have n : Computable (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.1.1.2.1) :=
  fst.comp (snd.comp <| fst.comp <| fst.comp fst)
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
a : Computable fun p => p.fst.fst.fst.fst.fst
n : Computable fun p => p.fst.fst.fst.snd.fst
⊢ Computable₂ 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₂)
[PROOFSTEP]
have m : Computable (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.1.1.2.2) :=
  snd.comp (snd.comp <| fst.comp <| fst.comp fst)
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
a : Computable fun p => p.fst.fst.fst.fst.fst
n : Computable fun p => p.fst.fst.fst.snd.fst
m : Computable fun p => p.fst.fst.fst.snd.snd
⊢ Computable₂ 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₂)
[PROOFSTEP]
have m₁ := fst.comp (Computable.unpair.comp m)
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
a : Computable fun p => p.fst.fst.fst.fst.fst
n : Computable fun p => p.fst.fst.fst.snd.fst
m : Computable fun p => p.fst.fst.fst.snd.snd
m₁ : Computable fun a => (unpair a.fst.fst.fst.snd.snd).fst
⊢ Computable₂ 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₂)
[PROOFSTEP]
have m₂ := snd.comp (Computable.unpair.comp m)
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
a : Computable fun p => p.fst.fst.fst.fst.fst
n : Computable fun p => p.fst.fst.fst.snd.fst
m : Computable fun p => p.fst.fst.fst.snd.snd
m₁ : Computable fun a => (unpair a.fst.fst.fst.snd.snd).fst
m₂ : Computable fun a => (unpair a.fst.fst.fst.snd.snd).snd
⊢ Computable₂ 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₂)
[PROOFSTEP]
have s : Computable (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.1.2) := snd.comp (fst.comp fst)
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s✝ : α → σ
hs : Computable s✝
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s✝ a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
a : Computable fun p => p.fst.fst.fst.fst.fst
n : Computable fun p => p.fst.fst.fst.snd.fst
m : Computable fun p => p.fst.fst.fst.snd.snd
m₁ : Computable fun a => (unpair a.fst.fst.fst.snd.snd).fst
m₂ : Computable fun a => (unpair a.fst.fst.fst.snd.snd).snd
s : Computable fun p => p.fst.fst.snd
⊢ Computable₂ 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₂)
[PROOFSTEP]
have s₁ : Computable (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.1.2) := snd.comp fst
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s✝ : α → σ
hs : Computable s✝
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s✝ a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
a : Computable fun p => p.fst.fst.fst.fst.fst
n : Computable fun p => p.fst.fst.fst.snd.fst
m : Computable fun p => p.fst.fst.fst.snd.snd
m₁ : Computable fun a => (unpair a.fst.fst.fst.snd.snd).fst
m₂ : Computable fun a => (unpair a.fst.fst.fst.snd.snd).snd
s : Computable fun p => p.fst.fst.snd
s₁ : Computable fun p => p.fst.snd
⊢ Computable₂ 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₂)
[PROOFSTEP]
have s₂ : Computable (fun p : ((((α × List σ) × ℕ × ℕ) × σ) × σ) × σ => p.2) := snd
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s✝ : α → σ
hs : Computable s✝
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s✝ a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
a : Computable fun p => p.fst.fst.fst.fst.fst
n : Computable fun p => p.fst.fst.fst.snd.fst
m : Computable fun p => p.fst.fst.fst.snd.snd
m₁ : Computable fun a => (unpair a.fst.fst.fst.snd.snd).fst
m₂ : Computable fun a => (unpair a.fst.fst.fst.snd.snd).snd
s : Computable fun p => p.fst.fst.snd
s₁ : Computable fun p => p.fst.snd
s₂ : Computable fun p => p.snd
⊢ Computable₂ 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₂)
[PROOFSTEP]
exact
  (nat_bodd.comp n).cond
    ((nat_bodd.comp <| nat_div2.comp n).cond (hrf.comp a (((Computable.ofNat Code).comp m).pair s))
      (hpc.comp a (((Computable.ofNat Code).comp m₁).pair <| ((Computable.ofNat Code).comp m₂).pair <| s₁.pair s₂)))
    (Computable.cond (nat_bodd.comp <| nat_div2.comp n)
      (hco.comp a (((Computable.ofNat Code).comp m₁).pair <| ((Computable.ofNat Code).comp m₂).pair <| s₁.pair s₂))
      (hpr.comp a (((Computable.ofNat Code).comp m₁).pair <| ((Computable.ofNat Code).comp m₂).pair <| s₁.pair s₂)))
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this : Computable G₁
⊢ Computable fun a => F a (c a)
[PROOFSTEP]
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)
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this : Computable 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))
⊢ Computable fun a => F a (c a)
[PROOFSTEP]
have : Computable₂ G :=
  Computable.nat_casesOn (list_length.comp snd) (option_some_iff.2 (hz.comp fst)) <|
    Computable.nat_casesOn snd (option_some_iff.2 (hs.comp (fst.comp fst))) <|
      Computable.nat_casesOn snd (option_some_iff.2 (hl.comp (fst.comp <| fst.comp fst))) <|
        Computable.nat_casesOn snd (option_some_iff.2 (hr.comp (fst.comp <| fst.comp <| fst.comp fst)))
          (this.comp <|
            ((Computable.fst.pair snd).comp <| fst.comp <| fst.comp <| fst.comp <| fst).pair <|
              snd.pair <| nat_div2.comp <| nat_div2.comp snd)
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ G
⊢ Computable fun a => F a (c a)
[PROOFSTEP]
refine'
  ((nat_strong_rec (fun a n => F a (ofNat Code n)) this.to₂ fun a n => _).comp Computable.id <| encode_iff.2 hc).of_eq
    fun a => by simp
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ G
a : α
⊢ F (id a) (ofNat Code (encode (c a))) = F a (c a)
[PROOFSTEP]
simp
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ 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)
[PROOFSTEP]
simp (config := { zeta := false })
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ G
a : α
n : ℕ
⊢ G a (List.map (fun n => F a (ofNat Code n)) (List.range n)) = some (F a (ofNat Code n))
[PROOFSTEP]
iterate 4 cases' n with n; · simp (config := { zeta := false }) [ofNatCode_eq, ofNatCode]; rfl
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ G
a : α
n : ℕ
⊢ G a (List.map (fun n => F a (ofNat Code n)) (List.range n)) = some (F a (ofNat Code n))
[PROOFSTEP]
cases' n with n
[GOAL]
case zero
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ G
a : α
⊢ G a (List.map (fun n => F a (ofNat Code n)) (List.range Nat.zero)) = some (F a (ofNat Code Nat.zero))
[PROOFSTEP]
simp (config := { zeta := false }) [ofNatCode_eq, ofNatCode]
[GOAL]
case zero
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ G
a : α
⊢ G a [] = some (F a zero)
[PROOFSTEP]
rfl
[GOAL]
case succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ G
a : α
n : ℕ
⊢ G a (List.map (fun n => F a (ofNat Code n)) (List.range (Nat.succ n))) = some (F a (ofNat Code (Nat.succ n)))
[PROOFSTEP]
cases' n with n
[GOAL]
case succ.zero
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ G
a : α
⊢ G a (List.map (fun n => F a (ofNat Code n)) (List.range (Nat.succ Nat.zero))) =
    some (F a (ofNat Code (Nat.succ Nat.zero)))
[PROOFSTEP]
simp (config := { zeta := false }) [ofNatCode_eq, ofNatCode]
[GOAL]
case succ.zero
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ G
a : α
⊢ G a [F a zero] = some (F a succ)
[PROOFSTEP]
rfl
[GOAL]
case succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ G
a : α
n : ℕ
⊢ G a (List.map (fun n => F a (ofNat Code n)) (List.range (Nat.succ (Nat.succ n)))) =
    some (F a (ofNat Code (Nat.succ (Nat.succ n))))
[PROOFSTEP]
cases' n with n
[GOAL]
case succ.succ.zero
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ G
a : α
⊢ G a (List.map (fun n => F a (ofNat Code n)) (List.range (Nat.succ (Nat.succ Nat.zero)))) =
    some (F a (ofNat Code (Nat.succ (Nat.succ Nat.zero))))
[PROOFSTEP]
simp (config := { zeta := false }) [ofNatCode_eq, ofNatCode]
[GOAL]
case succ.succ.zero
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ G
a : α
⊢ G a [F a zero, F a succ] = some (F a left)
[PROOFSTEP]
rfl
[GOAL]
case succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ 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)))))
[PROOFSTEP]
cases' n with n
[GOAL]
case succ.succ.succ.zero
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ 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)))))
[PROOFSTEP]
simp (config := { zeta := false }) [ofNatCode_eq, ofNatCode]
[GOAL]
case succ.succ.succ.zero
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ G
a : α
⊢ G a [F a zero, F a succ, F a left] = some (F a right)
[PROOFSTEP]
rfl
[GOAL]
case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ 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))))))
[PROOFSTEP]
simp only []
[GOAL]
case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ G
a : α
n : ℕ
⊢ Nat.rec (some (z a))
      (fun n_1 n_ih =>
        Nat.rec (some (s a))
          (fun n_2 n_ih =>
            Nat.rec (some (l a))
              (fun n_3 n_ih =>
                Nat.rec (some (r a))
                  (fun n_4 n_ih =>
                    Option.bind
                      (List.get?
                        (List.map
                          (fun n =>
                            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
                              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
                              (fun cf hf => rf a (cf, hf)) (ofNat Code n))
                          (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
                        (div2 (div2 n_4)))
                      fun s_1 =>
                      Option.bind
                        (List.get?
                          (List.map
                            (fun n =>
                              rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
                                (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
                                (fun cf hf => rf a (cf, hf)) (ofNat Code n))
                            (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
                          (unpair (div2 (div2 n_4))).fst)
                        fun s₁ =>
                        Option.map
                          (fun s₂ =>
                            bif bodd n_4 then
                              bif bodd (div2 n_4) then rf a (ofNat Code (div2 (div2 n_4)), s_1)
                              else
                                pc a
                                  (ofNat Code (unpair (div2 (div2 n_4))).fst, ofNat Code (unpair (div2 (div2 n_4))).snd,
                                    s₁, s₂)
                            else
                              bif bodd (div2 n_4) then
                                co a
                                  (ofNat Code (unpair (div2 (div2 n_4))).fst, ofNat Code (unpair (div2 (div2 n_4))).snd,
                                    s₁, s₂)
                              else
                                pr a
                                  (ofNat Code (unpair (div2 (div2 n_4))).fst, ofNat Code (unpair (div2 (div2 n_4))).snd,
                                    s₁, s₂))
                          (List.get?
                            (List.map
                              (fun n =>
                                rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
                                  (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
                                  (fun cf hf => rf a (cf, hf)) (ofNat Code n))
                              (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
                            (unpair (div2 (div2 n_4))).snd))
                  n_3)
              n_2)
          n_1)
      (List.length
        (List.map
          (fun n =>
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code n))
          (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))) =
    some
      (rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
        (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf))
        (ofNat Code (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
[PROOFSTEP]
rw [List.length_map, List.length_range]
[GOAL]
case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ G
a : α
n : ℕ
⊢ Nat.rec (some (z a))
      (fun n_1 n_ih =>
        Nat.rec (some (s a))
          (fun n_2 n_ih =>
            Nat.rec (some (l a))
              (fun n_3 n_ih =>
                Nat.rec (some (r a))
                  (fun n_4 n_ih =>
                    Option.bind
                      (List.get?
                        (List.map
                          (fun n =>
                            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
                              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
                              (fun cf hf => rf a (cf, hf)) (ofNat Code n))
                          (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
                        (div2 (div2 n_4)))
                      fun s_1 =>
                      Option.bind
                        (List.get?
                          (List.map
                            (fun n =>
                              rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
                                (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
                                (fun cf hf => rf a (cf, hf)) (ofNat Code n))
                            (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
                          (unpair (div2 (div2 n_4))).fst)
                        fun s₁ =>
                        Option.map
                          (fun s₂ =>
                            bif bodd n_4 then
                              bif bodd (div2 n_4) then rf a (ofNat Code (div2 (div2 n_4)), s_1)
                              else
                                pc a
                                  (ofNat Code (unpair (div2 (div2 n_4))).fst, ofNat Code (unpair (div2 (div2 n_4))).snd,
                                    s₁, s₂)
                            else
                              bif bodd (div2 n_4) then
                                co a
                                  (ofNat Code (unpair (div2 (div2 n_4))).fst, ofNat Code (unpair (div2 (div2 n_4))).snd,
                                    s₁, s₂)
                              else
                                pr a
                                  (ofNat Code (unpair (div2 (div2 n_4))).fst, ofNat Code (unpair (div2 (div2 n_4))).snd,
                                    s₁, s₂))
                          (List.get?
                            (List.map
                              (fun n =>
                                rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
                                  (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
                                  (fun cf hf => rf a (cf, hf)) (ofNat Code n))
                              (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
                            (unpair (div2 (div2 n_4))).snd))
                  n_3)
              n_2)
          n_1)
      (Nat.succ (Nat.succ (Nat.succ (Nat.succ n)))) =
    some
      (rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
        (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf))
        (ofNat Code (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
[PROOFSTEP]
let m := n.div2.div2
[GOAL]
case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
⊢ Nat.rec (some (z a))
      (fun n_1 n_ih =>
        Nat.rec (some (s a))
          (fun n_2 n_ih =>
            Nat.rec (some (l a))
              (fun n_3 n_ih =>
                Nat.rec (some (r a))
                  (fun n_4 n_ih =>
                    Option.bind
                      (List.get?
                        (List.map
                          (fun n =>
                            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
                              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
                              (fun cf hf => rf a (cf, hf)) (ofNat Code n))
                          (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
                        (div2 (div2 n_4)))
                      fun s_1 =>
                      Option.bind
                        (List.get?
                          (List.map
                            (fun n =>
                              rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
                                (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
                                (fun cf hf => rf a (cf, hf)) (ofNat Code n))
                            (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
                          (unpair (div2 (div2 n_4))).fst)
                        fun s₁ =>
                        Option.map
                          (fun s₂ =>
                            bif bodd n_4 then
                              bif bodd (div2 n_4) then rf a (ofNat Code (div2 (div2 n_4)), s_1)
                              else
                                pc a
                                  (ofNat Code (unpair (div2 (div2 n_4))).fst, ofNat Code (unpair (div2 (div2 n_4))).snd,
                                    s₁, s₂)
                            else
                              bif bodd (div2 n_4) then
                                co a
                                  (ofNat Code (unpair (div2 (div2 n_4))).fst, ofNat Code (unpair (div2 (div2 n_4))).snd,
                                    s₁, s₂)
                              else
                                pr a
                                  (ofNat Code (unpair (div2 (div2 n_4))).fst, ofNat Code (unpair (div2 (div2 n_4))).snd,
                                    s₁, s₂))
                          (List.get?
                            (List.map
                              (fun n =>
                                rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
                                  (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
                                  (fun cf hf => rf a (cf, hf)) (ofNat Code n))
                              (List.range (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
                            (unpair (div2 (div2 n_4))).snd))
                  n_3)
              n_2)
          n_1)
      (Nat.succ (Nat.succ (Nat.succ (Nat.succ n)))) =
    some
      (rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
        (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf))
        (ofNat Code (Nat.succ (Nat.succ (Nat.succ (Nat.succ n))))))
[PROOFSTEP]
show G₁ ((a, (List.range (n + 4)).map fun n => F a (ofNat Code n)), n, m) = some (F a (ofNat Code (n + 4)))
[GOAL]
case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ 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)))
[PROOFSTEP]
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 _ _))
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
⊢ m < n + 4
[PROOFSTEP]
simp [Nat.div2_val]
[GOAL]
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
⊢ n / 2 / 2 < n + 4
[PROOFSTEP]
exact lt_of_le_of_lt (le_trans (Nat.div_le_self _ _) (Nat.div_le_self _ _)) (Nat.succ_le_succ (Nat.le_add_right _ _))
[GOAL]
case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ 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)))
[PROOFSTEP]
have m1 : m.unpair.1 < n + 4 := lt_of_le_of_lt m.unpair_left_le hm
[GOAL]
case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ 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)))
[PROOFSTEP]
have m2 : m.unpair.2 < n + 4 := lt_of_le_of_lt m.unpair_right_le hm
[GOAL]
case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ 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)))
[PROOFSTEP]
simp [List.get?_map, List.get?_range, hm, m1, m2]
[GOAL]
case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
m1 : (unpair m).fst < n + 4
m2 : (unpair m).snd < n + 4
⊢ (bif bodd n then
      bif bodd (div2 n) then
        rf a
          (ofNat Code (div2 (div2 n)),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (div2 (div2 n))))
      else
        pc a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
    else
      bif bodd (div2 n) then
        co a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
      else
        pr a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))) =
    rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
      (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf)) (ofNat Code (n + 4))
[PROOFSTEP]
rw [show ofNat Code (n + 4) = ofNatCode (n + 4) from rfl]
[GOAL]
case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
m1 : (unpair m).fst < n + 4
m2 : (unpair m).snd < n + 4
⊢ (bif bodd n then
      bif bodd (div2 n) then
        rf a
          (ofNat Code (div2 (div2 n)),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (div2 (div2 n))))
      else
        pc a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
    else
      bif bodd (div2 n) then
        co a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
      else
        pr a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))) =
    rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
      (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf)) (ofNatCode (n + 4))
[PROOFSTEP]
simp [ofNatCode]
[GOAL]
case succ.succ.succ.succ
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
m1 : (unpair m).fst < n + 4
m2 : (unpair m).snd < n + 4
⊢ (bif bodd n then
      bif bodd (div2 n) then
        rf a
          (ofNat Code (div2 (div2 n)),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (div2 (div2 n))))
      else
        pc a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
    else
      bif bodd (div2 n) then
        co a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
      else
        pr a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))) =
    rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
      (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf))
      (match bodd n, bodd (div2 n) with
      | false, false => pair (ofNatCode (unpair (div2 (div2 n))).fst) (ofNatCode (unpair (div2 (div2 n))).snd)
      | false, true => comp (ofNatCode (unpair (div2 (div2 n))).fst) (ofNatCode (unpair (div2 (div2 n))).snd)
      | true, false => prec (ofNatCode (unpair (div2 (div2 n))).fst) (ofNatCode (unpair (div2 (div2 n))).snd)
      | true, true => rfind' (ofNatCode (div2 (div2 n))))
[PROOFSTEP]
cases n.bodd
[GOAL]
case succ.succ.succ.succ.false
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
m1 : (unpair m).fst < n + 4
m2 : (unpair m).snd < n + 4
⊢ (bif false then
      bif bodd (div2 n) then
        rf a
          (ofNat Code (div2 (div2 n)),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (div2 (div2 n))))
      else
        pc a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
    else
      bif bodd (div2 n) then
        co a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
      else
        pr a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))) =
    rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
      (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf))
      (match false, 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))))
[PROOFSTEP]
cases n.div2.bodd
[GOAL]
case succ.succ.succ.succ.true
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
m1 : (unpair m).fst < n + 4
m2 : (unpair m).snd < n + 4
⊢ (bif true then
      bif bodd (div2 n) then
        rf a
          (ofNat Code (div2 (div2 n)),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (div2 (div2 n))))
      else
        pc a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
    else
      bif bodd (div2 n) then
        co a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
      else
        pr a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))) =
    rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
      (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf))
      (match true, 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))))
[PROOFSTEP]
cases n.div2.bodd
[GOAL]
case succ.succ.succ.succ.false.false
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
m1 : (unpair m).fst < n + 4
m2 : (unpair m).snd < n + 4
⊢ (bif false then
      bif false then
        rf a
          (ofNat Code (div2 (div2 n)),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (div2 (div2 n))))
      else
        pc a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
    else
      bif false then
        co a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
      else
        pr a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))) =
    rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
      (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf))
      (match false, false 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))))
[PROOFSTEP]
rfl
[GOAL]
case succ.succ.succ.succ.false.true
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
m1 : (unpair m).fst < n + 4
m2 : (unpair m).snd < n + 4
⊢ (bif false then
      bif true then
        rf a
          (ofNat Code (div2 (div2 n)),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (div2 (div2 n))))
      else
        pc a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
    else
      bif true then
        co a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
      else
        pr a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))) =
    rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
      (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf))
      (match false, true 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))))
[PROOFSTEP]
rfl
[GOAL]
case succ.succ.succ.succ.true.false
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
m1 : (unpair m).fst < n + 4
m2 : (unpair m).snd < n + 4
⊢ (bif true then
      bif false then
        rf a
          (ofNat Code (div2 (div2 n)),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (div2 (div2 n))))
      else
        pc a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
    else
      bif false then
        co a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
      else
        pr a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))) =
    rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
      (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf))
      (match true, false 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))))
[PROOFSTEP]
rfl
[GOAL]
case succ.succ.succ.succ.true.true
α : Type u_1
σ : Type u_2
inst✝¹ : Primcodable α
inst✝ : Primcodable σ
c : α → Code
hc : Computable c
z : α → σ
hz : Computable z
s : α → σ
hs : Computable s
l : α → σ
hl : Computable l
r : α → σ
hr : Computable r
pr : α → Code × Code × σ × σ → σ
hpr : Computable₂ pr
co : α → Code × Code × σ × σ → σ
hco : Computable₂ co
pc : α → Code × Code × σ × σ → σ
hpc : Computable₂ pc
rf : α → Code × σ → σ
hrf : Computable₂ rf
PR✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pr a (cf, cg, hf, hg)
CO✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => co a (cf, cg, hf, hg)
PC✝ : α → Code → Code → σ → σ → σ := fun a cf cg hf hg => pc a (cf, cg, hf, hg)
RF✝ : α → Code → σ → σ := fun a cf hf => rf a (cf, hf)
F : α → Code → σ := fun a c => Code.recOn c (z a) (s a) (l a) (r a) (PR✝ a) (CO✝ a) (PC✝ a) (RF✝ a)
G₁ : (α × List σ) × ℕ × ℕ → Option σ :=
  fun p =>
    let a := p.fst.fst;
    let IH := p.fst.snd;
    let n := p.snd.fst;
    let m := p.snd.snd;
    Option.bind (List.get? IH m) fun s =>
      Option.bind (List.get? IH (unpair m).fst) fun s₁ =>
        Option.map
          (fun s₂ =>
            bif bodd n then
              bif bodd (div2 n) then rf a (ofNat Code m, s)
              else pc a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
            else
              bif bodd (div2 n) then co a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂)
              else pr a (ofNat Code (unpair m).fst, ofNat Code (unpair m).snd, s₁, s₂))
          (List.get? IH (unpair m).snd)
this✝ : Computable 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 : Computable₂ G
a : α
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
m1 : (unpair m).fst < n + 4
m2 : (unpair m).snd < n + 4
⊢ (bif true then
      bif true then
        rf a
          (ofNat Code (div2 (div2 n)),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (div2 (div2 n))))
      else
        pc a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
    else
      bif true then
        co a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))
      else
        pr a
          (ofNat Code (unpair (div2 (div2 n))).fst, ofNat Code (unpair (div2 (div2 n))).snd,
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).fst),
            rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg))
              (fun cf cg hf hg => co a (cf, cg, hf, hg)) (fun cf cg hf hg => pc a (cf, cg, hf, hg))
              (fun cf hf => rf a (cf, hf)) (ofNat Code (unpair (div2 (div2 n))).snd))) =
    rec (z a) (s a) (l a) (r a) (fun cf cg hf hg => pr a (cf, cg, hf, hg)) (fun cf cg hf hg => co a (cf, cg, hf, hg))
      (fun cf cg hf hg => pc a (cf, cg, hf, hg)) (fun cf hf => rf a (cf, hf))
      (match true, true 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))))
[PROOFSTEP]
rfl
[GOAL]
cf cg : Code
a : ℕ
⊢ eval (prec cf cg) (Nat.pair a 0) = eval cf a
[PROOFSTEP]
rw [eval, Nat.unpaired, Nat.unpair_pair]
[GOAL]
cf cg : Code
a : ℕ
⊢ Nat.rec (eval cf (a, 0).fst)
      (fun y IH => do
        let i ← IH
        eval cg (Nat.pair (a, 0).fst (Nat.pair y i)))
      (a, 0).snd =
    eval cf a
[PROOFSTEP]
simp (config := { Lean.Meta.Simp.neutralConfig with proj := true }) only []
[GOAL]
cf cg : Code
a : ℕ
⊢ Nat.rec (eval cf a)
      (fun y IH => do
        let i ← IH
        eval cg (Nat.pair a (Nat.pair y i)))
      0 =
    eval cf a
[PROOFSTEP]
rw [Nat.rec_zero]
[GOAL]
cf cg : Code
a k : ℕ
⊢ eval (prec cf cg) (Nat.pair a (Nat.succ k)) = do
    let ih ← eval (prec cf cg) (Nat.pair a k)
    eval cg (Nat.pair a (Nat.pair k ih))
[PROOFSTEP]
rw [eval, Nat.unpaired, Part.bind_eq_bind, Nat.unpair_pair]
[GOAL]
cf cg : Code
a k : ℕ
⊢ Nat.rec (eval cf (a, Nat.succ k).fst)
      (fun y IH => do
        let i ← IH
        eval cg (Nat.pair (a, Nat.succ k).fst (Nat.pair y i)))
      (a, Nat.succ k).snd =
    Part.bind
      (unpaired
        (fun a n =>
          Nat.rec (eval cf a)
            (fun y IH => do
              let i ← IH
              eval cg (Nat.pair a (Nat.pair y i)))
            n)
        (Nat.pair a k))
      fun ih => eval cg (Nat.pair a (Nat.pair k ih))
[PROOFSTEP]
simp
[GOAL]
n m : ℕ
⊢ eval (Code.const (n + 1)) m = Part.some (n + 1)
[PROOFSTEP]
simp! [eval_const n m]
[GOAL]
n : ℕ
⊢ eval Code.id n = Part.some n
[PROOFSTEP]
simp! [Seq.seq]
[GOAL]
c : Code
n x : ℕ
⊢ eval (curry c n) x = eval c (Nat.pair n x)
[PROOFSTEP]
simp! [Seq.seq]
[GOAL]
n : ℕ
⊢ (fun b => comp succ (n, b).snd)^[id n] zero = Code.const n
[PROOFSTEP]
simp
[GOAL]
n : ℕ
⊢ (fun b => comp succ b)^[n] zero = Code.const n
[PROOFSTEP]
induction n
[GOAL]
case zero
⊢ (fun b => comp succ b)^[Nat.zero] zero = Code.const Nat.zero
[PROOFSTEP]
simp [*, Code.const, Function.iterate_succ', -Function.iterate_succ]
[GOAL]
case succ
n✝ : ℕ
n_ih✝ : (fun b => comp succ b)^[n✝] zero = Code.const n✝
⊢ (fun b => comp succ b)^[Nat.succ n✝] zero = Code.const (Nat.succ n✝)
[PROOFSTEP]
simp [*, Code.const, Function.iterate_succ', -Function.iterate_succ]
[GOAL]
c₁ c₂ : Code
n₁ n₂ : ℕ
h : curry c₁ n₁ = curry c₂ n₂
⊢ c₁ = c₂
[PROOFSTEP]
injection h
[GOAL]
c₁ c₂ : Code
n₁ n₂ : ℕ
h : curry c₁ n₁ = curry c₂ n₂
⊢ n₁ = n₂
[PROOFSTEP]
injection h with h₁ h₂
[GOAL]
c₁ c₂ : Code
n₁ n₂ : ℕ
h₁ : c₁ = c₂
h₂ : pair (Code.const n₁) Code.id = pair (Code.const n₂) Code.id
⊢ n₁ = n₂
[PROOFSTEP]
injection h₂ with h₃ h₄
[GOAL]
c₁ c₂ : Code
n₁ n₂ : ℕ
h₁ : c₁ = c₂
h₃ : Code.const n₁ = Code.const n₂
h₄ : Code.id = Code.id
⊢ n₁ = n₂
[PROOFSTEP]
exact const_inj h₃
[GOAL]
f : ℕ →. ℕ
h : Partrec f
⊢ ∃ c, eval c = f
[PROOFSTEP]
induction h
[GOAL]
case zero
f : ℕ →. ℕ
⊢ ∃ c, eval c = pure 0
case succ
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑Nat.succ
case left
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑fun n => (unpair n).fst
case right
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑fun n => (unpair n).snd
case pair
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c, eval c = fun n => Seq.seq (Nat.pair <$> f✝ n) fun x => g✝ n
case comp
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c, eval c = fun n => g✝ n >>= f✝
case prec
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c,
    eval c =
      unpaired fun a n =>
        Nat.rec (f✝ a)
          (fun y IH => do
            let i ← IH
            g✝ (Nat.pair a (Nat.pair y i)))
          n
case rfind
f f✝ : ℕ →. ℕ
a✝ : Partrec f✝
a_ih✝ : ∃ c, eval c = f✝
⊢ ∃ c, eval c = fun a => Nat.rfind fun n => (fun m => decide (m = 0)) <$> f✝ (Nat.pair a n)
[PROOFSTEP]
case zero => exact ⟨zero, rfl⟩
[GOAL]
f : ℕ →. ℕ
⊢ ∃ c, eval c = pure 0
[PROOFSTEP]
case zero => exact ⟨zero, rfl⟩
[GOAL]
f : ℕ →. ℕ
⊢ ∃ c, eval c = pure 0
[PROOFSTEP]
exact ⟨zero, rfl⟩
[GOAL]
case succ
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑Nat.succ
case left
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑fun n => (unpair n).fst
case right
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑fun n => (unpair n).snd
case pair
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c, eval c = fun n => Seq.seq (Nat.pair <$> f✝ n) fun x => g✝ n
case comp
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c, eval c = fun n => g✝ n >>= f✝
case prec
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c,
    eval c =
      unpaired fun a n =>
        Nat.rec (f✝ a)
          (fun y IH => do
            let i ← IH
            g✝ (Nat.pair a (Nat.pair y i)))
          n
case rfind
f f✝ : ℕ →. ℕ
a✝ : Partrec f✝
a_ih✝ : ∃ c, eval c = f✝
⊢ ∃ c, eval c = fun a => Nat.rfind fun n => (fun m => decide (m = 0)) <$> f✝ (Nat.pair a n)
[PROOFSTEP]
case succ => exact ⟨succ, rfl⟩
[GOAL]
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑Nat.succ
[PROOFSTEP]
case succ => exact ⟨succ, rfl⟩
[GOAL]
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑Nat.succ
[PROOFSTEP]
exact ⟨succ, rfl⟩
[GOAL]
case left
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑fun n => (unpair n).fst
case right
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑fun n => (unpair n).snd
case pair
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c, eval c = fun n => Seq.seq (Nat.pair <$> f✝ n) fun x => g✝ n
case comp
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c, eval c = fun n => g✝ n >>= f✝
case prec
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c,
    eval c =
      unpaired fun a n =>
        Nat.rec (f✝ a)
          (fun y IH => do
            let i ← IH
            g✝ (Nat.pair a (Nat.pair y i)))
          n
case rfind
f f✝ : ℕ →. ℕ
a✝ : Partrec f✝
a_ih✝ : ∃ c, eval c = f✝
⊢ ∃ c, eval c = fun a => Nat.rfind fun n => (fun m => decide (m = 0)) <$> f✝ (Nat.pair a n)
[PROOFSTEP]
case left => exact ⟨left, rfl⟩
[GOAL]
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑fun n => (unpair n).fst
[PROOFSTEP]
case left => exact ⟨left, rfl⟩
[GOAL]
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑fun n => (unpair n).fst
[PROOFSTEP]
exact ⟨left, rfl⟩
[GOAL]
case right
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑fun n => (unpair n).snd
case pair
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c, eval c = fun n => Seq.seq (Nat.pair <$> f✝ n) fun x => g✝ n
case comp
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c, eval c = fun n => g✝ n >>= f✝
case prec
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c,
    eval c =
      unpaired fun a n =>
        Nat.rec (f✝ a)
          (fun y IH => do
            let i ← IH
            g✝ (Nat.pair a (Nat.pair y i)))
          n
case rfind
f f✝ : ℕ →. ℕ
a✝ : Partrec f✝
a_ih✝ : ∃ c, eval c = f✝
⊢ ∃ c, eval c = fun a => Nat.rfind fun n => (fun m => decide (m = 0)) <$> f✝ (Nat.pair a n)
[PROOFSTEP]
case right => exact ⟨right, rfl⟩
[GOAL]
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑fun n => (unpair n).snd
[PROOFSTEP]
case right => exact ⟨right, rfl⟩
[GOAL]
f : ℕ →. ℕ
⊢ ∃ c, eval c = ↑fun n => (unpair n).snd
[PROOFSTEP]
exact ⟨right, rfl⟩
[GOAL]
case pair
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c, eval c = fun n => Seq.seq (Nat.pair <$> f✝ n) fun x => g✝ n
case comp
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c, eval c = fun n => g✝ n >>= f✝
case prec
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c,
    eval c =
      unpaired fun a n =>
        Nat.rec (f✝ a)
          (fun y IH => do
            let i ← IH
            g✝ (Nat.pair a (Nat.pair y i)))
          n
case rfind
f f✝ : ℕ →. ℕ
a✝ : Partrec f✝
a_ih✝ : ∃ c, eval c = f✝
⊢ ∃ c, eval c = fun a => Nat.rfind fun n => (fun m => decide (m = 0)) <$> f✝ (Nat.pair a n)
[PROOFSTEP]
case pair f g pf pg hf hg =>
  rcases hf with ⟨cf, rfl⟩; rcases hg with ⟨cg, rfl⟩
  exact ⟨pair cf cg, rfl⟩
[GOAL]
f✝ f g : ℕ →. ℕ
pf : Partrec f
pg : Partrec g
hf : ∃ c, eval c = f
hg : ∃ c, eval c = g
⊢ ∃ c, eval c = fun n => Seq.seq (Nat.pair <$> f n) fun x => g n
[PROOFSTEP]
case pair f g pf pg hf hg =>
  rcases hf with ⟨cf, rfl⟩; rcases hg with ⟨cg, rfl⟩
  exact ⟨pair cf cg, rfl⟩
[GOAL]
f✝ f g : ℕ →. ℕ
pf : Partrec f
pg : Partrec g
hf : ∃ c, eval c = f
hg : ∃ c, eval c = g
⊢ ∃ c, eval c = fun n => Seq.seq (Nat.pair <$> f n) fun x => g n
[PROOFSTEP]
rcases hf with ⟨cf, rfl⟩
[GOAL]
case intro
f g : ℕ →. ℕ
pg : Partrec g
hg : ∃ c, eval c = g
cf : Code
pf : Partrec (eval cf)
⊢ ∃ c, eval c = fun n => Seq.seq (Nat.pair <$> eval cf n) fun x => g n
[PROOFSTEP]
rcases hg with ⟨cg, rfl⟩
[GOAL]
case intro.intro
f : ℕ →. ℕ
cf : Code
pf : Partrec (eval cf)
cg : Code
pg : Partrec (eval cg)
⊢ ∃ c, eval c = fun n => Seq.seq (Nat.pair <$> eval cf n) fun x => eval cg n
[PROOFSTEP]
exact ⟨pair cf cg, rfl⟩
[GOAL]
case comp
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c, eval c = fun n => g✝ n >>= f✝
case prec
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c,
    eval c =
      unpaired fun a n =>
        Nat.rec (f✝ a)
          (fun y IH => do
            let i ← IH
            g✝ (Nat.pair a (Nat.pair y i)))
          n
case rfind
f f✝ : ℕ →. ℕ
a✝ : Partrec f✝
a_ih✝ : ∃ c, eval c = f✝
⊢ ∃ c, eval c = fun a => Nat.rfind fun n => (fun m => decide (m = 0)) <$> f✝ (Nat.pair a n)
[PROOFSTEP]
case comp f g pf pg hf hg =>
  rcases hf with ⟨cf, rfl⟩; rcases hg with ⟨cg, rfl⟩
  exact ⟨comp cf cg, rfl⟩
[GOAL]
f✝ f g : ℕ →. ℕ
pf : Partrec f
pg : Partrec g
hf : ∃ c, eval c = f
hg : ∃ c, eval c = g
⊢ ∃ c, eval c = fun n => g n >>= f
[PROOFSTEP]
case comp f g pf pg hf hg =>
  rcases hf with ⟨cf, rfl⟩; rcases hg with ⟨cg, rfl⟩
  exact ⟨comp cf cg, rfl⟩
[GOAL]
f✝ f g : ℕ →. ℕ
pf : Partrec f
pg : Partrec g
hf : ∃ c, eval c = f
hg : ∃ c, eval c = g
⊢ ∃ c, eval c = fun n => g n >>= f
[PROOFSTEP]
rcases hf with ⟨cf, rfl⟩
[GOAL]
case intro
f g : ℕ →. ℕ
pg : Partrec g
hg : ∃ c, eval c = g
cf : Code
pf : Partrec (eval cf)
⊢ ∃ c, eval c = fun n => g n >>= eval cf
[PROOFSTEP]
rcases hg with ⟨cg, rfl⟩
[GOAL]
case intro.intro
f : ℕ →. ℕ
cf : Code
pf : Partrec (eval cf)
cg : Code
pg : Partrec (eval cg)
⊢ ∃ c, eval c = fun n => eval cg n >>= eval cf
[PROOFSTEP]
exact ⟨comp cf cg, rfl⟩
[GOAL]
case prec
f f✝ g✝ : ℕ →. ℕ
a✝¹ : Partrec f✝
a✝ : Partrec g✝
a_ih✝¹ : ∃ c, eval c = f✝
a_ih✝ : ∃ c, eval c = g✝
⊢ ∃ c,
    eval c =
      unpaired fun a n =>
        Nat.rec (f✝ a)
          (fun y IH => do
            let i ← IH
            g✝ (Nat.pair a (Nat.pair y i)))
          n
case rfind
f f✝ : ℕ →. ℕ
a✝ : Partrec f✝
a_ih✝ : ∃ c, eval c = f✝
⊢ ∃ c, eval c = fun a => Nat.rfind fun n => (fun m => decide (m = 0)) <$> f✝ (Nat.pair a n)
[PROOFSTEP]
case prec f g pf pg hf hg =>
  rcases hf with ⟨cf, rfl⟩; rcases hg with ⟨cg, rfl⟩
  exact ⟨prec cf cg, rfl⟩
[GOAL]
f✝ f g : ℕ →. ℕ
pf : Partrec f
pg : Partrec g
hf : ∃ c, eval c = f
hg : ∃ c, eval c = g
⊢ ∃ c,
    eval c =
      unpaired fun a n =>
        Nat.rec (f a)
          (fun y IH => do
            let i ← IH
            g (Nat.pair a (Nat.pair y i)))
          n
[PROOFSTEP]
case prec f g pf pg hf hg =>
  rcases hf with ⟨cf, rfl⟩; rcases hg with ⟨cg, rfl⟩
  exact ⟨prec cf cg, rfl⟩
[GOAL]
f✝ f g : ℕ →. ℕ
pf : Partrec f
pg : Partrec g
hf : ∃ c, eval c = f
hg : ∃ c, eval c = g
⊢ ∃ c,
    eval c =
      unpaired fun a n =>
        Nat.rec (f a)
          (fun y IH => do
            let i ← IH
            g (Nat.pair a (Nat.pair y i)))
          n
[PROOFSTEP]
rcases hf with ⟨cf, rfl⟩
[GOAL]
case intro
f g : ℕ →. ℕ
pg : Partrec g
hg : ∃ c, eval c = g
cf : Code
pf : Partrec (eval cf)
⊢ ∃ c,
    eval c =
      unpaired fun a n =>
        Nat.rec (eval cf a)
          (fun y IH => do
            let i ← IH
            g (Nat.pair a (Nat.pair y i)))
          n
[PROOFSTEP]
rcases hg with ⟨cg, rfl⟩
[GOAL]
case intro.intro
f : ℕ →. ℕ
cf : Code
pf : Partrec (eval cf)
cg : Code
pg : Partrec (eval cg)
⊢ ∃ c,
    eval c =
      unpaired fun a n =>
        Nat.rec (eval cf a)
          (fun y IH => do
            let i ← IH
            eval cg (Nat.pair a (Nat.pair y i)))
          n
[PROOFSTEP]
exact ⟨prec cf cg, rfl⟩
[GOAL]
case rfind
f f✝ : ℕ →. ℕ
a✝ : Partrec f✝
a_ih✝ : ∃ c, eval c = f✝
⊢ ∃ c, eval c = fun a => Nat.rfind fun n => (fun m => decide (m = 0)) <$> f✝ (Nat.pair a n)
[PROOFSTEP]
case rfind f pf hf =>
  rcases hf with ⟨cf, rfl⟩
  refine' ⟨comp (rfind' cf) (pair Code.id zero), _⟩
  simp [eval, Seq.seq, pure, PFun.pure, Part.map_id']
[GOAL]
f✝ f : ℕ →. ℕ
pf : Partrec f
hf : ∃ c, eval c = f
⊢ ∃ c, eval c = fun a => Nat.rfind fun n => (fun m => decide (m = 0)) <$> f (Nat.pair a n)
[PROOFSTEP]
case rfind f pf hf =>
  rcases hf with ⟨cf, rfl⟩
  refine' ⟨comp (rfind' cf) (pair Code.id zero), _⟩
  simp [eval, Seq.seq, pure, PFun.pure, Part.map_id']
[GOAL]
f✝ f : ℕ →. ℕ
pf : Partrec f
hf : ∃ c, eval c = f
⊢ ∃ c, eval c = fun a => Nat.rfind fun n => (fun m => decide (m = 0)) <$> f (Nat.pair a n)
[PROOFSTEP]
rcases hf with ⟨cf, rfl⟩
[GOAL]
case intro
f : ℕ →. ℕ
cf : Code
pf : Partrec (eval cf)
⊢ ∃ c, eval c = fun a => Nat.rfind fun n => (fun m => decide (m = 0)) <$> eval cf (Nat.pair a n)
[PROOFSTEP]
refine' ⟨comp (rfind' cf) (pair Code.id zero), _⟩
[GOAL]
case intro
f : ℕ →. ℕ
cf : Code
pf : Partrec (eval cf)
⊢ eval (comp (rfind' cf) (pair Code.id zero)) = fun a =>
    Nat.rfind fun n => (fun m => decide (m = 0)) <$> eval cf (Nat.pair a n)
[PROOFSTEP]
simp [eval, Seq.seq, pure, PFun.pure, Part.map_id']
[GOAL]
f : ℕ →. ℕ
h : ∃ c, eval c = f
⊢ Partrec f
[PROOFSTEP]
rcases h with ⟨c, rfl⟩
[GOAL]
case intro
c : Code
⊢ Partrec (eval c)
[PROOFSTEP]
induction c
[GOAL]
case intro.zero
⊢ Partrec (eval zero)
case intro.succ
⊢ Partrec (eval succ)
case intro.left
⊢ Partrec (eval left)
case intro.right
⊢ Partrec (eval right)
case intro.pair
a✝¹ a✝ : Code
a_ih✝¹ : Partrec (eval a✝¹)
a_ih✝ : Partrec (eval a✝)
⊢ Partrec (eval (pair a✝¹ a✝))
case intro.comp
a✝¹ a✝ : Code
a_ih✝¹ : Partrec (eval a✝¹)
a_ih✝ : Partrec (eval a✝)
⊢ Partrec (eval (comp a✝¹ a✝))
case intro.prec
a✝¹ a✝ : Code
a_ih✝¹ : Partrec (eval a✝¹)
a_ih✝ : Partrec (eval a✝)
⊢ Partrec (eval (prec a✝¹ a✝))
case intro.rfind' a✝ : Code a_ih✝ : Partrec (eval a✝) ⊢ Partrec (eval (rfind' a✝))
[PROOFSTEP]
case zero => exact Nat.Partrec.zero
[GOAL]
⊢ Partrec (eval zero)
[PROOFSTEP]
case zero => exact Nat.Partrec.zero
[GOAL]
⊢ Partrec (eval zero)
[PROOFSTEP]
exact Nat.Partrec.zero
[GOAL]
case intro.succ
⊢ Partrec (eval succ)
case intro.left
⊢ Partrec (eval left)
case intro.right
⊢ Partrec (eval right)
case intro.pair
a✝¹ a✝ : Code
a_ih✝¹ : Partrec (eval a✝¹)
a_ih✝ : Partrec (eval a✝)
⊢ Partrec (eval (pair a✝¹ a✝))
case intro.comp
a✝¹ a✝ : Code
a_ih✝¹ : Partrec (eval a✝¹)
a_ih✝ : Partrec (eval a✝)
⊢ Partrec (eval (comp a✝¹ a✝))
case intro.prec
a✝¹ a✝ : Code
a_ih✝¹ : Partrec (eval a✝¹)
a_ih✝ : Partrec (eval a✝)
⊢ Partrec (eval (prec a✝¹ a✝))
case intro.rfind' a✝ : Code a_ih✝ : Partrec (eval a✝) ⊢ Partrec (eval (rfind' a✝))
[PROOFSTEP]
case succ => exact Nat.Partrec.succ
[GOAL]
⊢ Partrec (eval succ)
[PROOFSTEP]
case succ => exact Nat.Partrec.succ
[GOAL]
⊢ Partrec (eval succ)
[PROOFSTEP]
exact Nat.Partrec.succ
[GOAL]
case intro.left
⊢ Partrec (eval left)
case intro.right
⊢ Partrec (eval right)
case intro.pair
a✝¹ a✝ : Code
a_ih✝¹ : Partrec (eval a✝¹)
a_ih✝ : Partrec (eval a✝)
⊢ Partrec (eval (pair a✝¹ a✝))
case intro.comp
a✝¹ a✝ : Code
a_ih✝¹ : Partrec (eval a✝¹)
a_ih✝ : Partrec (eval a✝)
⊢ Partrec (eval (comp a✝¹ a✝))
case intro.prec
a✝¹ a✝ : Code
a_ih✝¹ : Partrec (eval a✝¹)
a_ih✝ : Partrec (eval a✝)
⊢ Partrec (eval (prec a✝¹ a✝))
case intro.rfind' a✝ : Code a_ih✝ : Partrec (eval a✝) ⊢ Partrec (eval (rfind' a✝))
[PROOFSTEP]
case left => exact Nat.Partrec.left
[GOAL]
⊢ Partrec (eval left)
[PROOFSTEP]
case left => exact Nat.Partrec.left
[GOAL]
⊢ Partrec (eval left)
[PROOFSTEP]
exact Nat.Partrec.left
[GOAL]
case intro.right
⊢ Partrec (eval right)
case intro.pair
a✝¹ a✝ : Code
a_ih✝¹ : Partrec (eval a✝¹)
a_ih✝ : Partrec (eval a✝)
⊢ Partrec (eval (pair a✝¹ a✝))
case intro.comp
a✝¹ a✝ : Code
a_ih✝¹ : Partrec (eval a✝¹)
a_ih✝ : Partrec (eval a✝)
⊢ Partrec (eval (comp a✝¹ a✝))
case intro.prec
a✝¹ a✝ : Code
a_ih✝¹ : Partrec (eval a✝¹)
a_ih✝ : Partrec (eval a✝)
⊢ Partrec (eval (prec a✝¹ a✝))
case intro.rfind' a✝ : Code a_ih✝ : Partrec (eval a✝) ⊢ Partrec (eval (rfind' a✝))
[PROOFSTEP]
case right => exact Nat.Partrec.right
[GOAL]
⊢ Partrec (eval right)
[PROOFSTEP]
case right => exact Nat.Partrec.right
[GOAL]
⊢ Partrec (eval right)
[PROOFSTEP]
exact Nat.Partrec.right
[GOAL]
case intro.pair
a✝¹ a✝ : Code
a_ih✝¹ : Partrec (eval a✝¹)
a_ih✝ : Partrec (eval a✝)
⊢ Partrec (eval (pair a✝¹ a✝))
case intro.comp
a✝¹ a✝ : Code
a_ih✝¹ : Partrec (eval a✝¹)
a_ih✝ : Partrec (eval a✝)
⊢ Partrec (eval (comp a✝¹ a✝))
case intro.prec
a✝¹ a✝ : Code
a_ih✝¹ : Partrec (eval a✝¹)
a_ih✝ : Partrec (eval a✝)
⊢ Partrec (eval (prec a✝¹ a✝))
case intro.rfind' a✝ : Code a_ih✝ : Partrec (eval a✝) ⊢ Partrec (eval (rfind' a✝))
[PROOFSTEP]
case pair cf cg pf pg => exact pf.pair pg
[GOAL]
cf cg : Code
pf : Partrec (eval cf)
pg : Partrec (eval cg)
⊢ Partrec (eval (pair cf cg))
[PROOFSTEP]
case pair cf cg pf pg => exact pf.pair pg
[GOAL]
cf cg : Code
pf : Partrec (eval cf)
pg : Partrec (eval cg)
⊢ Partrec (eval (pair cf cg))
[PROOFSTEP]
exact pf.pair pg
[GOAL]
case intro.comp
a✝¹ a✝ : Code
a_ih✝¹ : Partrec (eval a✝¹)
a_ih✝ : Partrec (eval a✝)
⊢ Partrec (eval (comp a✝¹ a✝))
case intro.prec
a✝¹ a✝ : Code
a_ih✝¹ : Partrec (eval a✝¹)
a_ih✝ : Partrec (eval a✝)
⊢ Partrec (eval (prec a✝¹ a✝))
case intro.rfind' a✝ : Code a_ih✝ : Partrec (eval a✝) ⊢ Partrec (eval (rfind' a✝))
[PROOFSTEP]
case comp cf cg pf pg => exact pf.comp pg
[GOAL]
cf cg : Code
pf : Partrec (eval cf)
pg : Partrec (eval cg)
⊢ Partrec (eval (comp cf cg))
[PROOFSTEP]
case comp cf cg pf pg => exact pf.comp pg
[GOAL]
cf cg : Code
pf : Partrec (eval cf)
pg : Partrec (eval cg)
⊢ Partrec (eval (comp cf cg))
[PROOFSTEP]
exact pf.comp pg
[GOAL]
case intro.prec
a✝¹ a✝ : Code
a_ih✝¹ : Partrec (eval a✝¹)
a_ih✝ : Partrec (eval a✝)
⊢ Partrec (eval (prec a✝¹ a✝))
case intro.rfind' a✝ : Code a_ih✝ : Partrec (eval a✝) ⊢ Partrec (eval (rfind' a✝))
[PROOFSTEP]
case prec cf cg pf pg => exact pf.prec pg
[GOAL]
cf cg : Code
pf : Partrec (eval cf)
pg : Partrec (eval cg)
⊢ Partrec (eval (prec cf cg))
[PROOFSTEP]
case prec cf cg pf pg => exact pf.prec pg
[GOAL]
cf cg : Code
pf : Partrec (eval cf)
pg : Partrec (eval cg)
⊢ Partrec (eval (prec cf cg))
[PROOFSTEP]
exact pf.prec pg
[GOAL]
case intro.rfind'
a✝ : Code
a_ih✝ : Partrec (eval a✝)
⊢ Partrec (eval (rfind' a✝))
[PROOFSTEP]
case rfind' cf pf => exact pf.rfind'
[GOAL]
cf : Code
pf : Partrec (eval cf)
⊢ Partrec (eval (rfind' cf))
[PROOFSTEP]
case rfind' cf pf => exact pf.rfind'
[GOAL]
cf : Code
pf : Partrec (eval cf)
⊢ Partrec (eval (rfind' cf))
[PROOFSTEP]
exact pf.rfind'
[GOAL]
k : ℕ
cf cg : Code
⊢ (invImage (fun a => PSigma.casesOn a fun k snd => (k, snd)) Prod.instWellFoundedRelationProd).1
    { fst := k + 1, snd := cf } { fst := Nat.succ k, snd := pair cf cg }
[PROOFSTEP]
{decreasing_with simp (config := { arith := true }) [Zero.zero]; done
}
[GOAL]
k : ℕ
cf cg : Code
⊢ (invImage (fun a => PSigma.casesOn a fun k snd => (k, snd)) Prod.instWellFoundedRelationProd).1
    { fst := k + 1, snd := cf } { fst := Nat.succ k, snd := pair cf cg }
[PROOFSTEP]
decreasing_with simp (config := { arith := true }) [Zero.zero]; done
[GOAL]
case h
k : ℕ
cf cg : Code
⊢ sizeOf cf < sizeOf (pair cf cg)
[PROOFSTEP]
simp (config := { arith := true }) [Zero.zero]
[GOAL]

[PROOFSTEP]
done
[GOAL]
k : ℕ
cf cg : Code
⊢ (invImage (fun a => PSigma.casesOn a fun k snd => (k, snd)) Prod.instWellFoundedRelationProd).1
    { fst := k + 1, snd := cg } { fst := Nat.succ k, snd := pair cf cg }
[PROOFSTEP]
{decreasing_with simp (config := { arith := true }) [Zero.zero]; done
}
[GOAL]
k : ℕ
cf cg : Code
⊢ (invImage (fun a => PSigma.casesOn a fun k snd => (k, snd)) Prod.instWellFoundedRelationProd).1
    { fst := k + 1, snd := cg } { fst := Nat.succ k, snd := pair cf cg }
[PROOFSTEP]
decreasing_with simp (config := { arith := true }) [Zero.zero]; done
[GOAL]
case h
k : ℕ
cf cg : Code
⊢ sizeOf cg < sizeOf (pair cf cg)
[PROOFSTEP]
simp (config := { arith := true }) [Zero.zero]
[GOAL]

[PROOFSTEP]
done
[GOAL]
k : ℕ
cf cg : Code
⊢ (invImage (fun a => PSigma.casesOn a fun k snd => (k, snd)) Prod.instWellFoundedRelationProd).1
    { fst := k + 1, snd := cg } { fst := Nat.succ k, snd := comp cf cg }
[PROOFSTEP]
{decreasing_with simp (config := { arith := true }) [Zero.zero]; done
}
[GOAL]
k : ℕ
cf cg : Code
⊢ (invImage (fun a => PSigma.casesOn a fun k snd => (k, snd)) Prod.instWellFoundedRelationProd).1
    { fst := k + 1, snd := cg } { fst := Nat.succ k, snd := comp cf cg }
[PROOFSTEP]
decreasing_with simp (config := { arith := true }) [Zero.zero]; done
[GOAL]
case h
k : ℕ
cf cg : Code
⊢ sizeOf cg < sizeOf (comp cf cg)
[PROOFSTEP]
simp (config := { arith := true }) [Zero.zero]
[GOAL]

[PROOFSTEP]
done
[GOAL]
k : ℕ
cf cg : Code
⊢ (invImage (fun a => PSigma.casesOn a fun k snd => (k, snd)) Prod.instWellFoundedRelationProd).1
    { fst := k + 1, snd := cf } { fst := Nat.succ k, snd := comp cf cg }
[PROOFSTEP]
{decreasing_with simp (config := { arith := true }) [Zero.zero]; done
}
[GOAL]
k : ℕ
cf cg : Code
⊢ (invImage (fun a => PSigma.casesOn a fun k snd => (k, snd)) Prod.instWellFoundedRelationProd).1
    { fst := k + 1, snd := cf } { fst := Nat.succ k, snd := comp cf cg }
[PROOFSTEP]
decreasing_with simp (config := { arith := true }) [Zero.zero]; done
[GOAL]
case h
k : ℕ
cf cg : Code
⊢ sizeOf cf < sizeOf (comp cf cg)
[PROOFSTEP]
simp (config := { arith := true }) [Zero.zero]
[GOAL]

[PROOFSTEP]
done
[GOAL]
k : ℕ
cf cg : Code
⊢ (invImage (fun a => PSigma.casesOn a fun k snd => (k, snd)) Prod.instWellFoundedRelationProd).1
    { fst := k + 1, snd := cf } { fst := Nat.succ k, snd := prec cf cg }
[PROOFSTEP]
{decreasing_with simp (config := { arith := true }) [Zero.zero]; done
}
[GOAL]
k : ℕ
cf cg : Code
⊢ (invImage (fun a => PSigma.casesOn a fun k snd => (k, snd)) Prod.instWellFoundedRelationProd).1
    { fst := k + 1, snd := cf } { fst := Nat.succ k, snd := prec cf cg }
[PROOFSTEP]
decreasing_with simp (config := { arith := true }) [Zero.zero]; done
[GOAL]
case h
k : ℕ
cf cg : Code
⊢ sizeOf cf < sizeOf (prec cf cg)
[PROOFSTEP]
simp (config := { arith := true }) [Zero.zero]
[GOAL]

[PROOFSTEP]
done
[GOAL]
k : ℕ
cf cg : Code
⊢ (invImage (fun a => PSigma.casesOn a fun k snd => (k, snd)) Prod.instWellFoundedRelationProd).1
    { fst := k, snd := prec cf cg } { fst := Nat.succ k, snd := prec cf cg }
[PROOFSTEP]
{decreasing_with simp (config := { arith := true }) [Zero.zero]; done
}
[GOAL]
k : ℕ
cf cg : Code
⊢ (invImage (fun a => PSigma.casesOn a fun k snd => (k, snd)) Prod.instWellFoundedRelationProd).1
    { fst := k, snd := prec cf cg } { fst := Nat.succ k, snd := prec cf cg }
[PROOFSTEP]
decreasing_with simp (config := { arith := true }) [Zero.zero]; done
[GOAL]
case h
k : ℕ
cf cg : Code
⊢ k < Nat.succ k
[PROOFSTEP]
simp (config := { arith := true }) [Zero.zero]
[GOAL]

[PROOFSTEP]
done
[GOAL]
k : ℕ
cf cg : Code
⊢ (invImage (fun a => PSigma.casesOn a fun k snd => (k, snd)) Prod.instWellFoundedRelationProd).1
    { fst := k + 1, snd := cg } { fst := Nat.succ k, snd := prec cf cg }
[PROOFSTEP]
{decreasing_with simp (config := { arith := true }) [Zero.zero]; done
}
[GOAL]
k : ℕ
cf cg : Code
⊢ (invImage (fun a => PSigma.casesOn a fun k snd => (k, snd)) Prod.instWellFoundedRelationProd).1
    { fst := k + 1, snd := cg } { fst := Nat.succ k, snd := prec cf cg }
[PROOFSTEP]
decreasing_with simp (config := { arith := true }) [Zero.zero]; done
[GOAL]
case h
k : ℕ
cf cg : Code
⊢ sizeOf cg < sizeOf (prec cf cg)
[PROOFSTEP]
simp (config := { arith := true }) [Zero.zero]
[GOAL]

[PROOFSTEP]
done
[GOAL]
k : ℕ
cf : Code
⊢ (invImage (fun a => PSigma.casesOn a fun k snd => (k, snd)) Prod.instWellFoundedRelationProd).1
    { fst := k + 1, snd := cf } { fst := Nat.succ k, snd := rfind' cf }
[PROOFSTEP]
{decreasing_with simp (config := { arith := true }) [Zero.zero]; done
}
[GOAL]
k : ℕ
cf : Code
⊢ (invImage (fun a => PSigma.casesOn a fun k snd => (k, snd)) Prod.instWellFoundedRelationProd).1
    { fst := k + 1, snd := cf } { fst := Nat.succ k, snd := rfind' cf }
[PROOFSTEP]
decreasing_with simp (config := { arith := true }) [Zero.zero]; done
[GOAL]
case h
k : ℕ
cf : Code
⊢ sizeOf cf < sizeOf (rfind' cf)
[PROOFSTEP]
simp (config := { arith := true }) [Zero.zero]
[GOAL]

[PROOFSTEP]
done
[GOAL]
k : ℕ
cf : Code
⊢ (invImage (fun a => PSigma.casesOn a fun k snd => (k, snd)) Prod.instWellFoundedRelationProd).1
    { fst := k, snd := rfind' cf } { fst := Nat.succ k, snd := rfind' cf }
[PROOFSTEP]
{decreasing_with simp (config := { arith := true }) [Zero.zero]; done
}
[GOAL]
k : ℕ
cf : Code
⊢ (invImage (fun a => PSigma.casesOn a fun k snd => (k, snd)) Prod.instWellFoundedRelationProd).1
    { fst := k, snd := rfind' cf } { fst := Nat.succ k, snd := rfind' cf }
[PROOFSTEP]
decreasing_with simp (config := { arith := true }) [Zero.zero]; done
[GOAL]
case h
k : ℕ
cf : Code
⊢ k < Nat.succ k
[PROOFSTEP]
simp (config := { arith := true }) [Zero.zero]
[GOAL]

[PROOFSTEP]
done
[GOAL]
c : Code
n x : ℕ
h : x ∈ evaln 0 c n
⊢ n < 0
[PROOFSTEP]
simp [evaln] at h 
[GOAL]
k : ℕ
c : Code
n x : ℕ
h : x ∈ evaln (k + 1) c n
⊢ n < k + 1
[PROOFSTEP]
suffices
  ∀ {o : Option ℕ},
    x ∈ do {
        guard (n ≤ k);
        o
        } →
      n < k + 1
  by cases c <;> rw [evaln] at h  <;> exact this h
[GOAL]
k : ℕ
c : Code
n x : ℕ
h : x ∈ evaln (k + 1) c n
this :
  ∀ {o : Option ℕ},
    (x ∈ do
        guard (n ≤ k)
        o) →
      n < k + 1
⊢ n < k + 1
[PROOFSTEP]
cases c
[GOAL]
case zero
k n x : ℕ
this :
  ∀ {o : Option ℕ},
    (x ∈ do
        guard (n ≤ k)
        o) →
      n < k + 1
h : x ∈ evaln (k + 1) zero n
⊢ n < k + 1
[PROOFSTEP]
rw [evaln] at h 
[GOAL]
case succ
k n x : ℕ
this :
  ∀ {o : Option ℕ},
    (x ∈ do
        guard (n ≤ k)
        o) →
      n < k + 1
h : x ∈ evaln (k + 1) succ n
⊢ n < k + 1
[PROOFSTEP]
rw [evaln] at h 
[GOAL]
case left
k n x : ℕ
this :
  ∀ {o : Option ℕ},
    (x ∈ do
        guard (n ≤ k)
        o) →
      n < k + 1
h : x ∈ evaln (k + 1) left n
⊢ n < k + 1
[PROOFSTEP]
rw [evaln] at h 
[GOAL]
case right
k n x : ℕ
this :
  ∀ {o : Option ℕ},
    (x ∈ do
        guard (n ≤ k)
        o) →
      n < k + 1
h : x ∈ evaln (k + 1) right n
⊢ n < k + 1
[PROOFSTEP]
rw [evaln] at h 
[GOAL]
case pair
k n x : ℕ
this :
  ∀ {o : Option ℕ},
    (x ∈ do
        guard (n ≤ k)
        o) →
      n < k + 1
a✝¹ a✝ : Code
h : x ∈ evaln (k + 1) (pair a✝¹ a✝) n
⊢ n < k + 1
[PROOFSTEP]
rw [evaln] at h 
[GOAL]
case comp
k n x : ℕ
this :
  ∀ {o : Option ℕ},
    (x ∈ do
        guard (n ≤ k)
        o) →
      n < k + 1
a✝¹ a✝ : Code
h : x ∈ evaln (k + 1) (comp a✝¹ a✝) n
⊢ n < k + 1
[PROOFSTEP]
rw [evaln] at h 
[GOAL]
case prec
k n x : ℕ
this :
  ∀ {o : Option ℕ},
    (x ∈ do
        guard (n ≤ k)
        o) →
      n < k + 1
a✝¹ a✝ : Code
h : x ∈ evaln (k + 1) (prec a✝¹ a✝) n
⊢ n < k + 1
[PROOFSTEP]
rw [evaln] at h 
[GOAL]
case rfind'
k n x : ℕ
this :
  ∀ {o : Option ℕ},
    (x ∈ do
        guard (n ≤ k)
        o) →
      n < k + 1
a✝ : Code
h : x ∈ evaln (k + 1) (rfind' a✝) n
⊢ n < k + 1
[PROOFSTEP]
rw [evaln] at h 
[GOAL]
case zero
k n x : ℕ
this :
  ∀ {o : Option ℕ},
    (x ∈ do
        guard (n ≤ k)
        o) →
      n < k + 1
h :
  x ∈
    (fun n => do
        guard (n ≤ k)
        pure 0)
      n
⊢ n < k + 1
[PROOFSTEP]
exact this h
[GOAL]
case succ
k n x : ℕ
this :
  ∀ {o : Option ℕ},
    (x ∈ do
        guard (n ≤ k)
        o) →
      n < k + 1
h :
  x ∈
    (fun n => do
        guard (n ≤ k)
        pure (Nat.succ n))
      n
⊢ n < k + 1
[PROOFSTEP]
exact this h
[GOAL]
case left
k n x : ℕ
this :
  ∀ {o : Option ℕ},
    (x ∈ do
        guard (n ≤ k)
        o) →
      n < k + 1
h :
  x ∈
    (fun n => do
        guard (n ≤ k)
        pure (unpair n).fst)
      n
⊢ n < k + 1
[PROOFSTEP]
exact this h
[GOAL]
case right
k n x : ℕ
this :
  ∀ {o : Option ℕ},
    (x ∈ do
        guard (n ≤ k)
        o) →
      n < k + 1
h :
  x ∈
    (fun n => do
        guard (n ≤ k)
        pure (unpair n).snd)
      n
⊢ n < k + 1
[PROOFSTEP]
exact this h
[GOAL]
case pair
k n x : ℕ
this :
  ∀ {o : Option ℕ},
    (x ∈ do
        guard (n ≤ k)
        o) →
      n < k + 1
a✝¹ a✝ : Code
h :
  x ∈
    (fun n => do
        guard (n ≤ k)
        Seq.seq (Nat.pair <$> evaln (k + 1) a✝¹ n) fun x => evaln (k + 1) a✝ n)
      n
⊢ n < k + 1
[PROOFSTEP]
exact this h
[GOAL]
case comp
k n x : ℕ
this :
  ∀ {o : Option ℕ},
    (x ∈ do
        guard (n ≤ k)
        o) →
      n < k + 1
a✝¹ a✝ : Code
h :
  x ∈
    (fun n => do
        guard (n ≤ k)
        let x ← evaln (k + 1) a✝ n
        evaln (k + 1) a✝¹ x)
      n
⊢ n < k + 1
[PROOFSTEP]
exact this h
[GOAL]
case prec
k n x : ℕ
this :
  ∀ {o : Option ℕ},
    (x ∈ do
        guard (n ≤ k)
        o) →
      n < k + 1
a✝¹ a✝ : Code
h :
  x ∈
    (fun n => do
        guard (n ≤ k)
        unpaired
            (fun a n =>
              Nat.casesOn n (evaln (k + 1) a✝¹ a) fun y => do
                let i ← evaln k (prec a✝¹ a✝) (Nat.pair a y)
                evaln (k + 1) a✝ (Nat.pair a (Nat.pair y i)))
            n)
      n
⊢ n < k + 1
[PROOFSTEP]
exact this h
[GOAL]
case rfind'
k n x : ℕ
this :
  ∀ {o : Option ℕ},
    (x ∈ do
        guard (n ≤ k)
        o) →
      n < k + 1
a✝ : Code
h :
  x ∈
    (fun n => do
        guard (n ≤ k)
        unpaired
            (fun a m => do
              let x ← evaln (k + 1) a✝ (Nat.pair a m)
              if x = 0 then pure m else evaln k (rfind' a✝) (Nat.pair a (m + 1)))
            n)
      n
⊢ n < k + 1
[PROOFSTEP]
exact this h
[GOAL]
k : ℕ
c : Code
n x : ℕ
h : x ∈ evaln (k + 1) c n
⊢ ∀ {o : Option ℕ},
    (x ∈ do
        guard (n ≤ k)
        o) →
      n < k + 1
[PROOFSTEP]
simpa [Bind.bind] using Nat.lt_succ_of_le
[GOAL]
k₂ : ℕ
c : Code
n x : ℕ
x✝ : 0 ≤ k₂
h : x ∈ evaln 0 c n
⊢ x ∈ evaln k₂ c n
[PROOFSTEP]
simp [evaln] at h 
[GOAL]
k k₂ : ℕ
c : Code
n x : ℕ
hl : k + 1 ≤ k₂ + 1
h : x ∈ evaln (k + 1) c n
⊢ x ∈ evaln (k₂ + 1) c n
[PROOFSTEP]
have hl' := Nat.le_of_succ_le_succ hl
[GOAL]
k k₂ : ℕ
c : Code
n x : ℕ
hl : k + 1 ≤ k₂ + 1
h : x ∈ evaln (k + 1) c n
hl' : k ≤ k₂
⊢ x ∈ evaln (k₂ + 1) c n
[PROOFSTEP]
have :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        x ∈ do {
            guard (n ≤ k);
            o₁
            } →
          x ∈ do {
            guard (n ≤ k₂);
            o₂
            } :=
  by
  simp [Bind.bind]
  introv h h₁ h₂ h₃
  exact ⟨le_trans h₂ h, h₁ h₃⟩
[GOAL]
k k₂ : ℕ
c : Code
n x : ℕ
hl : k + 1 ≤ k₂ + 1
h : x ∈ evaln (k + 1) c n
hl' : k ≤ k₂
⊢ ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
[PROOFSTEP]
simp [Bind.bind]
[GOAL]
k k₂ : ℕ
c : Code
n x : ℕ
hl : k + 1 ≤ k₂ + 1
h : x ∈ evaln (k + 1) c n
hl' : k ≤ k₂
⊢ ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ}, k ≤ k₂ → (o₁ = some x → o₂ = some x) → n ≤ k → o₁ = some x → n ≤ k₂ ∧ o₂ = some x
[PROOFSTEP]
introv h h₁ h₂ h₃
[GOAL]
k✝ k₂✝ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k✝ + 1 ≤ k₂✝ + 1
h✝ : x✝ ∈ evaln (k✝ + 1) c n✝
hl' : k✝ ≤ k₂✝
k k₂ n x : ℕ
o₁ o₂ : Option ℕ
h : k ≤ k₂
h₁ : o₁ = some x → o₂ = some x
h₂ : n ≤ k
h₃ : o₁ = some x
⊢ n ≤ k₂ ∧ o₂ = some x
[PROOFSTEP]
exact ⟨le_trans h₂ h, h₁ h₃⟩
[GOAL]
k k₂ : ℕ
c : Code
n x : ℕ
hl : k + 1 ≤ k₂ + 1
h : x ∈ evaln (k + 1) c n
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
⊢ x ∈ evaln (k₂ + 1) c n
[PROOFSTEP]
simp at h ⊢
[GOAL]
k k₂ : ℕ
c : Code
n x : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h : evaln (k + 1) c n = some x
⊢ evaln (k₂ + 1) c n = some x
[PROOFSTEP]
induction' c with cf cg hf hg cf cg hf hg cf cg hf hg cf hf generalizing x n
[GOAL]
case zero
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝ : evaln (k + 1) c n✝ = some x✝
n x : ℕ
h : evaln (k + 1) zero n = some x
⊢ evaln (k₂ + 1) zero n = some x
[PROOFSTEP]
rw [evaln] at h ⊢
[GOAL]
case succ
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝ : evaln (k + 1) c n✝ = some x✝
n x : ℕ
h : evaln (k + 1) succ n = some x
⊢ evaln (k₂ + 1) succ n = some x
[PROOFSTEP]
rw [evaln] at h ⊢
[GOAL]
case left
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝ : evaln (k + 1) c n✝ = some x✝
n x : ℕ
h : evaln (k + 1) left n = some x
⊢ evaln (k₂ + 1) left n = some x
[PROOFSTEP]
rw [evaln] at h ⊢
[GOAL]
case right
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝ : evaln (k + 1) c n✝ = some x✝
n x : ℕ
h : evaln (k + 1) right n = some x
⊢ evaln (k₂ + 1) right n = some x
[PROOFSTEP]
rw [evaln] at h ⊢
[GOAL]
case pair
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h : evaln (k + 1) (pair cf cg) n = some x
⊢ evaln (k₂ + 1) (pair cf cg) n = some x
[PROOFSTEP]
rw [evaln] at h ⊢
[GOAL]
case comp
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h : evaln (k + 1) (comp cf cg) n = some x
⊢ evaln (k₂ + 1) (comp cf cg) n = some x
[PROOFSTEP]
rw [evaln] at h ⊢
[GOAL]
case prec
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h : evaln (k + 1) (prec cf cg) n = some x
⊢ evaln (k₂ + 1) (prec cf cg) n = some x
[PROOFSTEP]
rw [evaln] at h ⊢
[GOAL]
case rfind'
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝ : evaln (k + 1) c n✝ = some x✝
cf : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
n x : ℕ
h : evaln (k + 1) (rfind' cf) n = some x
⊢ evaln (k₂ + 1) (rfind' cf) n = some x
[PROOFSTEP]
rw [evaln] at h ⊢
[GOAL]
case zero
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝ : evaln (k + 1) c n✝ = some x✝
n x : ℕ
h :
  (fun n => do
        guard (n ≤ k)
        pure 0)
      n =
    some x
⊢ (fun n => do
        guard (n ≤ k₂)
        pure 0)
      n =
    some x
[PROOFSTEP]
refine' this hl' (fun h => _) h
[GOAL]
case succ
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝ : evaln (k + 1) c n✝ = some x✝
n x : ℕ
h :
  (fun n => do
        guard (n ≤ k)
        pure (Nat.succ n))
      n =
    some x
⊢ (fun n => do
        guard (n ≤ k₂)
        pure (Nat.succ n))
      n =
    some x
[PROOFSTEP]
refine' this hl' (fun h => _) h
[GOAL]
case left
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝ : evaln (k + 1) c n✝ = some x✝
n x : ℕ
h :
  (fun n => do
        guard (n ≤ k)
        pure (unpair n).fst)
      n =
    some x
⊢ (fun n => do
        guard (n ≤ k₂)
        pure (unpair n).fst)
      n =
    some x
[PROOFSTEP]
refine' this hl' (fun h => _) h
[GOAL]
case right
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝ : evaln (k + 1) c n✝ = some x✝
n x : ℕ
h :
  (fun n => do
        guard (n ≤ k)
        pure (unpair n).snd)
      n =
    some x
⊢ (fun n => do
        guard (n ≤ k₂)
        pure (unpair n).snd)
      n =
    some x
[PROOFSTEP]
refine' this hl' (fun h => _) h
[GOAL]
case pair
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h :
  (fun n => do
        guard (n ≤ k)
        Seq.seq (Nat.pair <$> evaln (k + 1) cf n) fun x => evaln (k + 1) cg n)
      n =
    some x
⊢ (fun n => do
        guard (n ≤ k₂)
        Seq.seq (Nat.pair <$> evaln (k₂ + 1) cf n) fun x => evaln (k₂ + 1) cg n)
      n =
    some x
[PROOFSTEP]
refine' this hl' (fun h => _) h
[GOAL]
case comp
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h :
  (fun n => do
        guard (n ≤ k)
        let x ← evaln (k + 1) cg n
        evaln (k + 1) cf x)
      n =
    some x
⊢ (fun n => do
        guard (n ≤ k₂)
        let x ← evaln (k₂ + 1) cg n
        evaln (k₂ + 1) cf x)
      n =
    some x
[PROOFSTEP]
refine' this hl' (fun h => _) h
[GOAL]
case prec
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h :
  (fun n => do
        guard (n ≤ k)
        unpaired
            (fun a n =>
              Nat.casesOn n (evaln (k + 1) cf a) fun y => do
                let i ← evaln k (prec cf cg) (Nat.pair a y)
                evaln (k + 1) cg (Nat.pair a (Nat.pair y i)))
            n)
      n =
    some x
⊢ (fun n => do
        guard (n ≤ k₂)
        unpaired
            (fun a n =>
              Nat.casesOn n (evaln (k₂ + 1) cf a) fun y => do
                let i ← evaln k₂ (prec cf cg) (Nat.pair a y)
                evaln (k₂ + 1) cg (Nat.pair a (Nat.pair y i)))
            n)
      n =
    some x
[PROOFSTEP]
refine' this hl' (fun h => _) h
[GOAL]
case rfind'
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝ : evaln (k + 1) c n✝ = some x✝
cf : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
n x : ℕ
h :
  (fun n => do
        guard (n ≤ k)
        unpaired
            (fun a m => do
              let x ← evaln (k + 1) cf (Nat.pair a m)
              if x = 0 then pure m else evaln k (rfind' cf) (Nat.pair a (m + 1)))
            n)
      n =
    some x
⊢ (fun n => do
        guard (n ≤ k₂)
        unpaired
            (fun a m => do
              let x ← evaln (k₂ + 1) cf (Nat.pair a m)
              if x = 0 then pure m else evaln k₂ (rfind' cf) (Nat.pair a (m + 1)))
            n)
      n =
    some x
[PROOFSTEP]
refine' this hl' (fun h => _) h
[GOAL]
case zero
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        pure 0)
      n =
    some x
h : x ∈ pure 0
⊢ x ∈ pure 0
case succ
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        pure (Nat.succ n))
      n =
    some x
h : x ∈ pure (Nat.succ n)
⊢ x ∈ pure (Nat.succ n)
case left
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        pure (unpair n).fst)
      n =
    some x
h : x ∈ pure (unpair n).fst
⊢ x ∈ pure (unpair n).fst
case right
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        pure (unpair n).snd)
      n =
    some x
h : x ∈ pure (unpair n).snd
⊢ x ∈ pure (unpair n).snd
case pair
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        Seq.seq (Nat.pair <$> evaln (k + 1) cf n) fun x => evaln (k + 1) cg n)
      n =
    some x
h : x ∈ Seq.seq (Nat.pair <$> evaln (k + 1) cf n) fun x => evaln (k + 1) cg n
⊢ x ∈ Seq.seq (Nat.pair <$> evaln (k₂ + 1) cf n) fun x => evaln (k₂ + 1) cg n
case comp
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        let x ← evaln (k + 1) cg n
        evaln (k + 1) cf x)
      n =
    some x
h :
  x ∈ do
    let x ← evaln (k + 1) cg n
    evaln (k + 1) cf x
⊢ x ∈ do
    let x ← evaln (k₂ + 1) cg n
    evaln (k₂ + 1) cf x
case prec
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        unpaired
            (fun a n =>
              Nat.casesOn n (evaln (k + 1) cf a) fun y => do
                let i ← evaln k (prec cf cg) (Nat.pair a y)
                evaln (k + 1) cg (Nat.pair a (Nat.pair y i)))
            n)
      n =
    some x
h :
  x ∈
    unpaired
      (fun a n =>
        Nat.casesOn n (evaln (k + 1) cf a) fun y => do
          let i ← evaln k (prec cf cg) (Nat.pair a y)
          evaln (k + 1) cg (Nat.pair a (Nat.pair y i)))
      n
⊢ x ∈
    unpaired
      (fun a n =>
        Nat.casesOn n (evaln (k₂ + 1) cf a) fun y => do
          let i ← evaln k₂ (prec cf cg) (Nat.pair a y)
          evaln (k₂ + 1) cg (Nat.pair a (Nat.pair y i)))
      n
case rfind'
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
cf : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        unpaired
            (fun a m => do
              let x ← evaln (k + 1) cf (Nat.pair a m)
              if x = 0 then pure m else evaln k (rfind' cf) (Nat.pair a (m + 1)))
            n)
      n =
    some x
h :
  x ∈
    unpaired
      (fun a m => do
        let x ← evaln (k + 1) cf (Nat.pair a m)
        if x = 0 then pure m else evaln k (rfind' cf) (Nat.pair a (m + 1)))
      n
⊢ x ∈
    unpaired
      (fun a m => do
        let x ← evaln (k₂ + 1) cf (Nat.pair a m)
        if x = 0 then pure m else evaln k₂ (rfind' cf) (Nat.pair a (m + 1)))
      n
[PROOFSTEP]
iterate 4 exact h
[GOAL]
case zero
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        pure 0)
      n =
    some x
h : x ∈ pure 0
⊢ x ∈ pure 0
case succ
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        pure (Nat.succ n))
      n =
    some x
h : x ∈ pure (Nat.succ n)
⊢ x ∈ pure (Nat.succ n)
case left
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        pure (unpair n).fst)
      n =
    some x
h : x ∈ pure (unpair n).fst
⊢ x ∈ pure (unpair n).fst
case right
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        pure (unpair n).snd)
      n =
    some x
h : x ∈ pure (unpair n).snd
⊢ x ∈ pure (unpair n).snd
case pair
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        Seq.seq (Nat.pair <$> evaln (k + 1) cf n) fun x => evaln (k + 1) cg n)
      n =
    some x
h : x ∈ Seq.seq (Nat.pair <$> evaln (k + 1) cf n) fun x => evaln (k + 1) cg n
⊢ x ∈ Seq.seq (Nat.pair <$> evaln (k₂ + 1) cf n) fun x => evaln (k₂ + 1) cg n
case comp
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        let x ← evaln (k + 1) cg n
        evaln (k + 1) cf x)
      n =
    some x
h :
  x ∈ do
    let x ← evaln (k + 1) cg n
    evaln (k + 1) cf x
⊢ x ∈ do
    let x ← evaln (k₂ + 1) cg n
    evaln (k₂ + 1) cf x
case prec
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        unpaired
            (fun a n =>
              Nat.casesOn n (evaln (k + 1) cf a) fun y => do
                let i ← evaln k (prec cf cg) (Nat.pair a y)
                evaln (k + 1) cg (Nat.pair a (Nat.pair y i)))
            n)
      n =
    some x
h :
  x ∈
    unpaired
      (fun a n =>
        Nat.casesOn n (evaln (k + 1) cf a) fun y => do
          let i ← evaln k (prec cf cg) (Nat.pair a y)
          evaln (k + 1) cg (Nat.pair a (Nat.pair y i)))
      n
⊢ x ∈
    unpaired
      (fun a n =>
        Nat.casesOn n (evaln (k₂ + 1) cf a) fun y => do
          let i ← evaln k₂ (prec cf cg) (Nat.pair a y)
          evaln (k₂ + 1) cg (Nat.pair a (Nat.pair y i)))
      n
case rfind'
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
cf : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        unpaired
            (fun a m => do
              let x ← evaln (k + 1) cf (Nat.pair a m)
              if x = 0 then pure m else evaln k (rfind' cf) (Nat.pair a (m + 1)))
            n)
      n =
    some x
h :
  x ∈
    unpaired
      (fun a m => do
        let x ← evaln (k + 1) cf (Nat.pair a m)
        if x = 0 then pure m else evaln k (rfind' cf) (Nat.pair a (m + 1)))
      n
⊢ x ∈
    unpaired
      (fun a m => do
        let x ← evaln (k₂ + 1) cf (Nat.pair a m)
        if x = 0 then pure m else evaln k₂ (rfind' cf) (Nat.pair a (m + 1)))
      n
[PROOFSTEP]
exact h
[GOAL]
case succ
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        pure (Nat.succ n))
      n =
    some x
h : x ∈ pure (Nat.succ n)
⊢ x ∈ pure (Nat.succ n)
case left
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        pure (unpair n).fst)
      n =
    some x
h : x ∈ pure (unpair n).fst
⊢ x ∈ pure (unpair n).fst
case right
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        pure (unpair n).snd)
      n =
    some x
h : x ∈ pure (unpair n).snd
⊢ x ∈ pure (unpair n).snd
case pair
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        Seq.seq (Nat.pair <$> evaln (k + 1) cf n) fun x => evaln (k + 1) cg n)
      n =
    some x
h : x ∈ Seq.seq (Nat.pair <$> evaln (k + 1) cf n) fun x => evaln (k + 1) cg n
⊢ x ∈ Seq.seq (Nat.pair <$> evaln (k₂ + 1) cf n) fun x => evaln (k₂ + 1) cg n
case comp
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        let x ← evaln (k + 1) cg n
        evaln (k + 1) cf x)
      n =
    some x
h :
  x ∈ do
    let x ← evaln (k + 1) cg n
    evaln (k + 1) cf x
⊢ x ∈ do
    let x ← evaln (k₂ + 1) cg n
    evaln (k₂ + 1) cf x
case prec
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        unpaired
            (fun a n =>
              Nat.casesOn n (evaln (k + 1) cf a) fun y => do
                let i ← evaln k (prec cf cg) (Nat.pair a y)
                evaln (k + 1) cg (Nat.pair a (Nat.pair y i)))
            n)
      n =
    some x
h :
  x ∈
    unpaired
      (fun a n =>
        Nat.casesOn n (evaln (k + 1) cf a) fun y => do
          let i ← evaln k (prec cf cg) (Nat.pair a y)
          evaln (k + 1) cg (Nat.pair a (Nat.pair y i)))
      n
⊢ x ∈
    unpaired
      (fun a n =>
        Nat.casesOn n (evaln (k₂ + 1) cf a) fun y => do
          let i ← evaln k₂ (prec cf cg) (Nat.pair a y)
          evaln (k₂ + 1) cg (Nat.pair a (Nat.pair y i)))
      n
case rfind'
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
cf : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        unpaired
            (fun a m => do
              let x ← evaln (k + 1) cf (Nat.pair a m)
              if x = 0 then pure m else evaln k (rfind' cf) (Nat.pair a (m + 1)))
            n)
      n =
    some x
h :
  x ∈
    unpaired
      (fun a m => do
        let x ← evaln (k + 1) cf (Nat.pair a m)
        if x = 0 then pure m else evaln k (rfind' cf) (Nat.pair a (m + 1)))
      n
⊢ x ∈
    unpaired
      (fun a m => do
        let x ← evaln (k₂ + 1) cf (Nat.pair a m)
        if x = 0 then pure m else evaln k₂ (rfind' cf) (Nat.pair a (m + 1)))
      n
[PROOFSTEP]
exact h
[GOAL]
case left
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        pure (unpair n).fst)
      n =
    some x
h : x ∈ pure (unpair n).fst
⊢ x ∈ pure (unpair n).fst
case right
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        pure (unpair n).snd)
      n =
    some x
h : x ∈ pure (unpair n).snd
⊢ x ∈ pure (unpair n).snd
case pair
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        Seq.seq (Nat.pair <$> evaln (k + 1) cf n) fun x => evaln (k + 1) cg n)
      n =
    some x
h : x ∈ Seq.seq (Nat.pair <$> evaln (k + 1) cf n) fun x => evaln (k + 1) cg n
⊢ x ∈ Seq.seq (Nat.pair <$> evaln (k₂ + 1) cf n) fun x => evaln (k₂ + 1) cg n
case comp
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        let x ← evaln (k + 1) cg n
        evaln (k + 1) cf x)
      n =
    some x
h :
  x ∈ do
    let x ← evaln (k + 1) cg n
    evaln (k + 1) cf x
⊢ x ∈ do
    let x ← evaln (k₂ + 1) cg n
    evaln (k₂ + 1) cf x
case prec
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        unpaired
            (fun a n =>
              Nat.casesOn n (evaln (k + 1) cf a) fun y => do
                let i ← evaln k (prec cf cg) (Nat.pair a y)
                evaln (k + 1) cg (Nat.pair a (Nat.pair y i)))
            n)
      n =
    some x
h :
  x ∈
    unpaired
      (fun a n =>
        Nat.casesOn n (evaln (k + 1) cf a) fun y => do
          let i ← evaln k (prec cf cg) (Nat.pair a y)
          evaln (k + 1) cg (Nat.pair a (Nat.pair y i)))
      n
⊢ x ∈
    unpaired
      (fun a n =>
        Nat.casesOn n (evaln (k₂ + 1) cf a) fun y => do
          let i ← evaln k₂ (prec cf cg) (Nat.pair a y)
          evaln (k₂ + 1) cg (Nat.pair a (Nat.pair y i)))
      n
case rfind'
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
cf : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        unpaired
            (fun a m => do
              let x ← evaln (k + 1) cf (Nat.pair a m)
              if x = 0 then pure m else evaln k (rfind' cf) (Nat.pair a (m + 1)))
            n)
      n =
    some x
h :
  x ∈
    unpaired
      (fun a m => do
        let x ← evaln (k + 1) cf (Nat.pair a m)
        if x = 0 then pure m else evaln k (rfind' cf) (Nat.pair a (m + 1)))
      n
⊢ x ∈
    unpaired
      (fun a m => do
        let x ← evaln (k₂ + 1) cf (Nat.pair a m)
        if x = 0 then pure m else evaln k₂ (rfind' cf) (Nat.pair a (m + 1)))
      n
[PROOFSTEP]
exact h
[GOAL]
case right
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        pure (unpair n).snd)
      n =
    some x
h : x ∈ pure (unpair n).snd
⊢ x ∈ pure (unpair n).snd
case pair
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        Seq.seq (Nat.pair <$> evaln (k + 1) cf n) fun x => evaln (k + 1) cg n)
      n =
    some x
h : x ∈ Seq.seq (Nat.pair <$> evaln (k + 1) cf n) fun x => evaln (k + 1) cg n
⊢ x ∈ Seq.seq (Nat.pair <$> evaln (k₂ + 1) cf n) fun x => evaln (k₂ + 1) cg n
case comp
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        let x ← evaln (k + 1) cg n
        evaln (k + 1) cf x)
      n =
    some x
h :
  x ∈ do
    let x ← evaln (k + 1) cg n
    evaln (k + 1) cf x
⊢ x ∈ do
    let x ← evaln (k₂ + 1) cg n
    evaln (k₂ + 1) cf x
case prec
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        unpaired
            (fun a n =>
              Nat.casesOn n (evaln (k + 1) cf a) fun y => do
                let i ← evaln k (prec cf cg) (Nat.pair a y)
                evaln (k + 1) cg (Nat.pair a (Nat.pair y i)))
            n)
      n =
    some x
h :
  x ∈
    unpaired
      (fun a n =>
        Nat.casesOn n (evaln (k + 1) cf a) fun y => do
          let i ← evaln k (prec cf cg) (Nat.pair a y)
          evaln (k + 1) cg (Nat.pair a (Nat.pair y i)))
      n
⊢ x ∈
    unpaired
      (fun a n =>
        Nat.casesOn n (evaln (k₂ + 1) cf a) fun y => do
          let i ← evaln k₂ (prec cf cg) (Nat.pair a y)
          evaln (k₂ + 1) cg (Nat.pair a (Nat.pair y i)))
      n
case rfind'
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
cf : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        unpaired
            (fun a m => do
              let x ← evaln (k + 1) cf (Nat.pair a m)
              if x = 0 then pure m else evaln k (rfind' cf) (Nat.pair a (m + 1)))
            n)
      n =
    some x
h :
  x ∈
    unpaired
      (fun a m => do
        let x ← evaln (k + 1) cf (Nat.pair a m)
        if x = 0 then pure m else evaln k (rfind' cf) (Nat.pair a (m + 1)))
      n
⊢ x ∈
    unpaired
      (fun a m => do
        let x ← evaln (k₂ + 1) cf (Nat.pair a m)
        if x = 0 then pure m else evaln k₂ (rfind' cf) (Nat.pair a (m + 1)))
      n
[PROOFSTEP]
exact h
[GOAL]
case pair
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        Seq.seq (Nat.pair <$> evaln (k + 1) cf n) fun x => evaln (k + 1) cg n)
      n =
    some x
h : x ∈ Seq.seq (Nat.pair <$> evaln (k + 1) cf n) fun x => evaln (k + 1) cg n
⊢ x ∈ Seq.seq (Nat.pair <$> evaln (k₂ + 1) cf n) fun x => evaln (k₂ + 1) cg n
[PROOFSTEP]
simp [Seq.seq] at h ⊢
[GOAL]
case pair
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        Seq.seq (Nat.pair <$> evaln (k + 1) cf n) fun x => evaln (k + 1) cg n)
      n =
    some x
h : ∃ a, evaln (k + 1) cf n = some a ∧ ∃ a_1, evaln (k + 1) cg n = some a_1 ∧ Nat.pair a a_1 = x
⊢ ∃ a, evaln (k₂ + 1) cf n = some a ∧ ∃ a_1, evaln (k₂ + 1) cg n = some a_1 ∧ Nat.pair a a_1 = x
[PROOFSTEP]
exact h.imp fun a => And.imp (hf _ _) <| Exists.imp fun b => And.imp_left (hg _ _)
[GOAL]
case comp
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        let x ← evaln (k + 1) cg n
        evaln (k + 1) cf x)
      n =
    some x
h :
  x ∈ do
    let x ← evaln (k + 1) cg n
    evaln (k + 1) cf x
⊢ x ∈ do
    let x ← evaln (k₂ + 1) cg n
    evaln (k₂ + 1) cf x
[PROOFSTEP]
simp [Bind.bind] at h ⊢
[GOAL]
case comp
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        let x ← evaln (k + 1) cg n
        evaln (k + 1) cf x)
      n =
    some x
h : ∃ a, evaln (k + 1) cg n = some a ∧ evaln (k + 1) cf a = some x
⊢ ∃ a, evaln (k₂ + 1) cg n = some a ∧ evaln (k₂ + 1) cf a = some x
[PROOFSTEP]
exact h.imp fun a => And.imp (hg _ _) (hf _ _)
[GOAL]
case prec
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        unpaired
            (fun a n =>
              Nat.casesOn n (evaln (k + 1) cf a) fun y => do
                let i ← evaln k (prec cf cg) (Nat.pair a y)
                evaln (k + 1) cg (Nat.pair a (Nat.pair y i)))
            n)
      n =
    some x
h :
  x ∈
    unpaired
      (fun a n =>
        Nat.casesOn n (evaln (k + 1) cf a) fun y => do
          let i ← evaln k (prec cf cg) (Nat.pair a y)
          evaln (k + 1) cg (Nat.pair a (Nat.pair y i)))
      n
⊢ x ∈
    unpaired
      (fun a n =>
        Nat.casesOn n (evaln (k₂ + 1) cf a) fun y => do
          let i ← evaln k₂ (prec cf cg) (Nat.pair a y)
          evaln (k₂ + 1) cg (Nat.pair a (Nat.pair y i)))
      n
[PROOFSTEP]
revert h
[GOAL]
case prec
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h :
  (fun n => do
        guard (n ≤ k)
        unpaired
            (fun a n =>
              Nat.casesOn n (evaln (k + 1) cf a) fun y => do
                let i ← evaln k (prec cf cg) (Nat.pair a y)
                evaln (k + 1) cg (Nat.pair a (Nat.pair y i)))
            n)
      n =
    some x
⊢ x ∈
      unpaired
        (fun a n =>
          Nat.casesOn n (evaln (k + 1) cf a) fun y => do
            let i ← evaln k (prec cf cg) (Nat.pair a y)
            evaln (k + 1) cg (Nat.pair a (Nat.pair y i)))
        n →
    x ∈
      unpaired
        (fun a n =>
          Nat.casesOn n (evaln (k₂ + 1) cf a) fun y => do
            let i ← evaln k₂ (prec cf cg) (Nat.pair a y)
            evaln (k₂ + 1) cg (Nat.pair a (Nat.pair y i)))
        n
[PROOFSTEP]
simp [Bind.bind]
[GOAL]
case prec
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h :
  (fun n => do
        guard (n ≤ k)
        unpaired
            (fun a n =>
              Nat.casesOn n (evaln (k + 1) cf a) fun y => do
                let i ← evaln k (prec cf cg) (Nat.pair a y)
                evaln (k + 1) cg (Nat.pair a (Nat.pair y i)))
            n)
      n =
    some x
⊢ Nat.rec (evaln (k + 1) cf (unpair n).fst)
        (fun n_1 n_ih =>
          Option.bind (evaln k (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
            evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
        (unpair n).snd =
      some x →
    Nat.rec (evaln (k₂ + 1) cf (unpair n).fst)
        (fun n_1 n_ih =>
          Option.bind (evaln k₂ (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
            evaln (k₂ + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
        (unpair n).snd =
      some x
[PROOFSTEP]
induction n.unpair.2
[GOAL]
case prec.zero
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h :
  (fun n => do
        guard (n ≤ k)
        unpaired
            (fun a n =>
              Nat.casesOn n (evaln (k + 1) cf a) fun y => do
                let i ← evaln k (prec cf cg) (Nat.pair a y)
                evaln (k + 1) cg (Nat.pair a (Nat.pair y i)))
            n)
      n =
    some x
⊢ Nat.rec (evaln (k + 1) cf (unpair n).fst)
        (fun n_1 n_ih =>
          Option.bind (evaln k (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
            evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
        Nat.zero =
      some x →
    Nat.rec (evaln (k₂ + 1) cf (unpair n).fst)
        (fun n_1 n_ih =>
          Option.bind (evaln k₂ (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
            evaln (k₂ + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
        Nat.zero =
      some x
[PROOFSTEP]
simp
[GOAL]
case prec.succ
k k₂ : ℕ
c : Code
n✝¹ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝ : evaln (k + 1) c n✝¹ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h :
  (fun n => do
        guard (n ≤ k)
        unpaired
            (fun a n =>
              Nat.casesOn n (evaln (k + 1) cf a) fun y => do
                let i ← evaln k (prec cf cg) (Nat.pair a y)
                evaln (k + 1) cg (Nat.pair a (Nat.pair y i)))
            n)
      n =
    some x
n✝ : ℕ
n_ih✝ :
  Nat.rec (evaln (k + 1) cf (unpair n).fst)
        (fun n_1 n_ih =>
          Option.bind (evaln k (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
            evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
        n✝ =
      some x →
    Nat.rec (evaln (k₂ + 1) cf (unpair n).fst)
        (fun n_1 n_ih =>
          Option.bind (evaln k₂ (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
            evaln (k₂ + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
        n✝ =
      some x
⊢ Nat.rec (evaln (k + 1) cf (unpair n).fst)
        (fun n_1 n_ih =>
          Option.bind (evaln k (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
            evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
        (Nat.succ n✝) =
      some x →
    Nat.rec (evaln (k₂ + 1) cf (unpair n).fst)
        (fun n_1 n_ih =>
          Option.bind (evaln k₂ (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
            evaln (k₂ + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
        (Nat.succ n✝) =
      some x
[PROOFSTEP]
simp
[GOAL]
case prec.zero
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝ : evaln (k + 1) c n✝ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h :
  (fun n => do
        guard (n ≤ k)
        unpaired
            (fun a n =>
              Nat.casesOn n (evaln (k + 1) cf a) fun y => do
                let i ← evaln k (prec cf cg) (Nat.pair a y)
                evaln (k + 1) cg (Nat.pair a (Nat.pair y i)))
            n)
      n =
    some x
⊢ evaln (k + 1) cf (unpair n).fst = some x → evaln (k₂ + 1) cf (unpair n).fst = some x
[PROOFSTEP]
apply hf
[GOAL]
case prec.succ
k k₂ : ℕ
c : Code
n✝¹ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝ : evaln (k + 1) c n✝¹ = some x✝
cf cg : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
hg : ∀ (n x : ℕ), evaln (k + 1) cg n = some x → evaln (k₂ + 1) cg n = some x
n x : ℕ
h :
  (fun n => do
        guard (n ≤ k)
        unpaired
            (fun a n =>
              Nat.casesOn n (evaln (k + 1) cf a) fun y => do
                let i ← evaln k (prec cf cg) (Nat.pair a y)
                evaln (k + 1) cg (Nat.pair a (Nat.pair y i)))
            n)
      n =
    some x
n✝ : ℕ
n_ih✝ :
  Nat.rec (evaln (k + 1) cf (unpair n).fst)
        (fun n_1 n_ih =>
          Option.bind (evaln k (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
            evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
        n✝ =
      some x →
    Nat.rec (evaln (k₂ + 1) cf (unpair n).fst)
        (fun n_1 n_ih =>
          Option.bind (evaln k₂ (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
            evaln (k₂ + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
        n✝ =
      some x
⊢ ∀ (x_1 : ℕ),
    evaln k (prec cf cg) (Nat.pair (unpair n).fst n✝) = some x_1 →
      evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair n✝ x_1)) = some x →
        ∃ a,
          evaln k₂ (prec cf cg) (Nat.pair (unpair n).fst n✝) = some a ∧
            evaln (k₂ + 1) cg (Nat.pair (unpair n).fst (Nat.pair n✝ a)) = some x
[PROOFSTEP]
exact fun y h₁ h₂ => ⟨y, evaln_mono hl' h₁, hg _ _ h₂⟩
[GOAL]
case rfind'
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
cf : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        unpaired
            (fun a m => do
              let x ← evaln (k + 1) cf (Nat.pair a m)
              if x = 0 then pure m else evaln k (rfind' cf) (Nat.pair a (m + 1)))
            n)
      n =
    some x
h :
  x ∈
    unpaired
      (fun a m => do
        let x ← evaln (k + 1) cf (Nat.pair a m)
        if x = 0 then pure m else evaln k (rfind' cf) (Nat.pair a (m + 1)))
      n
⊢ x ∈
    unpaired
      (fun a m => do
        let x ← evaln (k₂ + 1) cf (Nat.pair a m)
        if x = 0 then pure m else evaln k₂ (rfind' cf) (Nat.pair a (m + 1)))
      n
[PROOFSTEP]
simp [Bind.bind] at h ⊢
[GOAL]
case rfind'
k k₂ : ℕ
c : Code
n✝ x✝ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝
cf : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
n x : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        unpaired
            (fun a m => do
              let x ← evaln (k + 1) cf (Nat.pair a m)
              if x = 0 then pure m else evaln k (rfind' cf) (Nat.pair a (m + 1)))
            n)
      n =
    some x
h :
  ∃ a,
    evaln (k + 1) cf n = some a ∧
      (if a = 0 then pure (unpair n).snd else evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
        some x
⊢ ∃ a,
    evaln (k₂ + 1) cf n = some a ∧
      (if a = 0 then pure (unpair n).snd else evaln k₂ (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
        some x
[PROOFSTEP]
refine' h.imp fun x => And.imp (hf _ _) _
[GOAL]
case rfind'
k k₂ : ℕ
c : Code
n✝ x✝¹ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝¹
cf : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
n x✝ : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        unpaired
            (fun a m => do
              let x ← evaln (k + 1) cf (Nat.pair a m)
              if x = 0 then pure m else evaln k (rfind' cf) (Nat.pair a (m + 1)))
            n)
      n =
    some x✝
h :
  ∃ a,
    evaln (k + 1) cf n = some a ∧
      (if a = 0 then pure (unpair n).snd else evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
        some x✝
x : ℕ
⊢ (if x = 0 then pure (unpair n).snd else evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
      some x✝ →
    (if x = 0 then pure (unpair n).snd else evaln k₂ (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
      some x✝
[PROOFSTEP]
by_cases x0 : x = 0
[GOAL]
case pos
k k₂ : ℕ
c : Code
n✝ x✝¹ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝¹
cf : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
n x✝ : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        unpaired
            (fun a m => do
              let x ← evaln (k + 1) cf (Nat.pair a m)
              if x = 0 then pure m else evaln k (rfind' cf) (Nat.pair a (m + 1)))
            n)
      n =
    some x✝
h :
  ∃ a,
    evaln (k + 1) cf n = some a ∧
      (if a = 0 then pure (unpair n).snd else evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
        some x✝
x : ℕ
x0 : x = 0
⊢ (if x = 0 then pure (unpair n).snd else evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
      some x✝ →
    (if x = 0 then pure (unpair n).snd else evaln k₂ (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
      some x✝
[PROOFSTEP]
simp [x0]
[GOAL]
case neg
k k₂ : ℕ
c : Code
n✝ x✝¹ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝¹
cf : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
n x✝ : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        unpaired
            (fun a m => do
              let x ← evaln (k + 1) cf (Nat.pair a m)
              if x = 0 then pure m else evaln k (rfind' cf) (Nat.pair a (m + 1)))
            n)
      n =
    some x✝
h :
  ∃ a,
    evaln (k + 1) cf n = some a ∧
      (if a = 0 then pure (unpair n).snd else evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
        some x✝
x : ℕ
x0 : ¬x = 0
⊢ (if x = 0 then pure (unpair n).snd else evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
      some x✝ →
    (if x = 0 then pure (unpair n).snd else evaln k₂ (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
      some x✝
[PROOFSTEP]
simp [x0]
[GOAL]
case neg
k k₂ : ℕ
c : Code
n✝ x✝¹ : ℕ
hl : k + 1 ≤ k₂ + 1
hl' : k ≤ k₂
this :
  ∀ {k k₂ n x : ℕ} {o₁ o₂ : Option ℕ},
    k ≤ k₂ →
      (x ∈ o₁ → x ∈ o₂) →
        (x ∈ do
            guard (n ≤ k)
            o₁) →
          x ∈ do
            guard (n ≤ k₂)
            o₂
h✝¹ : evaln (k + 1) c n✝ = some x✝¹
cf : Code
hf : ∀ (n x : ℕ), evaln (k + 1) cf n = some x → evaln (k₂ + 1) cf n = some x
n x✝ : ℕ
h✝ :
  (fun n => do
        guard (n ≤ k)
        unpaired
            (fun a m => do
              let x ← evaln (k + 1) cf (Nat.pair a m)
              if x = 0 then pure m else evaln k (rfind' cf) (Nat.pair a (m + 1)))
            n)
      n =
    some x✝
h :
  ∃ a,
    evaln (k + 1) cf n = some a ∧
      (if a = 0 then pure (unpair n).snd else evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
        some x✝
x : ℕ
x0 : ¬x = 0
⊢ evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1)) = some x✝ →
    evaln k₂ (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1)) = some x✝
[PROOFSTEP]
exact evaln_mono hl'
[GOAL]
x✝ : Code
n x : ℕ
h : x ∈ evaln 0 x✝ n
⊢ x ∈ eval x✝ n
[PROOFSTEP]
simp [evaln] at h 
[GOAL]
k : ℕ
c : Code
n x : ℕ
h : x ∈ evaln (k + 1) c n
⊢ x ∈ eval c n
[PROOFSTEP]
induction' c with cf cg hf hg cf cg hf hg cf cg hf hg cf hf generalizing x n
[GOAL]
case zero
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
n x : ℕ
h : x ∈ evaln (k + 1) zero n
⊢ x ∈ eval zero n
[PROOFSTEP]
simp [eval, evaln, Bind.bind, Seq.seq] at h ⊢
[GOAL]
case succ
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
n x : ℕ
h : x ∈ evaln (k + 1) succ n
⊢ x ∈ eval succ n
[PROOFSTEP]
simp [eval, evaln, Bind.bind, Seq.seq] at h ⊢
[GOAL]
case left
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
n x : ℕ
h : x ∈ evaln (k + 1) left n
⊢ x ∈ eval left n
[PROOFSTEP]
simp [eval, evaln, Bind.bind, Seq.seq] at h ⊢
[GOAL]
case right
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
n x : ℕ
h : x ∈ evaln (k + 1) right n
⊢ x ∈ eval right n
[PROOFSTEP]
simp [eval, evaln, Bind.bind, Seq.seq] at h ⊢
[GOAL]
case pair
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x : ℕ
h : x ∈ evaln (k + 1) (pair cf cg) n
⊢ x ∈ eval (pair cf cg) n
[PROOFSTEP]
simp [eval, evaln, Bind.bind, Seq.seq] at h ⊢
[GOAL]
case comp
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x : ℕ
h : x ∈ evaln (k + 1) (comp cf cg) n
⊢ x ∈ eval (comp cf cg) n
[PROOFSTEP]
simp [eval, evaln, Bind.bind, Seq.seq] at h ⊢
[GOAL]
case prec
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x : ℕ
h : x ∈ evaln (k + 1) (prec cf cg) n
⊢ x ∈ eval (prec cf cg) n
[PROOFSTEP]
simp [eval, evaln, Bind.bind, Seq.seq] at h ⊢
[GOAL]
case rfind'
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
n x : ℕ
h : x ∈ evaln (k + 1) (rfind' cf) n
⊢ x ∈ eval (rfind' cf) n
[PROOFSTEP]
simp [eval, evaln, Bind.bind, Seq.seq] at h ⊢
[GOAL]
case zero
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
n x : ℕ
h : n ≤ k ∧ pure 0 = some x
⊢ x ∈ pure 0 n
[PROOFSTEP]
cases' h with _ h
[GOAL]
case succ
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
n x : ℕ
h : n ≤ k ∧ pure (Nat.succ n) = some x
⊢ x = Nat.succ n
[PROOFSTEP]
cases' h with _ h
[GOAL]
case left
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
n x : ℕ
h : n ≤ k ∧ pure (unpair n).fst = some x
⊢ x = (unpair n).fst
[PROOFSTEP]
cases' h with _ h
[GOAL]
case right
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
n x : ℕ
h : n ≤ k ∧ pure (unpair n).snd = some x
⊢ x = (unpair n).snd
[PROOFSTEP]
cases' h with _ h
[GOAL]
case pair
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x : ℕ
h : n ≤ k ∧ ∃ a, evaln (k + 1) cf n = some a ∧ ∃ a_1, evaln (k + 1) cg n = some a_1 ∧ Nat.pair a a_1 = x
⊢ ∃ a, a ∈ eval cf n ∧ ∃ a_1, a_1 ∈ eval cg n ∧ Nat.pair a a_1 = x
[PROOFSTEP]
cases' h with _ h
[GOAL]
case comp
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x : ℕ
h : n ≤ k ∧ ∃ a, evaln (k + 1) cg n = some a ∧ evaln (k + 1) cf a = some x
⊢ ∃ a, a ∈ eval cg n ∧ x ∈ eval cf a
[PROOFSTEP]
cases' h with _ h
[GOAL]
case prec
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x : ℕ
h :
  n ≤ k ∧
    Nat.rec (evaln (k + 1) cf (unpair n).fst)
        (fun n_1 n_ih =>
          Option.bind (evaln k (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
            evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
        (unpair n).snd =
      some x
⊢ x ∈
    Nat.rec (eval cf (unpair n).fst)
      (fun y IH => Part.bind IH fun i => eval cg (Nat.pair (unpair n).fst (Nat.pair y i))) (unpair n).snd
[PROOFSTEP]
cases' h with _ h
[GOAL]
case rfind'
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
n x : ℕ
h :
  n ≤ k ∧
    ∃ a,
      evaln (k + 1) cf n = some a ∧
        (if a = 0 then pure (unpair n).snd else evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
          some x
⊢ ∃ a,
    (0 ∈ eval cf (Nat.pair (unpair n).fst (a + (unpair n).snd)) ∧
        ∀ {m : ℕ}, m < a → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0) ∧
      a + (unpair n).snd = x
[PROOFSTEP]
cases' h with _ h
[GOAL]
case zero.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
n x : ℕ
left✝ : n ≤ k
h : pure 0 = some x
⊢ x ∈ pure 0 n
case succ.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
n x : ℕ
left✝ : n ≤ k
h : pure (Nat.succ n) = some x
⊢ x = Nat.succ n
case left.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
n x : ℕ
left✝ : n ≤ k
h : pure (unpair n).fst = some x
⊢ x = (unpair n).fst
case right.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
n x : ℕ
left✝ : n ≤ k
h : pure (unpair n).snd = some x
⊢ x = (unpair n).snd
case pair.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x : ℕ
left✝ : n ≤ k
h : ∃ a, evaln (k + 1) cf n = some a ∧ ∃ a_1, evaln (k + 1) cg n = some a_1 ∧ Nat.pair a a_1 = x
⊢ ∃ a, a ∈ eval cf n ∧ ∃ a_1, a_1 ∈ eval cg n ∧ Nat.pair a a_1 = x
case comp.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x : ℕ
left✝ : n ≤ k
h : ∃ a, evaln (k + 1) cg n = some a ∧ evaln (k + 1) cf a = some x
⊢ ∃ a, a ∈ eval cg n ∧ x ∈ eval cf a
case prec.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x : ℕ
left✝ : n ≤ k
h :
  Nat.rec (evaln (k + 1) cf (unpair n).fst)
      (fun n_1 n_ih =>
        Option.bind (evaln k (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
          evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
      (unpair n).snd =
    some x
⊢ x ∈
    Nat.rec (eval cf (unpair n).fst)
      (fun y IH => Part.bind IH fun i => eval cg (Nat.pair (unpair n).fst (Nat.pair y i))) (unpair n).snd
case rfind'.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
n x : ℕ
left✝ : n ≤ k
h :
  ∃ a,
    evaln (k + 1) cf n = some a ∧
      (if a = 0 then pure (unpair n).snd else evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
        some x
⊢ ∃ a,
    (0 ∈ eval cf (Nat.pair (unpair n).fst (a + (unpair n).snd)) ∧
        ∀ {m : ℕ}, m < a → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0) ∧
      a + (unpair n).snd = x
[PROOFSTEP]
iterate 4 simpa [pure, PFun.pure, eq_comm] using h
[GOAL]
case zero.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
n x : ℕ
left✝ : n ≤ k
h : pure 0 = some x
⊢ x ∈ pure 0 n
case succ.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
n x : ℕ
left✝ : n ≤ k
h : pure (Nat.succ n) = some x
⊢ x = Nat.succ n
case left.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
n x : ℕ
left✝ : n ≤ k
h : pure (unpair n).fst = some x
⊢ x = (unpair n).fst
case right.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
n x : ℕ
left✝ : n ≤ k
h : pure (unpair n).snd = some x
⊢ x = (unpair n).snd
case pair.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x : ℕ
left✝ : n ≤ k
h : ∃ a, evaln (k + 1) cf n = some a ∧ ∃ a_1, evaln (k + 1) cg n = some a_1 ∧ Nat.pair a a_1 = x
⊢ ∃ a, a ∈ eval cf n ∧ ∃ a_1, a_1 ∈ eval cg n ∧ Nat.pair a a_1 = x
case comp.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x : ℕ
left✝ : n ≤ k
h : ∃ a, evaln (k + 1) cg n = some a ∧ evaln (k + 1) cf a = some x
⊢ ∃ a, a ∈ eval cg n ∧ x ∈ eval cf a
case prec.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x : ℕ
left✝ : n ≤ k
h :
  Nat.rec (evaln (k + 1) cf (unpair n).fst)
      (fun n_1 n_ih =>
        Option.bind (evaln k (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
          evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
      (unpair n).snd =
    some x
⊢ x ∈
    Nat.rec (eval cf (unpair n).fst)
      (fun y IH => Part.bind IH fun i => eval cg (Nat.pair (unpair n).fst (Nat.pair y i))) (unpair n).snd
case rfind'.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
n x : ℕ
left✝ : n ≤ k
h :
  ∃ a,
    evaln (k + 1) cf n = some a ∧
      (if a = 0 then pure (unpair n).snd else evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
        some x
⊢ ∃ a,
    (0 ∈ eval cf (Nat.pair (unpair n).fst (a + (unpair n).snd)) ∧
        ∀ {m : ℕ}, m < a → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0) ∧
      a + (unpair n).snd = x
[PROOFSTEP]
simpa [pure, PFun.pure, eq_comm] using h
[GOAL]
case succ.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
n x : ℕ
left✝ : n ≤ k
h : pure (Nat.succ n) = some x
⊢ x = Nat.succ n
case left.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
n x : ℕ
left✝ : n ≤ k
h : pure (unpair n).fst = some x
⊢ x = (unpair n).fst
case right.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
n x : ℕ
left✝ : n ≤ k
h : pure (unpair n).snd = some x
⊢ x = (unpair n).snd
case pair.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x : ℕ
left✝ : n ≤ k
h : ∃ a, evaln (k + 1) cf n = some a ∧ ∃ a_1, evaln (k + 1) cg n = some a_1 ∧ Nat.pair a a_1 = x
⊢ ∃ a, a ∈ eval cf n ∧ ∃ a_1, a_1 ∈ eval cg n ∧ Nat.pair a a_1 = x
case comp.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x : ℕ
left✝ : n ≤ k
h : ∃ a, evaln (k + 1) cg n = some a ∧ evaln (k + 1) cf a = some x
⊢ ∃ a, a ∈ eval cg n ∧ x ∈ eval cf a
case prec.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x : ℕ
left✝ : n ≤ k
h :
  Nat.rec (evaln (k + 1) cf (unpair n).fst)
      (fun n_1 n_ih =>
        Option.bind (evaln k (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
          evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
      (unpair n).snd =
    some x
⊢ x ∈
    Nat.rec (eval cf (unpair n).fst)
      (fun y IH => Part.bind IH fun i => eval cg (Nat.pair (unpair n).fst (Nat.pair y i))) (unpair n).snd
case rfind'.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
n x : ℕ
left✝ : n ≤ k
h :
  ∃ a,
    evaln (k + 1) cf n = some a ∧
      (if a = 0 then pure (unpair n).snd else evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
        some x
⊢ ∃ a,
    (0 ∈ eval cf (Nat.pair (unpair n).fst (a + (unpair n).snd)) ∧
        ∀ {m : ℕ}, m < a → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0) ∧
      a + (unpair n).snd = x
[PROOFSTEP]
simpa [pure, PFun.pure, eq_comm] using h
[GOAL]
case left.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
n x : ℕ
left✝ : n ≤ k
h : pure (unpair n).fst = some x
⊢ x = (unpair n).fst
case right.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
n x : ℕ
left✝ : n ≤ k
h : pure (unpair n).snd = some x
⊢ x = (unpair n).snd
case pair.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x : ℕ
left✝ : n ≤ k
h : ∃ a, evaln (k + 1) cf n = some a ∧ ∃ a_1, evaln (k + 1) cg n = some a_1 ∧ Nat.pair a a_1 = x
⊢ ∃ a, a ∈ eval cf n ∧ ∃ a_1, a_1 ∈ eval cg n ∧ Nat.pair a a_1 = x
case comp.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x : ℕ
left✝ : n ≤ k
h : ∃ a, evaln (k + 1) cg n = some a ∧ evaln (k + 1) cf a = some x
⊢ ∃ a, a ∈ eval cg n ∧ x ∈ eval cf a
case prec.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x : ℕ
left✝ : n ≤ k
h :
  Nat.rec (evaln (k + 1) cf (unpair n).fst)
      (fun n_1 n_ih =>
        Option.bind (evaln k (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
          evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
      (unpair n).snd =
    some x
⊢ x ∈
    Nat.rec (eval cf (unpair n).fst)
      (fun y IH => Part.bind IH fun i => eval cg (Nat.pair (unpair n).fst (Nat.pair y i))) (unpair n).snd
case rfind'.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
n x : ℕ
left✝ : n ≤ k
h :
  ∃ a,
    evaln (k + 1) cf n = some a ∧
      (if a = 0 then pure (unpair n).snd else evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
        some x
⊢ ∃ a,
    (0 ∈ eval cf (Nat.pair (unpair n).fst (a + (unpair n).snd)) ∧
        ∀ {m : ℕ}, m < a → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0) ∧
      a + (unpair n).snd = x
[PROOFSTEP]
simpa [pure, PFun.pure, eq_comm] using h
[GOAL]
case right.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
n x : ℕ
left✝ : n ≤ k
h : pure (unpair n).snd = some x
⊢ x = (unpair n).snd
case pair.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x : ℕ
left✝ : n ≤ k
h : ∃ a, evaln (k + 1) cf n = some a ∧ ∃ a_1, evaln (k + 1) cg n = some a_1 ∧ Nat.pair a a_1 = x
⊢ ∃ a, a ∈ eval cf n ∧ ∃ a_1, a_1 ∈ eval cg n ∧ Nat.pair a a_1 = x
case comp.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x : ℕ
left✝ : n ≤ k
h : ∃ a, evaln (k + 1) cg n = some a ∧ evaln (k + 1) cf a = some x
⊢ ∃ a, a ∈ eval cg n ∧ x ∈ eval cf a
case prec.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x : ℕ
left✝ : n ≤ k
h :
  Nat.rec (evaln (k + 1) cf (unpair n).fst)
      (fun n_1 n_ih =>
        Option.bind (evaln k (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
          evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
      (unpair n).snd =
    some x
⊢ x ∈
    Nat.rec (eval cf (unpair n).fst)
      (fun y IH => Part.bind IH fun i => eval cg (Nat.pair (unpair n).fst (Nat.pair y i))) (unpair n).snd
case rfind'.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
n x : ℕ
left✝ : n ≤ k
h :
  ∃ a,
    evaln (k + 1) cf n = some a ∧
      (if a = 0 then pure (unpair n).snd else evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
        some x
⊢ ∃ a,
    (0 ∈ eval cf (Nat.pair (unpair n).fst (a + (unpair n).snd)) ∧
        ∀ {m : ℕ}, m < a → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0) ∧
      a + (unpair n).snd = x
[PROOFSTEP]
simpa [pure, PFun.pure, eq_comm] using h
[GOAL]
case pair.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x : ℕ
left✝ : n ≤ k
h : ∃ a, evaln (k + 1) cf n = some a ∧ ∃ a_1, evaln (k + 1) cg n = some a_1 ∧ Nat.pair a a_1 = x
⊢ ∃ a, a ∈ eval cf n ∧ ∃ a_1, a_1 ∈ eval cg n ∧ Nat.pair a a_1 = x
[PROOFSTEP]
rcases h with ⟨y, ef, z, eg, rfl⟩
[GOAL]
case pair.intro.intro.intro.intro.intro
k : ℕ
c : Code
n✝ x : ℕ
h : x ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n : ℕ
left✝ : n ≤ k
y : ℕ
ef : evaln (k + 1) cf n = some y
z : ℕ
eg : evaln (k + 1) cg n = some z
⊢ ∃ a, a ∈ eval cf n ∧ ∃ a_1, a_1 ∈ eval cg n ∧ Nat.pair a a_1 = Nat.pair y z
[PROOFSTEP]
exact ⟨_, hf _ _ ef, _, hg _ _ eg, rfl⟩
[GOAL]
case comp.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x : ℕ
left✝ : n ≤ k
h : ∃ a, evaln (k + 1) cg n = some a ∧ evaln (k + 1) cf a = some x
⊢ ∃ a, a ∈ eval cg n ∧ x ∈ eval cf a
[PROOFSTEP]
rcases h with ⟨y, eg, ef⟩
[GOAL]
case comp.intro.intro.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h : x✝ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x : ℕ
left✝ : n ≤ k
y : ℕ
eg : evaln (k + 1) cg n = some y
ef : evaln (k + 1) cf y = some x
⊢ ∃ a, a ∈ eval cg n ∧ x ∈ eval cf a
[PROOFSTEP]
exact ⟨_, hg _ _ eg, hf _ _ ef⟩
[GOAL]
case prec.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x : ℕ
left✝ : n ≤ k
h :
  Nat.rec (evaln (k + 1) cf (unpair n).fst)
      (fun n_1 n_ih =>
        Option.bind (evaln k (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
          evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
      (unpair n).snd =
    some x
⊢ x ∈
    Nat.rec (eval cf (unpair n).fst)
      (fun y IH => Part.bind IH fun i => eval cg (Nat.pair (unpair n).fst (Nat.pair y i))) (unpair n).snd
[PROOFSTEP]
revert h
[GOAL]
case prec.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h : x✝ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x : ℕ
left✝ : n ≤ k
⊢ Nat.rec (evaln (k + 1) cf (unpair n).fst)
        (fun n_1 n_ih =>
          Option.bind (evaln k (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
            evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
        (unpair n).snd =
      some x →
    x ∈
      Nat.rec (eval cf (unpair n).fst)
        (fun y IH => Part.bind IH fun i => eval cg (Nat.pair (unpair n).fst (Nat.pair y i))) (unpair n).snd
[PROOFSTEP]
induction' n.unpair.2 with m IH generalizing x
[GOAL]
case prec.intro.zero
k : ℕ
c : Code
n✝ x✝¹ : ℕ
h : x✝¹ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x✝ : ℕ
left✝ : n ≤ k
x : ℕ
⊢ Nat.rec (evaln (k + 1) cf (unpair n).fst)
        (fun n_1 n_ih =>
          Option.bind (evaln k (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
            evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
        Nat.zero =
      some x →
    x ∈
      Nat.rec (eval cf (unpair n).fst)
        (fun y IH => Part.bind IH fun i => eval cg (Nat.pair (unpair n).fst (Nat.pair y i))) Nat.zero
[PROOFSTEP]
simp
[GOAL]
case prec.intro.succ
k : ℕ
c : Code
n✝ x✝¹ : ℕ
h : x✝¹ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x✝ : ℕ
left✝ : n ≤ k
m : ℕ
IH :
  ∀ (x : ℕ),
    Nat.rec (evaln (k + 1) cf (unpair n).fst)
          (fun n_1 n_ih =>
            Option.bind (evaln k (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
              evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
          m =
        some x →
      x ∈
        Nat.rec (eval cf (unpair n).fst)
          (fun y IH => Part.bind IH fun i => eval cg (Nat.pair (unpair n).fst (Nat.pair y i))) m
x : ℕ
⊢ Nat.rec (evaln (k + 1) cf (unpair n).fst)
        (fun n_1 n_ih =>
          Option.bind (evaln k (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
            evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
        (Nat.succ m) =
      some x →
    x ∈
      Nat.rec (eval cf (unpair n).fst)
        (fun y IH => Part.bind IH fun i => eval cg (Nat.pair (unpair n).fst (Nat.pair y i))) (Nat.succ m)
[PROOFSTEP]
simp
[GOAL]
case prec.intro.zero
k : ℕ
c : Code
n✝ x✝¹ : ℕ
h : x✝¹ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x✝ : ℕ
left✝ : n ≤ k
x : ℕ
⊢ evaln (k + 1) cf (unpair n).fst = some x → x ∈ eval cf (unpair n).fst
[PROOFSTEP]
apply hf
[GOAL]
case prec.intro.succ
k : ℕ
c : Code
n✝ x✝¹ : ℕ
h : x✝¹ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x✝ : ℕ
left✝ : n ≤ k
m : ℕ
IH :
  ∀ (x : ℕ),
    Nat.rec (evaln (k + 1) cf (unpair n).fst)
          (fun n_1 n_ih =>
            Option.bind (evaln k (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
              evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
          m =
        some x →
      x ∈
        Nat.rec (eval cf (unpair n).fst)
          (fun y IH => Part.bind IH fun i => eval cg (Nat.pair (unpair n).fst (Nat.pair y i))) m
x : ℕ
⊢ ∀ (x_1 : ℕ),
    evaln k (prec cf cg) (Nat.pair (unpair n).fst m) = some x_1 →
      evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair m x_1)) = some x →
        ∃ a,
          a ∈
              Nat.rec (eval cf (unpair n).fst)
                (fun y IH => Part.bind IH fun i => eval cg (Nat.pair (unpair n).fst (Nat.pair y i))) m ∧
            x ∈ eval cg (Nat.pair (unpair n).fst (Nat.pair m a))
[PROOFSTEP]
refine' fun y h₁ h₂ => ⟨y, IH _ _, _⟩
[GOAL]
case prec.intro.succ.refine'_1
k : ℕ
c : Code
n✝ x✝¹ : ℕ
h : x✝¹ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x✝ : ℕ
left✝ : n ≤ k
m : ℕ
IH :
  ∀ (x : ℕ),
    Nat.rec (evaln (k + 1) cf (unpair n).fst)
          (fun n_1 n_ih =>
            Option.bind (evaln k (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
              evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
          m =
        some x →
      x ∈
        Nat.rec (eval cf (unpair n).fst)
          (fun y IH => Part.bind IH fun i => eval cg (Nat.pair (unpair n).fst (Nat.pair y i))) m
x y : ℕ
h₁ : evaln k (prec cf cg) (Nat.pair (unpair n).fst m) = some y
h₂ : evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair m y)) = some x
⊢ Nat.rec (evaln (k + 1) cf (unpair n).fst)
      (fun n_1 n_ih =>
        Option.bind (evaln k (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
          evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
      m =
    some y
[PROOFSTEP]
have := evaln_mono k.le_succ h₁
[GOAL]
case prec.intro.succ.refine'_1
k : ℕ
c : Code
n✝ x✝¹ : ℕ
h : x✝¹ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x✝ : ℕ
left✝ : n ≤ k
m : ℕ
IH :
  ∀ (x : ℕ),
    Nat.rec (evaln (k + 1) cf (unpair n).fst)
          (fun n_1 n_ih =>
            Option.bind (evaln k (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
              evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
          m =
        some x →
      x ∈
        Nat.rec (eval cf (unpair n).fst)
          (fun y IH => Part.bind IH fun i => eval cg (Nat.pair (unpair n).fst (Nat.pair y i))) m
x y : ℕ
h₁ : evaln k (prec cf cg) (Nat.pair (unpair n).fst m) = some y
h₂ : evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair m y)) = some x
this : y ∈ evaln (Nat.succ k) (prec cf cg) (Nat.pair (unpair n).fst m)
⊢ Nat.rec (evaln (k + 1) cf (unpair n).fst)
      (fun n_1 n_ih =>
        Option.bind (evaln k (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
          evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
      m =
    some y
[PROOFSTEP]
simp [evaln, Bind.bind] at this 
[GOAL]
case prec.intro.succ.refine'_1
k : ℕ
c : Code
n✝ x✝¹ : ℕ
h : x✝¹ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x✝ : ℕ
left✝ : n ≤ k
m : ℕ
IH :
  ∀ (x : ℕ),
    Nat.rec (evaln (k + 1) cf (unpair n).fst)
          (fun n_1 n_ih =>
            Option.bind (evaln k (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
              evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
          m =
        some x →
      x ∈
        Nat.rec (eval cf (unpair n).fst)
          (fun y IH => Part.bind IH fun i => eval cg (Nat.pair (unpair n).fst (Nat.pair y i))) m
x y : ℕ
h₁ : evaln k (prec cf cg) (Nat.pair (unpair n).fst m) = some y
h₂ : evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair m y)) = some x
this :
  Nat.pair (unpair n).fst m ≤ k ∧
    Nat.rec (evaln (k + 1) cf (unpair n).fst)
        (fun n_1 n_ih =>
          Option.bind (evaln k (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
            evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
        m =
      some y
⊢ Nat.rec (evaln (k + 1) cf (unpair n).fst)
      (fun n_1 n_ih =>
        Option.bind (evaln k (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
          evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
      m =
    some y
[PROOFSTEP]
exact this.2
[GOAL]
case prec.intro.succ.refine'_2
k : ℕ
c : Code
n✝ x✝¹ : ℕ
h : x✝¹ ∈ evaln (k + 1) c n✝
cf cg : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
hg : ∀ (n x : ℕ), x ∈ evaln (k + 1) cg n → x ∈ eval cg n
n x✝ : ℕ
left✝ : n ≤ k
m : ℕ
IH :
  ∀ (x : ℕ),
    Nat.rec (evaln (k + 1) cf (unpair n).fst)
          (fun n_1 n_ih =>
            Option.bind (evaln k (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
              evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
          m =
        some x →
      x ∈
        Nat.rec (eval cf (unpair n).fst)
          (fun y IH => Part.bind IH fun i => eval cg (Nat.pair (unpair n).fst (Nat.pair y i))) m
x y : ℕ
h₁ : evaln k (prec cf cg) (Nat.pair (unpair n).fst m) = some y
h₂ : evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair m y)) = some x
⊢ x ∈ eval cg (Nat.pair (unpair n).fst (Nat.pair m y))
[PROOFSTEP]
exact hg _ _ h₂
[GOAL]
case rfind'.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h✝ : x✝ ∈ evaln (k + 1) c n✝
cf : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
n x : ℕ
left✝ : n ≤ k
h :
  ∃ a,
    evaln (k + 1) cf n = some a ∧
      (if a = 0 then pure (unpair n).snd else evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
        some x
⊢ ∃ a,
    (0 ∈ eval cf (Nat.pair (unpair n).fst (a + (unpair n).snd)) ∧
        ∀ {m : ℕ}, m < a → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0) ∧
      a + (unpair n).snd = x
[PROOFSTEP]
rcases h with ⟨m, h₁, h₂⟩
[GOAL]
case rfind'.intro.intro.intro
k : ℕ
c : Code
n✝ x✝ : ℕ
h : x✝ ∈ evaln (k + 1) c n✝
cf : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
n x : ℕ
left✝ : n ≤ k
m : ℕ
h₁ : evaln (k + 1) cf n = some m
h₂ :
  (if m = 0 then pure (unpair n).snd else evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) = some x
⊢ ∃ a,
    (0 ∈ eval cf (Nat.pair (unpair n).fst (a + (unpair n).snd)) ∧
        ∀ {m : ℕ}, m < a → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0) ∧
      a + (unpair n).snd = x
[PROOFSTEP]
by_cases m0 : m = 0
[GOAL]
case pos
k : ℕ
c : Code
n✝ x✝ : ℕ
h : x✝ ∈ evaln (k + 1) c n✝
cf : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
n x : ℕ
left✝ : n ≤ k
m : ℕ
h₁ : evaln (k + 1) cf n = some m
h₂ :
  (if m = 0 then pure (unpair n).snd else evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) = some x
m0 : m = 0
⊢ ∃ a,
    (0 ∈ eval cf (Nat.pair (unpair n).fst (a + (unpair n).snd)) ∧
        ∀ {m : ℕ}, m < a → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0) ∧
      a + (unpair n).snd = x
[PROOFSTEP]
simp [m0] at h₂ 
[GOAL]
case neg
k : ℕ
c : Code
n✝ x✝ : ℕ
h : x✝ ∈ evaln (k + 1) c n✝
cf : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
n x : ℕ
left✝ : n ≤ k
m : ℕ
h₁ : evaln (k + 1) cf n = some m
h₂ :
  (if m = 0 then pure (unpair n).snd else evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) = some x
m0 : ¬m = 0
⊢ ∃ a,
    (0 ∈ eval cf (Nat.pair (unpair n).fst (a + (unpair n).snd)) ∧
        ∀ {m : ℕ}, m < a → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0) ∧
      a + (unpair n).snd = x
[PROOFSTEP]
simp [m0] at h₂ 
[GOAL]
case pos
k : ℕ
c : Code
n✝ x✝ : ℕ
h : x✝ ∈ evaln (k + 1) c n✝
cf : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
n x : ℕ
left✝ : n ≤ k
m : ℕ
h₁ : evaln (k + 1) cf n = some m
m0 : m = 0
h₂ : pure (unpair n).snd = some x
⊢ ∃ a,
    (0 ∈ eval cf (Nat.pair (unpair n).fst (a + (unpair n).snd)) ∧
        ∀ {m : ℕ}, m < a → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0) ∧
      a + (unpair n).snd = x
[PROOFSTEP]
exact ⟨0, ⟨by simpa [m0] using hf _ _ h₁, fun {m} => (Nat.not_lt_zero _).elim⟩, by injection h₂ with h₂; simp [h₂]⟩
[GOAL]
k : ℕ
c : Code
n✝ x✝ : ℕ
h : x✝ ∈ evaln (k + 1) c n✝
cf : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
n x : ℕ
left✝ : n ≤ k
m : ℕ
h₁ : evaln (k + 1) cf n = some m
m0 : m = 0
h₂ : pure (unpair n).snd = some x
⊢ 0 ∈ eval cf (Nat.pair (unpair n).fst (0 + (unpair n).snd))
[PROOFSTEP]
simpa [m0] using hf _ _ h₁
[GOAL]
k : ℕ
c : Code
n✝ x✝ : ℕ
h : x✝ ∈ evaln (k + 1) c n✝
cf : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
n x : ℕ
left✝ : n ≤ k
m : ℕ
h₁ : evaln (k + 1) cf n = some m
m0 : m = 0
h₂ : pure (unpair n).snd = some x
⊢ 0 + (unpair n).snd = x
[PROOFSTEP]
injection h₂ with h₂
[GOAL]
k : ℕ
c : Code
n✝ x✝ : ℕ
h : x✝ ∈ evaln (k + 1) c n✝
cf : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
n x : ℕ
left✝ : n ≤ k
m : ℕ
h₁ : evaln (k + 1) cf n = some m
m0 : m = 0
h₂ : (unpair n).snd = x
⊢ 0 + (unpair n).snd = x
[PROOFSTEP]
simp [h₂]
[GOAL]
case neg
k : ℕ
c : Code
n✝ x✝ : ℕ
h : x✝ ∈ evaln (k + 1) c n✝
cf : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
n x : ℕ
left✝ : n ≤ k
m : ℕ
h₁ : evaln (k + 1) cf n = some m
m0 : ¬m = 0
h₂ : evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1)) = some x
⊢ ∃ a,
    (0 ∈ eval cf (Nat.pair (unpair n).fst (a + (unpair n).snd)) ∧
        ∀ {m : ℕ}, m < a → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0) ∧
      a + (unpair n).snd = x
[PROOFSTEP]
have := evaln_sound h₂
[GOAL]
case neg
k : ℕ
c : Code
n✝ x✝ : ℕ
h : x✝ ∈ evaln (k + 1) c n✝
cf : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
n x : ℕ
left✝ : n ≤ k
m : ℕ
h₁ : evaln (k + 1) cf n = some m
m0 : ¬m = 0
h₂ : evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1)) = some x
this : x ∈ eval (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))
⊢ ∃ a,
    (0 ∈ eval cf (Nat.pair (unpair n).fst (a + (unpair n).snd)) ∧
        ∀ {m : ℕ}, m < a → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0) ∧
      a + (unpair n).snd = x
[PROOFSTEP]
simp [eval] at this 
[GOAL]
case neg
k : ℕ
c : Code
n✝ x✝ : ℕ
h : x✝ ∈ evaln (k + 1) c n✝
cf : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
n x : ℕ
left✝ : n ≤ k
m : ℕ
h₁ : evaln (k + 1) cf n = some m
m0 : ¬m = 0
h₂ : evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1)) = some x
this :
  ∃ a,
    (0 ∈ eval cf (Nat.pair (unpair n).fst (a + ((unpair n).snd + 1))) ∧
        ∀ {m : ℕ}, m < a → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + ((unpair n).snd + 1))) ∧ ¬a = 0) ∧
      a + ((unpair n).snd + 1) = x
⊢ ∃ a,
    (0 ∈ eval cf (Nat.pair (unpair n).fst (a + (unpair n).snd)) ∧
        ∀ {m : ℕ}, m < a → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0) ∧
      a + (unpair n).snd = x
[PROOFSTEP]
rcases this with ⟨y, ⟨hy₁, hy₂⟩, rfl⟩
[GOAL]
case neg.intro.intro.intro
k : ℕ
c : Code
n✝ x : ℕ
h : x ∈ evaln (k + 1) c n✝
cf : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
n : ℕ
left✝ : n ≤ k
m : ℕ
h₁ : evaln (k + 1) cf n = some m
m0 : ¬m = 0
y : ℕ
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y + ((unpair n).snd + 1)))
hy₂ : ∀ {m : ℕ}, m < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + ((unpair n).snd + 1))) ∧ ¬a = 0
h₂ : evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1)) = some (y + ((unpair n).snd + 1))
⊢ ∃ a,
    (0 ∈ eval cf (Nat.pair (unpair n).fst (a + (unpair n).snd)) ∧
        ∀ {m : ℕ}, m < a → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0) ∧
      a + (unpair n).snd = y + ((unpair n).snd + 1)
[PROOFSTEP]
refine' ⟨y + 1, ⟨by simpa [add_comm, add_left_comm] using hy₁, fun {i} im => _⟩, by simp [add_comm, add_left_comm]⟩
[GOAL]
k : ℕ
c : Code
n✝ x : ℕ
h : x ∈ evaln (k + 1) c n✝
cf : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
n : ℕ
left✝ : n ≤ k
m : ℕ
h₁ : evaln (k + 1) cf n = some m
m0 : ¬m = 0
y : ℕ
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y + ((unpair n).snd + 1)))
hy₂ : ∀ {m : ℕ}, m < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + ((unpair n).snd + 1))) ∧ ¬a = 0
h₂ : evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1)) = some (y + ((unpair n).snd + 1))
⊢ 0 ∈ eval cf (Nat.pair (unpair n).fst (y + 1 + (unpair n).snd))
[PROOFSTEP]
simpa [add_comm, add_left_comm] using hy₁
[GOAL]
k : ℕ
c : Code
n✝ x : ℕ
h : x ∈ evaln (k + 1) c n✝
cf : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
n : ℕ
left✝ : n ≤ k
m : ℕ
h₁ : evaln (k + 1) cf n = some m
m0 : ¬m = 0
y : ℕ
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y + ((unpair n).snd + 1)))
hy₂ : ∀ {m : ℕ}, m < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + ((unpair n).snd + 1))) ∧ ¬a = 0
h₂ : evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1)) = some (y + ((unpair n).snd + 1))
⊢ y + 1 + (unpair n).snd = y + ((unpair n).snd + 1)
[PROOFSTEP]
simp [add_comm, add_left_comm]
[GOAL]
case neg.intro.intro.intro
k : ℕ
c : Code
n✝ x : ℕ
h : x ∈ evaln (k + 1) c n✝
cf : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
n : ℕ
left✝ : n ≤ k
m : ℕ
h₁ : evaln (k + 1) cf n = some m
m0 : ¬m = 0
y : ℕ
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y + ((unpair n).snd + 1)))
hy₂ : ∀ {m : ℕ}, m < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + ((unpair n).snd + 1))) ∧ ¬a = 0
h₂ : evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1)) = some (y + ((unpair n).snd + 1))
i : ℕ
im : i < y + 1
⊢ ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (i + (unpair n).snd)) ∧ ¬a = 0
[PROOFSTEP]
cases' i with i
[GOAL]
case neg.intro.intro.intro.zero
k : ℕ
c : Code
n✝ x : ℕ
h : x ∈ evaln (k + 1) c n✝
cf : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
n : ℕ
left✝ : n ≤ k
m : ℕ
h₁ : evaln (k + 1) cf n = some m
m0 : ¬m = 0
y : ℕ
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y + ((unpair n).snd + 1)))
hy₂ : ∀ {m : ℕ}, m < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + ((unpair n).snd + 1))) ∧ ¬a = 0
h₂ : evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1)) = some (y + ((unpair n).snd + 1))
im : Nat.zero < y + 1
⊢ ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (Nat.zero + (unpair n).snd)) ∧ ¬a = 0
[PROOFSTEP]
exact ⟨m, by simpa using hf _ _ h₁, m0⟩
[GOAL]
k : ℕ
c : Code
n✝ x : ℕ
h : x ∈ evaln (k + 1) c n✝
cf : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
n : ℕ
left✝ : n ≤ k
m : ℕ
h₁ : evaln (k + 1) cf n = some m
m0 : ¬m = 0
y : ℕ
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y + ((unpair n).snd + 1)))
hy₂ : ∀ {m : ℕ}, m < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + ((unpair n).snd + 1))) ∧ ¬a = 0
h₂ : evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1)) = some (y + ((unpair n).snd + 1))
im : Nat.zero < y + 1
⊢ m ∈ eval cf (Nat.pair (unpair n).fst (Nat.zero + (unpair n).snd))
[PROOFSTEP]
simpa using hf _ _ h₁
[GOAL]
case neg.intro.intro.intro.succ
k : ℕ
c : Code
n✝ x : ℕ
h : x ∈ evaln (k + 1) c n✝
cf : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
n : ℕ
left✝ : n ≤ k
m : ℕ
h₁ : evaln (k + 1) cf n = some m
m0 : ¬m = 0
y : ℕ
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y + ((unpair n).snd + 1)))
hy₂ : ∀ {m : ℕ}, m < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + ((unpair n).snd + 1))) ∧ ¬a = 0
h₂ : evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1)) = some (y + ((unpair n).snd + 1))
i : ℕ
im : Nat.succ i < y + 1
⊢ ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (Nat.succ i + (unpair n).snd)) ∧ ¬a = 0
[PROOFSTEP]
rcases hy₂ (Nat.lt_of_succ_lt_succ im) with ⟨z, hz, z0⟩
[GOAL]
case neg.intro.intro.intro.succ.intro.intro
k : ℕ
c : Code
n✝ x : ℕ
h : x ∈ evaln (k + 1) c n✝
cf : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
n : ℕ
left✝ : n ≤ k
m : ℕ
h₁ : evaln (k + 1) cf n = some m
m0 : ¬m = 0
y : ℕ
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y + ((unpair n).snd + 1)))
hy₂ : ∀ {m : ℕ}, m < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + ((unpair n).snd + 1))) ∧ ¬a = 0
h₂ : evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1)) = some (y + ((unpair n).snd + 1))
i : ℕ
im : Nat.succ i < y + 1
z : ℕ
hz : z ∈ eval cf (Nat.pair (unpair n).fst (i + ((unpair n).snd + 1)))
z0 : ¬z = 0
⊢ ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (Nat.succ i + (unpair n).snd)) ∧ ¬a = 0
[PROOFSTEP]
exact ⟨z, by simpa [Nat.succ_eq_add_one, add_comm, add_left_comm] using hz, z0⟩
[GOAL]
k : ℕ
c : Code
n✝ x : ℕ
h : x ∈ evaln (k + 1) c n✝
cf : Code
hf : ∀ (n x : ℕ), x ∈ evaln (k + 1) cf n → x ∈ eval cf n
n : ℕ
left✝ : n ≤ k
m : ℕ
h₁ : evaln (k + 1) cf n = some m
m0 : ¬m = 0
y : ℕ
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y + ((unpair n).snd + 1)))
hy₂ : ∀ {m : ℕ}, m < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + ((unpair n).snd + 1))) ∧ ¬a = 0
h₂ : evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1)) = some (y + ((unpair n).snd + 1))
i : ℕ
im : Nat.succ i < y + 1
z : ℕ
hz : z ∈ eval cf (Nat.pair (unpair n).fst (i + ((unpair n).snd + 1)))
z0 : ¬z = 0
⊢ z ∈ eval cf (Nat.pair (unpair n).fst (Nat.succ i + (unpair n).snd))
[PROOFSTEP]
simpa [Nat.succ_eq_add_one, add_comm, add_left_comm] using hz
[GOAL]
c : Code
n x : ℕ
h : x ∈ eval c n
⊢ ∃ k, x ∈ evaln k c n
[PROOFSTEP]
rsuffices ⟨k, h⟩ : ∃ k, x ∈ evaln (k + 1) c n
[GOAL]
case intro
c : Code
n x : ℕ
h✝ : x ∈ eval c n
k : ℕ
h : x ∈ evaln (k + 1) c n
⊢ ∃ k, x ∈ evaln k c n
[PROOFSTEP]
exact ⟨k + 1, h⟩
[GOAL]
c : Code
n x : ℕ
h : x ∈ eval c n
⊢ ∃ k, x ∈ evaln (k + 1) c n
[PROOFSTEP]
induction c generalizing n x
[GOAL]
case zero
n x : ℕ
h : x ∈ eval zero n
⊢ ∃ k, x ∈ evaln (k + 1) zero n
[PROOFSTEP]
simp [eval, evaln, pure, PFun.pure, Seq.seq, Bind.bind] at h ⊢
[GOAL]
case succ
n x : ℕ
h : x ∈ eval succ n
⊢ ∃ k, x ∈ evaln (k + 1) succ n
[PROOFSTEP]
simp [eval, evaln, pure, PFun.pure, Seq.seq, Bind.bind] at h ⊢
[GOAL]
case left
n x : ℕ
h : x ∈ eval left n
⊢ ∃ k, x ∈ evaln (k + 1) left n
[PROOFSTEP]
simp [eval, evaln, pure, PFun.pure, Seq.seq, Bind.bind] at h ⊢
[GOAL]
case right
n x : ℕ
h : x ∈ eval right n
⊢ ∃ k, x ∈ evaln (k + 1) right n
[PROOFSTEP]
simp [eval, evaln, pure, PFun.pure, Seq.seq, Bind.bind] at h ⊢
[GOAL]
case pair
a✝¹ a✝ : Code
a_ih✝¹ : ∀ {n x : ℕ}, x ∈ eval a✝¹ n → ∃ k, x ∈ evaln (k + 1) a✝¹ n
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h : x ∈ eval (pair a✝¹ a✝) n
⊢ ∃ k, x ∈ evaln (k + 1) (pair a✝¹ a✝) n
[PROOFSTEP]
simp [eval, evaln, pure, PFun.pure, Seq.seq, Bind.bind] at h ⊢
[GOAL]
case comp
a✝¹ a✝ : Code
a_ih✝¹ : ∀ {n x : ℕ}, x ∈ eval a✝¹ n → ∃ k, x ∈ evaln (k + 1) a✝¹ n
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h : x ∈ eval (comp a✝¹ a✝) n
⊢ ∃ k, x ∈ evaln (k + 1) (comp a✝¹ a✝) n
[PROOFSTEP]
simp [eval, evaln, pure, PFun.pure, Seq.seq, Bind.bind] at h ⊢
[GOAL]
case prec
a✝¹ a✝ : Code
a_ih✝¹ : ∀ {n x : ℕ}, x ∈ eval a✝¹ n → ∃ k, x ∈ evaln (k + 1) a✝¹ n
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h : x ∈ eval (prec a✝¹ a✝) n
⊢ ∃ k, x ∈ evaln (k + 1) (prec a✝¹ a✝) n
[PROOFSTEP]
simp [eval, evaln, pure, PFun.pure, Seq.seq, Bind.bind] at h ⊢
[GOAL]
case rfind'
a✝ : Code
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h : x ∈ eval (rfind' a✝) n
⊢ ∃ k, x ∈ evaln (k + 1) (rfind' a✝) n
[PROOFSTEP]
simp [eval, evaln, pure, PFun.pure, Seq.seq, Bind.bind] at h ⊢
[GOAL]
case zero
n x : ℕ
h : x = 0
⊢ (∃ x, n ≤ x) ∧ 0 = x
case succ
n x : ℕ
h : x = Nat.succ n
⊢ (∃ x, n ≤ x) ∧ Nat.succ n = x
case left
n x : ℕ
h : x = (unpair n).fst
⊢ (∃ x, n ≤ x) ∧ (unpair n).fst = x
case right
n x : ℕ
h : x = (unpair n).snd
⊢ (∃ x, n ≤ x) ∧ (unpair n).snd = x
case pair
a✝¹ a✝ : Code
a_ih✝¹ : ∀ {n x : ℕ}, x ∈ eval a✝¹ n → ∃ k, x ∈ evaln (k + 1) a✝¹ n
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h : ∃ a, a ∈ eval a✝¹ n ∧ ∃ a_1, a_1 ∈ eval a✝ n ∧ Nat.pair a a_1 = x
⊢ ∃ k, n ≤ k ∧ ∃ a, evaln (k + 1) a✝¹ n = some a ∧ ∃ a_1, evaln (k + 1) a✝ n = some a_1 ∧ Nat.pair a a_1 = x
case comp
a✝¹ a✝ : Code
a_ih✝¹ : ∀ {n x : ℕ}, x ∈ eval a✝¹ n → ∃ k, x ∈ evaln (k + 1) a✝¹ n
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h : ∃ a, a ∈ eval a✝ n ∧ x ∈ eval a✝¹ a
⊢ ∃ k, n ≤ k ∧ ∃ a, evaln (k + 1) a✝ n = some a ∧ evaln (k + 1) a✝¹ a = some x
case prec
a✝¹ a✝ : Code
a_ih✝¹ : ∀ {n x : ℕ}, x ∈ eval a✝¹ n → ∃ k, x ∈ evaln (k + 1) a✝¹ n
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h :
  x ∈
    Nat.rec (eval a✝¹ (unpair n).fst)
      (fun y IH => Part.bind IH fun i => eval a✝ (Nat.pair (unpair n).fst (Nat.pair y i))) (unpair n).snd
⊢ ∃ k,
    n ≤ k ∧
      Nat.rec (evaln (k + 1) a✝¹ (unpair n).fst)
          (fun n_1 n_ih =>
            Option.bind (evaln k (prec a✝¹ a✝) (Nat.pair (unpair n).fst n_1)) fun i =>
              evaln (k + 1) a✝ (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
          (unpair n).snd =
        some x
case rfind'
a✝ : Code
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h :
  ∃ a,
    (0 ∈ eval a✝ (Nat.pair (unpair n).fst (a + (unpair n).snd)) ∧
        ∀ {m : ℕ}, m < a → ∃ a, a ∈ eval a✝ (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0) ∧
      a + (unpair n).snd = x
⊢ ∃ k,
    n ≤ k ∧
      ∃ a,
        evaln (k + 1) a✝ n = some a ∧
          (if a = 0 then some (unpair n).snd else evaln k (rfind' a✝) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
            some x
[PROOFSTEP]
iterate 4 exact ⟨⟨_, le_rfl⟩, h.symm⟩
[GOAL]
case zero
n x : ℕ
h : x = 0
⊢ (∃ x, n ≤ x) ∧ 0 = x
case succ
n x : ℕ
h : x = Nat.succ n
⊢ (∃ x, n ≤ x) ∧ Nat.succ n = x
case left
n x : ℕ
h : x = (unpair n).fst
⊢ (∃ x, n ≤ x) ∧ (unpair n).fst = x
case right
n x : ℕ
h : x = (unpair n).snd
⊢ (∃ x, n ≤ x) ∧ (unpair n).snd = x
case pair
a✝¹ a✝ : Code
a_ih✝¹ : ∀ {n x : ℕ}, x ∈ eval a✝¹ n → ∃ k, x ∈ evaln (k + 1) a✝¹ n
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h : ∃ a, a ∈ eval a✝¹ n ∧ ∃ a_1, a_1 ∈ eval a✝ n ∧ Nat.pair a a_1 = x
⊢ ∃ k, n ≤ k ∧ ∃ a, evaln (k + 1) a✝¹ n = some a ∧ ∃ a_1, evaln (k + 1) a✝ n = some a_1 ∧ Nat.pair a a_1 = x
case comp
a✝¹ a✝ : Code
a_ih✝¹ : ∀ {n x : ℕ}, x ∈ eval a✝¹ n → ∃ k, x ∈ evaln (k + 1) a✝¹ n
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h : ∃ a, a ∈ eval a✝ n ∧ x ∈ eval a✝¹ a
⊢ ∃ k, n ≤ k ∧ ∃ a, evaln (k + 1) a✝ n = some a ∧ evaln (k + 1) a✝¹ a = some x
case prec
a✝¹ a✝ : Code
a_ih✝¹ : ∀ {n x : ℕ}, x ∈ eval a✝¹ n → ∃ k, x ∈ evaln (k + 1) a✝¹ n
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h :
  x ∈
    Nat.rec (eval a✝¹ (unpair n).fst)
      (fun y IH => Part.bind IH fun i => eval a✝ (Nat.pair (unpair n).fst (Nat.pair y i))) (unpair n).snd
⊢ ∃ k,
    n ≤ k ∧
      Nat.rec (evaln (k + 1) a✝¹ (unpair n).fst)
          (fun n_1 n_ih =>
            Option.bind (evaln k (prec a✝¹ a✝) (Nat.pair (unpair n).fst n_1)) fun i =>
              evaln (k + 1) a✝ (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
          (unpair n).snd =
        some x
case rfind'
a✝ : Code
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h :
  ∃ a,
    (0 ∈ eval a✝ (Nat.pair (unpair n).fst (a + (unpair n).snd)) ∧
        ∀ {m : ℕ}, m < a → ∃ a, a ∈ eval a✝ (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0) ∧
      a + (unpair n).snd = x
⊢ ∃ k,
    n ≤ k ∧
      ∃ a,
        evaln (k + 1) a✝ n = some a ∧
          (if a = 0 then some (unpair n).snd else evaln k (rfind' a✝) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
            some x
[PROOFSTEP]
exact ⟨⟨_, le_rfl⟩, h.symm⟩
[GOAL]
case succ
n x : ℕ
h : x = Nat.succ n
⊢ (∃ x, n ≤ x) ∧ Nat.succ n = x
case left
n x : ℕ
h : x = (unpair n).fst
⊢ (∃ x, n ≤ x) ∧ (unpair n).fst = x
case right
n x : ℕ
h : x = (unpair n).snd
⊢ (∃ x, n ≤ x) ∧ (unpair n).snd = x
case pair
a✝¹ a✝ : Code
a_ih✝¹ : ∀ {n x : ℕ}, x ∈ eval a✝¹ n → ∃ k, x ∈ evaln (k + 1) a✝¹ n
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h : ∃ a, a ∈ eval a✝¹ n ∧ ∃ a_1, a_1 ∈ eval a✝ n ∧ Nat.pair a a_1 = x
⊢ ∃ k, n ≤ k ∧ ∃ a, evaln (k + 1) a✝¹ n = some a ∧ ∃ a_1, evaln (k + 1) a✝ n = some a_1 ∧ Nat.pair a a_1 = x
case comp
a✝¹ a✝ : Code
a_ih✝¹ : ∀ {n x : ℕ}, x ∈ eval a✝¹ n → ∃ k, x ∈ evaln (k + 1) a✝¹ n
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h : ∃ a, a ∈ eval a✝ n ∧ x ∈ eval a✝¹ a
⊢ ∃ k, n ≤ k ∧ ∃ a, evaln (k + 1) a✝ n = some a ∧ evaln (k + 1) a✝¹ a = some x
case prec
a✝¹ a✝ : Code
a_ih✝¹ : ∀ {n x : ℕ}, x ∈ eval a✝¹ n → ∃ k, x ∈ evaln (k + 1) a✝¹ n
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h :
  x ∈
    Nat.rec (eval a✝¹ (unpair n).fst)
      (fun y IH => Part.bind IH fun i => eval a✝ (Nat.pair (unpair n).fst (Nat.pair y i))) (unpair n).snd
⊢ ∃ k,
    n ≤ k ∧
      Nat.rec (evaln (k + 1) a✝¹ (unpair n).fst)
          (fun n_1 n_ih =>
            Option.bind (evaln k (prec a✝¹ a✝) (Nat.pair (unpair n).fst n_1)) fun i =>
              evaln (k + 1) a✝ (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
          (unpair n).snd =
        some x
case rfind'
a✝ : Code
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h :
  ∃ a,
    (0 ∈ eval a✝ (Nat.pair (unpair n).fst (a + (unpair n).snd)) ∧
        ∀ {m : ℕ}, m < a → ∃ a, a ∈ eval a✝ (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0) ∧
      a + (unpair n).snd = x
⊢ ∃ k,
    n ≤ k ∧
      ∃ a,
        evaln (k + 1) a✝ n = some a ∧
          (if a = 0 then some (unpair n).snd else evaln k (rfind' a✝) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
            some x
[PROOFSTEP]
exact ⟨⟨_, le_rfl⟩, h.symm⟩
[GOAL]
case left
n x : ℕ
h : x = (unpair n).fst
⊢ (∃ x, n ≤ x) ∧ (unpair n).fst = x
case right
n x : ℕ
h : x = (unpair n).snd
⊢ (∃ x, n ≤ x) ∧ (unpair n).snd = x
case pair
a✝¹ a✝ : Code
a_ih✝¹ : ∀ {n x : ℕ}, x ∈ eval a✝¹ n → ∃ k, x ∈ evaln (k + 1) a✝¹ n
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h : ∃ a, a ∈ eval a✝¹ n ∧ ∃ a_1, a_1 ∈ eval a✝ n ∧ Nat.pair a a_1 = x
⊢ ∃ k, n ≤ k ∧ ∃ a, evaln (k + 1) a✝¹ n = some a ∧ ∃ a_1, evaln (k + 1) a✝ n = some a_1 ∧ Nat.pair a a_1 = x
case comp
a✝¹ a✝ : Code
a_ih✝¹ : ∀ {n x : ℕ}, x ∈ eval a✝¹ n → ∃ k, x ∈ evaln (k + 1) a✝¹ n
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h : ∃ a, a ∈ eval a✝ n ∧ x ∈ eval a✝¹ a
⊢ ∃ k, n ≤ k ∧ ∃ a, evaln (k + 1) a✝ n = some a ∧ evaln (k + 1) a✝¹ a = some x
case prec
a✝¹ a✝ : Code
a_ih✝¹ : ∀ {n x : ℕ}, x ∈ eval a✝¹ n → ∃ k, x ∈ evaln (k + 1) a✝¹ n
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h :
  x ∈
    Nat.rec (eval a✝¹ (unpair n).fst)
      (fun y IH => Part.bind IH fun i => eval a✝ (Nat.pair (unpair n).fst (Nat.pair y i))) (unpair n).snd
⊢ ∃ k,
    n ≤ k ∧
      Nat.rec (evaln (k + 1) a✝¹ (unpair n).fst)
          (fun n_1 n_ih =>
            Option.bind (evaln k (prec a✝¹ a✝) (Nat.pair (unpair n).fst n_1)) fun i =>
              evaln (k + 1) a✝ (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
          (unpair n).snd =
        some x
case rfind'
a✝ : Code
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h :
  ∃ a,
    (0 ∈ eval a✝ (Nat.pair (unpair n).fst (a + (unpair n).snd)) ∧
        ∀ {m : ℕ}, m < a → ∃ a, a ∈ eval a✝ (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0) ∧
      a + (unpair n).snd = x
⊢ ∃ k,
    n ≤ k ∧
      ∃ a,
        evaln (k + 1) a✝ n = some a ∧
          (if a = 0 then some (unpair n).snd else evaln k (rfind' a✝) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
            some x
[PROOFSTEP]
exact ⟨⟨_, le_rfl⟩, h.symm⟩
[GOAL]
case right
n x : ℕ
h : x = (unpair n).snd
⊢ (∃ x, n ≤ x) ∧ (unpair n).snd = x
case pair
a✝¹ a✝ : Code
a_ih✝¹ : ∀ {n x : ℕ}, x ∈ eval a✝¹ n → ∃ k, x ∈ evaln (k + 1) a✝¹ n
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h : ∃ a, a ∈ eval a✝¹ n ∧ ∃ a_1, a_1 ∈ eval a✝ n ∧ Nat.pair a a_1 = x
⊢ ∃ k, n ≤ k ∧ ∃ a, evaln (k + 1) a✝¹ n = some a ∧ ∃ a_1, evaln (k + 1) a✝ n = some a_1 ∧ Nat.pair a a_1 = x
case comp
a✝¹ a✝ : Code
a_ih✝¹ : ∀ {n x : ℕ}, x ∈ eval a✝¹ n → ∃ k, x ∈ evaln (k + 1) a✝¹ n
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h : ∃ a, a ∈ eval a✝ n ∧ x ∈ eval a✝¹ a
⊢ ∃ k, n ≤ k ∧ ∃ a, evaln (k + 1) a✝ n = some a ∧ evaln (k + 1) a✝¹ a = some x
case prec
a✝¹ a✝ : Code
a_ih✝¹ : ∀ {n x : ℕ}, x ∈ eval a✝¹ n → ∃ k, x ∈ evaln (k + 1) a✝¹ n
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h :
  x ∈
    Nat.rec (eval a✝¹ (unpair n).fst)
      (fun y IH => Part.bind IH fun i => eval a✝ (Nat.pair (unpair n).fst (Nat.pair y i))) (unpair n).snd
⊢ ∃ k,
    n ≤ k ∧
      Nat.rec (evaln (k + 1) a✝¹ (unpair n).fst)
          (fun n_1 n_ih =>
            Option.bind (evaln k (prec a✝¹ a✝) (Nat.pair (unpair n).fst n_1)) fun i =>
              evaln (k + 1) a✝ (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
          (unpair n).snd =
        some x
case rfind'
a✝ : Code
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h :
  ∃ a,
    (0 ∈ eval a✝ (Nat.pair (unpair n).fst (a + (unpair n).snd)) ∧
        ∀ {m : ℕ}, m < a → ∃ a, a ∈ eval a✝ (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0) ∧
      a + (unpair n).snd = x
⊢ ∃ k,
    n ≤ k ∧
      ∃ a,
        evaln (k + 1) a✝ n = some a ∧
          (if a = 0 then some (unpair n).snd else evaln k (rfind' a✝) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
            some x
[PROOFSTEP]
exact ⟨⟨_, le_rfl⟩, h.symm⟩
[GOAL]
case pair
a✝¹ a✝ : Code
a_ih✝¹ : ∀ {n x : ℕ}, x ∈ eval a✝¹ n → ∃ k, x ∈ evaln (k + 1) a✝¹ n
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h : ∃ a, a ∈ eval a✝¹ n ∧ ∃ a_1, a_1 ∈ eval a✝ n ∧ Nat.pair a a_1 = x
⊢ ∃ k, n ≤ k ∧ ∃ a, evaln (k + 1) a✝¹ n = some a ∧ ∃ a_1, evaln (k + 1) a✝ n = some a_1 ∧ Nat.pair a a_1 = x
case comp
a✝¹ a✝ : Code
a_ih✝¹ : ∀ {n x : ℕ}, x ∈ eval a✝¹ n → ∃ k, x ∈ evaln (k + 1) a✝¹ n
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h : ∃ a, a ∈ eval a✝ n ∧ x ∈ eval a✝¹ a
⊢ ∃ k, n ≤ k ∧ ∃ a, evaln (k + 1) a✝ n = some a ∧ evaln (k + 1) a✝¹ a = some x
case prec
a✝¹ a✝ : Code
a_ih✝¹ : ∀ {n x : ℕ}, x ∈ eval a✝¹ n → ∃ k, x ∈ evaln (k + 1) a✝¹ n
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h :
  x ∈
    Nat.rec (eval a✝¹ (unpair n).fst)
      (fun y IH => Part.bind IH fun i => eval a✝ (Nat.pair (unpair n).fst (Nat.pair y i))) (unpair n).snd
⊢ ∃ k,
    n ≤ k ∧
      Nat.rec (evaln (k + 1) a✝¹ (unpair n).fst)
          (fun n_1 n_ih =>
            Option.bind (evaln k (prec a✝¹ a✝) (Nat.pair (unpair n).fst n_1)) fun i =>
              evaln (k + 1) a✝ (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
          (unpair n).snd =
        some x
case rfind'
a✝ : Code
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h :
  ∃ a,
    (0 ∈ eval a✝ (Nat.pair (unpair n).fst (a + (unpair n).snd)) ∧
        ∀ {m : ℕ}, m < a → ∃ a, a ∈ eval a✝ (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0) ∧
      a + (unpair n).snd = x
⊢ ∃ k,
    n ≤ k ∧
      ∃ a,
        evaln (k + 1) a✝ n = some a ∧
          (if a = 0 then some (unpair n).snd else evaln k (rfind' a✝) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
            some x
[PROOFSTEP]
case pair cf cg hf hg =>
  rcases h with ⟨x, hx, y, hy, rfl⟩
  rcases hf hx with ⟨k₁, hk₁⟩; rcases hg hy with ⟨k₂, hk₂⟩
  refine' ⟨max k₁ k₂, _⟩
  refine'
    ⟨le_max_of_le_left <| Nat.le_of_lt_succ <| evaln_bound hk₁, _, evaln_mono (Nat.succ_le_succ <| le_max_left _ _) hk₁,
      _, evaln_mono (Nat.succ_le_succ <| le_max_right _ _) hk₂, rfl⟩
[GOAL]
cf cg : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
hg : ∀ {n x : ℕ}, x ∈ eval cg n → ∃ k, x ∈ evaln (k + 1) cg n
n x : ℕ
h : ∃ a, a ∈ eval cf n ∧ ∃ a_1, a_1 ∈ eval cg n ∧ Nat.pair a a_1 = x
⊢ ∃ k, n ≤ k ∧ ∃ a, evaln (k + 1) cf n = some a ∧ ∃ a_1, evaln (k + 1) cg n = some a_1 ∧ Nat.pair a a_1 = x
[PROOFSTEP]
case pair cf cg hf hg =>
  rcases h with ⟨x, hx, y, hy, rfl⟩
  rcases hf hx with ⟨k₁, hk₁⟩; rcases hg hy with ⟨k₂, hk₂⟩
  refine' ⟨max k₁ k₂, _⟩
  refine'
    ⟨le_max_of_le_left <| Nat.le_of_lt_succ <| evaln_bound hk₁, _, evaln_mono (Nat.succ_le_succ <| le_max_left _ _) hk₁,
      _, evaln_mono (Nat.succ_le_succ <| le_max_right _ _) hk₂, rfl⟩
[GOAL]
cf cg : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
hg : ∀ {n x : ℕ}, x ∈ eval cg n → ∃ k, x ∈ evaln (k + 1) cg n
n x : ℕ
h : ∃ a, a ∈ eval cf n ∧ ∃ a_1, a_1 ∈ eval cg n ∧ Nat.pair a a_1 = x
⊢ ∃ k, n ≤ k ∧ ∃ a, evaln (k + 1) cf n = some a ∧ ∃ a_1, evaln (k + 1) cg n = some a_1 ∧ Nat.pair a a_1 = x
[PROOFSTEP]
rcases h with ⟨x, hx, y, hy, rfl⟩
[GOAL]
case intro.intro.intro.intro
cf cg : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
hg : ∀ {n x : ℕ}, x ∈ eval cg n → ∃ k, x ∈ evaln (k + 1) cg n
n x : ℕ
hx : x ∈ eval cf n
y : ℕ
hy : y ∈ eval cg n
⊢ ∃ k, n ≤ k ∧ ∃ a, evaln (k + 1) cf n = some a ∧ ∃ a_1, evaln (k + 1) cg n = some a_1 ∧ Nat.pair a a_1 = Nat.pair x y
[PROOFSTEP]
rcases hf hx with ⟨k₁, hk₁⟩
[GOAL]
case intro.intro.intro.intro.intro
cf cg : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
hg : ∀ {n x : ℕ}, x ∈ eval cg n → ∃ k, x ∈ evaln (k + 1) cg n
n x : ℕ
hx : x ∈ eval cf n
y : ℕ
hy : y ∈ eval cg n
k₁ : ℕ
hk₁ : x ∈ evaln (k₁ + 1) cf n
⊢ ∃ k, n ≤ k ∧ ∃ a, evaln (k + 1) cf n = some a ∧ ∃ a_1, evaln (k + 1) cg n = some a_1 ∧ Nat.pair a a_1 = Nat.pair x y
[PROOFSTEP]
rcases hg hy with ⟨k₂, hk₂⟩
[GOAL]
case intro.intro.intro.intro.intro.intro
cf cg : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
hg : ∀ {n x : ℕ}, x ∈ eval cg n → ∃ k, x ∈ evaln (k + 1) cg n
n x : ℕ
hx : x ∈ eval cf n
y : ℕ
hy : y ∈ eval cg n
k₁ : ℕ
hk₁ : x ∈ evaln (k₁ + 1) cf n
k₂ : ℕ
hk₂ : y ∈ evaln (k₂ + 1) cg n
⊢ ∃ k, n ≤ k ∧ ∃ a, evaln (k + 1) cf n = some a ∧ ∃ a_1, evaln (k + 1) cg n = some a_1 ∧ Nat.pair a a_1 = Nat.pair x y
[PROOFSTEP]
refine' ⟨max k₁ k₂, _⟩
[GOAL]
case intro.intro.intro.intro.intro.intro
cf cg : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
hg : ∀ {n x : ℕ}, x ∈ eval cg n → ∃ k, x ∈ evaln (k + 1) cg n
n x : ℕ
hx : x ∈ eval cf n
y : ℕ
hy : y ∈ eval cg n
k₁ : ℕ
hk₁ : x ∈ evaln (k₁ + 1) cf n
k₂ : ℕ
hk₂ : y ∈ evaln (k₂ + 1) cg n
⊢ n ≤ max k₁ k₂ ∧
    ∃ a,
      evaln (max k₁ k₂ + 1) cf n = some a ∧ ∃ a_1, evaln (max k₁ k₂ + 1) cg n = some a_1 ∧ Nat.pair a a_1 = Nat.pair x y
[PROOFSTEP]
refine'
  ⟨le_max_of_le_left <| Nat.le_of_lt_succ <| evaln_bound hk₁, _, evaln_mono (Nat.succ_le_succ <| le_max_left _ _) hk₁,
    _, evaln_mono (Nat.succ_le_succ <| le_max_right _ _) hk₂, rfl⟩
[GOAL]
case comp
a✝¹ a✝ : Code
a_ih✝¹ : ∀ {n x : ℕ}, x ∈ eval a✝¹ n → ∃ k, x ∈ evaln (k + 1) a✝¹ n
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h : ∃ a, a ∈ eval a✝ n ∧ x ∈ eval a✝¹ a
⊢ ∃ k, n ≤ k ∧ ∃ a, evaln (k + 1) a✝ n = some a ∧ evaln (k + 1) a✝¹ a = some x
case prec
a✝¹ a✝ : Code
a_ih✝¹ : ∀ {n x : ℕ}, x ∈ eval a✝¹ n → ∃ k, x ∈ evaln (k + 1) a✝¹ n
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h :
  x ∈
    Nat.rec (eval a✝¹ (unpair n).fst)
      (fun y IH => Part.bind IH fun i => eval a✝ (Nat.pair (unpair n).fst (Nat.pair y i))) (unpair n).snd
⊢ ∃ k,
    n ≤ k ∧
      Nat.rec (evaln (k + 1) a✝¹ (unpair n).fst)
          (fun n_1 n_ih =>
            Option.bind (evaln k (prec a✝¹ a✝) (Nat.pair (unpair n).fst n_1)) fun i =>
              evaln (k + 1) a✝ (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
          (unpair n).snd =
        some x
case rfind'
a✝ : Code
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h :
  ∃ a,
    (0 ∈ eval a✝ (Nat.pair (unpair n).fst (a + (unpair n).snd)) ∧
        ∀ {m : ℕ}, m < a → ∃ a, a ∈ eval a✝ (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0) ∧
      a + (unpair n).snd = x
⊢ ∃ k,
    n ≤ k ∧
      ∃ a,
        evaln (k + 1) a✝ n = some a ∧
          (if a = 0 then some (unpair n).snd else evaln k (rfind' a✝) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
            some x
[PROOFSTEP]
case comp cf cg hf hg =>
  rcases h with ⟨y, hy, hx⟩
  rcases hg hy with ⟨k₁, hk₁⟩; rcases hf hx with ⟨k₂, hk₂⟩
  refine' ⟨max k₁ k₂, _⟩
  exact
    ⟨le_max_of_le_left <| Nat.le_of_lt_succ <| evaln_bound hk₁, _, evaln_mono (Nat.succ_le_succ <| le_max_left _ _) hk₁,
      evaln_mono (Nat.succ_le_succ <| le_max_right _ _) hk₂⟩
[GOAL]
cf cg : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
hg : ∀ {n x : ℕ}, x ∈ eval cg n → ∃ k, x ∈ evaln (k + 1) cg n
n x : ℕ
h : ∃ a, a ∈ eval cg n ∧ x ∈ eval cf a
⊢ ∃ k, n ≤ k ∧ ∃ a, evaln (k + 1) cg n = some a ∧ evaln (k + 1) cf a = some x
[PROOFSTEP]
case comp cf cg hf hg =>
  rcases h with ⟨y, hy, hx⟩
  rcases hg hy with ⟨k₁, hk₁⟩; rcases hf hx with ⟨k₂, hk₂⟩
  refine' ⟨max k₁ k₂, _⟩
  exact
    ⟨le_max_of_le_left <| Nat.le_of_lt_succ <| evaln_bound hk₁, _, evaln_mono (Nat.succ_le_succ <| le_max_left _ _) hk₁,
      evaln_mono (Nat.succ_le_succ <| le_max_right _ _) hk₂⟩
[GOAL]
cf cg : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
hg : ∀ {n x : ℕ}, x ∈ eval cg n → ∃ k, x ∈ evaln (k + 1) cg n
n x : ℕ
h : ∃ a, a ∈ eval cg n ∧ x ∈ eval cf a
⊢ ∃ k, n ≤ k ∧ ∃ a, evaln (k + 1) cg n = some a ∧ evaln (k + 1) cf a = some x
[PROOFSTEP]
rcases h with ⟨y, hy, hx⟩
[GOAL]
case intro.intro
cf cg : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
hg : ∀ {n x : ℕ}, x ∈ eval cg n → ∃ k, x ∈ evaln (k + 1) cg n
n x y : ℕ
hy : y ∈ eval cg n
hx : x ∈ eval cf y
⊢ ∃ k, n ≤ k ∧ ∃ a, evaln (k + 1) cg n = some a ∧ evaln (k + 1) cf a = some x
[PROOFSTEP]
rcases hg hy with ⟨k₁, hk₁⟩
[GOAL]
case intro.intro.intro
cf cg : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
hg : ∀ {n x : ℕ}, x ∈ eval cg n → ∃ k, x ∈ evaln (k + 1) cg n
n x y : ℕ
hy : y ∈ eval cg n
hx : x ∈ eval cf y
k₁ : ℕ
hk₁ : y ∈ evaln (k₁ + 1) cg n
⊢ ∃ k, n ≤ k ∧ ∃ a, evaln (k + 1) cg n = some a ∧ evaln (k + 1) cf a = some x
[PROOFSTEP]
rcases hf hx with ⟨k₂, hk₂⟩
[GOAL]
case intro.intro.intro.intro
cf cg : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
hg : ∀ {n x : ℕ}, x ∈ eval cg n → ∃ k, x ∈ evaln (k + 1) cg n
n x y : ℕ
hy : y ∈ eval cg n
hx : x ∈ eval cf y
k₁ : ℕ
hk₁ : y ∈ evaln (k₁ + 1) cg n
k₂ : ℕ
hk₂ : x ∈ evaln (k₂ + 1) cf y
⊢ ∃ k, n ≤ k ∧ ∃ a, evaln (k + 1) cg n = some a ∧ evaln (k + 1) cf a = some x
[PROOFSTEP]
refine' ⟨max k₁ k₂, _⟩
[GOAL]
case intro.intro.intro.intro
cf cg : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
hg : ∀ {n x : ℕ}, x ∈ eval cg n → ∃ k, x ∈ evaln (k + 1) cg n
n x y : ℕ
hy : y ∈ eval cg n
hx : x ∈ eval cf y
k₁ : ℕ
hk₁ : y ∈ evaln (k₁ + 1) cg n
k₂ : ℕ
hk₂ : x ∈ evaln (k₂ + 1) cf y
⊢ n ≤ max k₁ k₂ ∧ ∃ a, evaln (max k₁ k₂ + 1) cg n = some a ∧ evaln (max k₁ k₂ + 1) cf a = some x
[PROOFSTEP]
exact
  ⟨le_max_of_le_left <| Nat.le_of_lt_succ <| evaln_bound hk₁, _, evaln_mono (Nat.succ_le_succ <| le_max_left _ _) hk₁,
    evaln_mono (Nat.succ_le_succ <| le_max_right _ _) hk₂⟩
[GOAL]
case prec
a✝¹ a✝ : Code
a_ih✝¹ : ∀ {n x : ℕ}, x ∈ eval a✝¹ n → ∃ k, x ∈ evaln (k + 1) a✝¹ n
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h :
  x ∈
    Nat.rec (eval a✝¹ (unpair n).fst)
      (fun y IH => Part.bind IH fun i => eval a✝ (Nat.pair (unpair n).fst (Nat.pair y i))) (unpair n).snd
⊢ ∃ k,
    n ≤ k ∧
      Nat.rec (evaln (k + 1) a✝¹ (unpair n).fst)
          (fun n_1 n_ih =>
            Option.bind (evaln k (prec a✝¹ a✝) (Nat.pair (unpair n).fst n_1)) fun i =>
              evaln (k + 1) a✝ (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
          (unpair n).snd =
        some x
case rfind'
a✝ : Code
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h :
  ∃ a,
    (0 ∈ eval a✝ (Nat.pair (unpair n).fst (a + (unpair n).snd)) ∧
        ∀ {m : ℕ}, m < a → ∃ a, a ∈ eval a✝ (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0) ∧
      a + (unpair n).snd = x
⊢ ∃ k,
    n ≤ k ∧
      ∃ a,
        evaln (k + 1) a✝ n = some a ∧
          (if a = 0 then some (unpair n).snd else evaln k (rfind' a✝) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
            some x
[PROOFSTEP]
case prec cf cg hf hg =>
  revert h
  generalize n.unpair.1 = n₁; generalize n.unpair.2 = n₂
  induction' n₂ with m IH generalizing x n <;> simp
  · intro h
    rcases hf h with ⟨k, hk⟩
    exact ⟨_, le_max_left _ _, evaln_mono (Nat.succ_le_succ <| le_max_right _ _) hk⟩
  · intro y hy hx
    rcases IH hy with ⟨k₁, nk₁, hk₁⟩
    rcases hg hx with ⟨k₂, hk₂⟩
    refine'
      ⟨(max k₁ k₂).succ, Nat.le_succ_of_le <| le_max_of_le_left <| le_trans (le_max_left _ (Nat.pair n₁ m)) nk₁, y,
        evaln_mono (Nat.succ_le_succ <| le_max_left _ _) _,
        evaln_mono (Nat.succ_le_succ <| Nat.le_succ_of_le <| le_max_right _ _) hk₂⟩
    simp [evaln, Bind.bind]
    exact ⟨le_trans (le_max_right _ _) nk₁, hk₁⟩
[GOAL]
cf cg : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
hg : ∀ {n x : ℕ}, x ∈ eval cg n → ∃ k, x ∈ evaln (k + 1) cg n
n x : ℕ
h :
  x ∈
    Nat.rec (eval cf (unpair n).fst)
      (fun y IH => Part.bind IH fun i => eval cg (Nat.pair (unpair n).fst (Nat.pair y i))) (unpair n).snd
⊢ ∃ k,
    n ≤ k ∧
      Nat.rec (evaln (k + 1) cf (unpair n).fst)
          (fun n_1 n_ih =>
            Option.bind (evaln k (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
              evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
          (unpair n).snd =
        some x
[PROOFSTEP]
case prec cf cg hf hg =>
  revert h
  generalize n.unpair.1 = n₁; generalize n.unpair.2 = n₂
  induction' n₂ with m IH generalizing x n <;> simp
  · intro h
    rcases hf h with ⟨k, hk⟩
    exact ⟨_, le_max_left _ _, evaln_mono (Nat.succ_le_succ <| le_max_right _ _) hk⟩
  · intro y hy hx
    rcases IH hy with ⟨k₁, nk₁, hk₁⟩
    rcases hg hx with ⟨k₂, hk₂⟩
    refine'
      ⟨(max k₁ k₂).succ, Nat.le_succ_of_le <| le_max_of_le_left <| le_trans (le_max_left _ (Nat.pair n₁ m)) nk₁, y,
        evaln_mono (Nat.succ_le_succ <| le_max_left _ _) _,
        evaln_mono (Nat.succ_le_succ <| Nat.le_succ_of_le <| le_max_right _ _) hk₂⟩
    simp [evaln, Bind.bind]
    exact ⟨le_trans (le_max_right _ _) nk₁, hk₁⟩
[GOAL]
cf cg : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
hg : ∀ {n x : ℕ}, x ∈ eval cg n → ∃ k, x ∈ evaln (k + 1) cg n
n x : ℕ
h :
  x ∈
    Nat.rec (eval cf (unpair n).fst)
      (fun y IH => Part.bind IH fun i => eval cg (Nat.pair (unpair n).fst (Nat.pair y i))) (unpair n).snd
⊢ ∃ k,
    n ≤ k ∧
      Nat.rec (evaln (k + 1) cf (unpair n).fst)
          (fun n_1 n_ih =>
            Option.bind (evaln k (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
              evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
          (unpair n).snd =
        some x
[PROOFSTEP]
revert h
[GOAL]
cf cg : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
hg : ∀ {n x : ℕ}, x ∈ eval cg n → ∃ k, x ∈ evaln (k + 1) cg n
n x : ℕ
⊢ x ∈
      Nat.rec (eval cf (unpair n).fst)
        (fun y IH => Part.bind IH fun i => eval cg (Nat.pair (unpair n).fst (Nat.pair y i))) (unpair n).snd →
    ∃ k,
      n ≤ k ∧
        Nat.rec (evaln (k + 1) cf (unpair n).fst)
            (fun n_1 n_ih =>
              Option.bind (evaln k (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
                evaln (k + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
            (unpair n).snd =
          some x
[PROOFSTEP]
generalize n.unpair.1 = n₁
[GOAL]
cf cg : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
hg : ∀ {n x : ℕ}, x ∈ eval cg n → ∃ k, x ∈ evaln (k + 1) cg n
n x n₁ : ℕ
⊢ x ∈ Nat.rec (eval cf n₁) (fun y IH => Part.bind IH fun i => eval cg (Nat.pair n₁ (Nat.pair y i))) (unpair n).snd →
    ∃ k,
      n ≤ k ∧
        Nat.rec (evaln (k + 1) cf n₁)
            (fun n n_ih =>
              Option.bind (evaln k (prec cf cg) (Nat.pair n₁ n)) fun i => evaln (k + 1) cg (Nat.pair n₁ (Nat.pair n i)))
            (unpair n).snd =
          some x
[PROOFSTEP]
generalize n.unpair.2 = n₂
[GOAL]
cf cg : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
hg : ∀ {n x : ℕ}, x ∈ eval cg n → ∃ k, x ∈ evaln (k + 1) cg n
n x n₁ n₂ : ℕ
⊢ x ∈ Nat.rec (eval cf n₁) (fun y IH => Part.bind IH fun i => eval cg (Nat.pair n₁ (Nat.pair y i))) n₂ →
    ∃ k,
      n ≤ k ∧
        Nat.rec (evaln (k + 1) cf n₁)
            (fun n n_ih =>
              Option.bind (evaln k (prec cf cg) (Nat.pair n₁ n)) fun i => evaln (k + 1) cg (Nat.pair n₁ (Nat.pair n i)))
            n₂ =
          some x
[PROOFSTEP]
induction' n₂ with m IH generalizing x n
[GOAL]
case zero
cf cg : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
hg : ∀ {n x : ℕ}, x ∈ eval cg n → ∃ k, x ∈ evaln (k + 1) cg n
n✝ x✝ n₁ n x : ℕ
⊢ x ∈ Nat.rec (eval cf n₁) (fun y IH => Part.bind IH fun i => eval cg (Nat.pair n₁ (Nat.pair y i))) Nat.zero →
    ∃ k,
      n ≤ k ∧
        Nat.rec (evaln (k + 1) cf n₁)
            (fun n n_ih =>
              Option.bind (evaln k (prec cf cg) (Nat.pair n₁ n)) fun i => evaln (k + 1) cg (Nat.pair n₁ (Nat.pair n i)))
            Nat.zero =
          some x
[PROOFSTEP]
simp
[GOAL]
case succ
cf cg : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
hg : ∀ {n x : ℕ}, x ∈ eval cg n → ∃ k, x ∈ evaln (k + 1) cg n
n✝ x✝ n₁ m : ℕ
IH :
  ∀ {n x : ℕ},
    x ∈ Nat.rec (eval cf n₁) (fun y IH => Part.bind IH fun i => eval cg (Nat.pair n₁ (Nat.pair y i))) m →
      ∃ k,
        n ≤ k ∧
          Nat.rec (evaln (k + 1) cf n₁)
              (fun n n_ih =>
                Option.bind (evaln k (prec cf cg) (Nat.pair n₁ n)) fun i =>
                  evaln (k + 1) cg (Nat.pair n₁ (Nat.pair n i)))
              m =
            some x
n x : ℕ
⊢ x ∈ Nat.rec (eval cf n₁) (fun y IH => Part.bind IH fun i => eval cg (Nat.pair n₁ (Nat.pair y i))) (Nat.succ m) →
    ∃ k,
      n ≤ k ∧
        Nat.rec (evaln (k + 1) cf n₁)
            (fun n n_ih =>
              Option.bind (evaln k (prec cf cg) (Nat.pair n₁ n)) fun i => evaln (k + 1) cg (Nat.pair n₁ (Nat.pair n i)))
            (Nat.succ m) =
          some x
[PROOFSTEP]
simp
[GOAL]
case zero
cf cg : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
hg : ∀ {n x : ℕ}, x ∈ eval cg n → ∃ k, x ∈ evaln (k + 1) cg n
n✝ x✝ n₁ n x : ℕ
⊢ x ∈ eval cf n₁ → ∃ k, n ≤ k ∧ evaln (k + 1) cf n₁ = some x
[PROOFSTEP]
intro h
[GOAL]
case zero
cf cg : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
hg : ∀ {n x : ℕ}, x ∈ eval cg n → ∃ k, x ∈ evaln (k + 1) cg n
n✝ x✝ n₁ n x : ℕ
h : x ∈ eval cf n₁
⊢ ∃ k, n ≤ k ∧ evaln (k + 1) cf n₁ = some x
[PROOFSTEP]
rcases hf h with ⟨k, hk⟩
[GOAL]
case zero.intro
cf cg : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
hg : ∀ {n x : ℕ}, x ∈ eval cg n → ∃ k, x ∈ evaln (k + 1) cg n
n✝ x✝ n₁ n x : ℕ
h : x ∈ eval cf n₁
k : ℕ
hk : x ∈ evaln (k + 1) cf n₁
⊢ ∃ k, n ≤ k ∧ evaln (k + 1) cf n₁ = some x
[PROOFSTEP]
exact ⟨_, le_max_left _ _, evaln_mono (Nat.succ_le_succ <| le_max_right _ _) hk⟩
[GOAL]
case succ
cf cg : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
hg : ∀ {n x : ℕ}, x ∈ eval cg n → ∃ k, x ∈ evaln (k + 1) cg n
n✝ x✝ n₁ m : ℕ
IH :
  ∀ {n x : ℕ},
    x ∈ Nat.rec (eval cf n₁) (fun y IH => Part.bind IH fun i => eval cg (Nat.pair n₁ (Nat.pair y i))) m →
      ∃ k,
        n ≤ k ∧
          Nat.rec (evaln (k + 1) cf n₁)
              (fun n n_ih =>
                Option.bind (evaln k (prec cf cg) (Nat.pair n₁ n)) fun i =>
                  evaln (k + 1) cg (Nat.pair n₁ (Nat.pair n i)))
              m =
            some x
n x : ℕ
⊢ ∀ (x_1 : ℕ),
    x_1 ∈ Nat.rec (eval cf n₁) (fun y IH => Part.bind IH fun i => eval cg (Nat.pair n₁ (Nat.pair y i))) m →
      x ∈ eval cg (Nat.pair n₁ (Nat.pair m x_1)) →
        ∃ k,
          n ≤ k ∧
            ∃ a, evaln k (prec cf cg) (Nat.pair n₁ m) = some a ∧ evaln (k + 1) cg (Nat.pair n₁ (Nat.pair m a)) = some x
[PROOFSTEP]
intro y hy hx
[GOAL]
case succ
cf cg : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
hg : ∀ {n x : ℕ}, x ∈ eval cg n → ∃ k, x ∈ evaln (k + 1) cg n
n✝ x✝ n₁ m : ℕ
IH :
  ∀ {n x : ℕ},
    x ∈ Nat.rec (eval cf n₁) (fun y IH => Part.bind IH fun i => eval cg (Nat.pair n₁ (Nat.pair y i))) m →
      ∃ k,
        n ≤ k ∧
          Nat.rec (evaln (k + 1) cf n₁)
              (fun n n_ih =>
                Option.bind (evaln k (prec cf cg) (Nat.pair n₁ n)) fun i =>
                  evaln (k + 1) cg (Nat.pair n₁ (Nat.pair n i)))
              m =
            some x
n x y : ℕ
hy : y ∈ Nat.rec (eval cf n₁) (fun y IH => Part.bind IH fun i => eval cg (Nat.pair n₁ (Nat.pair y i))) m
hx : x ∈ eval cg (Nat.pair n₁ (Nat.pair m y))
⊢ ∃ k,
    n ≤ k ∧ ∃ a, evaln k (prec cf cg) (Nat.pair n₁ m) = some a ∧ evaln (k + 1) cg (Nat.pair n₁ (Nat.pair m a)) = some x
[PROOFSTEP]
rcases IH hy with ⟨k₁, nk₁, hk₁⟩
[GOAL]
case succ.intro.intro
cf cg : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
hg : ∀ {n x : ℕ}, x ∈ eval cg n → ∃ k, x ∈ evaln (k + 1) cg n
n✝ x✝ n₁ m : ℕ
IH :
  ∀ {n x : ℕ},
    x ∈ Nat.rec (eval cf n₁) (fun y IH => Part.bind IH fun i => eval cg (Nat.pair n₁ (Nat.pair y i))) m →
      ∃ k,
        n ≤ k ∧
          Nat.rec (evaln (k + 1) cf n₁)
              (fun n n_ih =>
                Option.bind (evaln k (prec cf cg) (Nat.pair n₁ n)) fun i =>
                  evaln (k + 1) cg (Nat.pair n₁ (Nat.pair n i)))
              m =
            some x
n x y : ℕ
hy : y ∈ Nat.rec (eval cf n₁) (fun y IH => Part.bind IH fun i => eval cg (Nat.pair n₁ (Nat.pair y i))) m
hx : x ∈ eval cg (Nat.pair n₁ (Nat.pair m y))
k₁ : ℕ
nk₁ : ?m.1242894 ≤ k₁
hk₁ :
  Nat.rec (evaln (k₁ + 1) cf n₁)
      (fun n n_ih =>
        Option.bind (evaln k₁ (prec cf cg) (Nat.pair n₁ n)) fun i => evaln (k₁ + 1) cg (Nat.pair n₁ (Nat.pair n i)))
      m =
    some y
⊢ ∃ k,
    n ≤ k ∧ ∃ a, evaln k (prec cf cg) (Nat.pair n₁ m) = some a ∧ evaln (k + 1) cg (Nat.pair n₁ (Nat.pair m a)) = some x
[PROOFSTEP]
rcases hg hx with ⟨k₂, hk₂⟩
[GOAL]
case succ.intro.intro.intro
cf cg : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
hg : ∀ {n x : ℕ}, x ∈ eval cg n → ∃ k, x ∈ evaln (k + 1) cg n
n✝ x✝ n₁ m : ℕ
IH :
  ∀ {n x : ℕ},
    x ∈ Nat.rec (eval cf n₁) (fun y IH => Part.bind IH fun i => eval cg (Nat.pair n₁ (Nat.pair y i))) m →
      ∃ k,
        n ≤ k ∧
          Nat.rec (evaln (k + 1) cf n₁)
              (fun n n_ih =>
                Option.bind (evaln k (prec cf cg) (Nat.pair n₁ n)) fun i =>
                  evaln (k + 1) cg (Nat.pair n₁ (Nat.pair n i)))
              m =
            some x
n x y : ℕ
hy : y ∈ Nat.rec (eval cf n₁) (fun y IH => Part.bind IH fun i => eval cg (Nat.pair n₁ (Nat.pair y i))) m
hx : x ∈ eval cg (Nat.pair n₁ (Nat.pair m y))
k₁ : ℕ
nk₁ : ?m.1242894 ≤ k₁
hk₁ :
  Nat.rec (evaln (k₁ + 1) cf n₁)
      (fun n n_ih =>
        Option.bind (evaln k₁ (prec cf cg) (Nat.pair n₁ n)) fun i => evaln (k₁ + 1) cg (Nat.pair n₁ (Nat.pair n i)))
      m =
    some y
k₂ : ℕ
hk₂ : x ∈ evaln (k₂ + 1) cg (Nat.pair n₁ (Nat.pair m y))
⊢ ∃ k,
    n ≤ k ∧ ∃ a, evaln k (prec cf cg) (Nat.pair n₁ m) = some a ∧ evaln (k + 1) cg (Nat.pair n₁ (Nat.pair m a)) = some x
[PROOFSTEP]
refine'
  ⟨(max k₁ k₂).succ, Nat.le_succ_of_le <| le_max_of_le_left <| le_trans (le_max_left _ (Nat.pair n₁ m)) nk₁, y,
    evaln_mono (Nat.succ_le_succ <| le_max_left _ _) _,
    evaln_mono (Nat.succ_le_succ <| Nat.le_succ_of_le <| le_max_right _ _) hk₂⟩
[GOAL]
case succ.intro.intro.intro
cf cg : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
hg : ∀ {n x : ℕ}, x ∈ eval cg n → ∃ k, x ∈ evaln (k + 1) cg n
n✝ x✝ n₁ m : ℕ
IH :
  ∀ {n x : ℕ},
    x ∈ Nat.rec (eval cf n₁) (fun y IH => Part.bind IH fun i => eval cg (Nat.pair n₁ (Nat.pair y i))) m →
      ∃ k,
        n ≤ k ∧
          Nat.rec (evaln (k + 1) cf n₁)
              (fun n n_ih =>
                Option.bind (evaln k (prec cf cg) (Nat.pair n₁ n)) fun i =>
                  evaln (k + 1) cg (Nat.pair n₁ (Nat.pair n i)))
              m =
            some x
n x y : ℕ
hy : y ∈ Nat.rec (eval cf n₁) (fun y IH => Part.bind IH fun i => eval cg (Nat.pair n₁ (Nat.pair y i))) m
hx : x ∈ eval cg (Nat.pair n₁ (Nat.pair m y))
k₁ : ℕ
nk₁ : max n (Nat.pair n₁ m) ≤ k₁
hk₁ :
  Nat.rec (evaln (k₁ + 1) cf n₁)
      (fun n n_ih =>
        Option.bind (evaln k₁ (prec cf cg) (Nat.pair n₁ n)) fun i => evaln (k₁ + 1) cg (Nat.pair n₁ (Nat.pair n i)))
      m =
    some y
k₂ : ℕ
hk₂ : x ∈ evaln (k₂ + 1) cg (Nat.pair n₁ (Nat.pair m y))
⊢ y ∈ evaln (Nat.succ k₁) (prec cf cg) (Nat.pair n₁ m)
[PROOFSTEP]
simp [evaln, Bind.bind]
[GOAL]
case succ.intro.intro.intro
cf cg : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
hg : ∀ {n x : ℕ}, x ∈ eval cg n → ∃ k, x ∈ evaln (k + 1) cg n
n✝ x✝ n₁ m : ℕ
IH :
  ∀ {n x : ℕ},
    x ∈ Nat.rec (eval cf n₁) (fun y IH => Part.bind IH fun i => eval cg (Nat.pair n₁ (Nat.pair y i))) m →
      ∃ k,
        n ≤ k ∧
          Nat.rec (evaln (k + 1) cf n₁)
              (fun n n_ih =>
                Option.bind (evaln k (prec cf cg) (Nat.pair n₁ n)) fun i =>
                  evaln (k + 1) cg (Nat.pair n₁ (Nat.pair n i)))
              m =
            some x
n x y : ℕ
hy : y ∈ Nat.rec (eval cf n₁) (fun y IH => Part.bind IH fun i => eval cg (Nat.pair n₁ (Nat.pair y i))) m
hx : x ∈ eval cg (Nat.pair n₁ (Nat.pair m y))
k₁ : ℕ
nk₁ : max n (Nat.pair n₁ m) ≤ k₁
hk₁ :
  Nat.rec (evaln (k₁ + 1) cf n₁)
      (fun n n_ih =>
        Option.bind (evaln k₁ (prec cf cg) (Nat.pair n₁ n)) fun i => evaln (k₁ + 1) cg (Nat.pair n₁ (Nat.pair n i)))
      m =
    some y
k₂ : ℕ
hk₂ : x ∈ evaln (k₂ + 1) cg (Nat.pair n₁ (Nat.pair m y))
⊢ Nat.pair n₁ m ≤ k₁ ∧
    Nat.rec (evaln (k₁ + 1) cf n₁)
        (fun n n_ih =>
          Option.bind (evaln k₁ (prec cf cg) (Nat.pair n₁ n)) fun i => evaln (k₁ + 1) cg (Nat.pair n₁ (Nat.pair n i)))
        m =
      some y
[PROOFSTEP]
exact ⟨le_trans (le_max_right _ _) nk₁, hk₁⟩
[GOAL]
case rfind'
a✝ : Code
a_ih✝ : ∀ {n x : ℕ}, x ∈ eval a✝ n → ∃ k, x ∈ evaln (k + 1) a✝ n
n x : ℕ
h :
  ∃ a,
    (0 ∈ eval a✝ (Nat.pair (unpair n).fst (a + (unpair n).snd)) ∧
        ∀ {m : ℕ}, m < a → ∃ a, a ∈ eval a✝ (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0) ∧
      a + (unpair n).snd = x
⊢ ∃ k,
    n ≤ k ∧
      ∃ a,
        evaln (k + 1) a✝ n = some a ∧
          (if a = 0 then some (unpair n).snd else evaln k (rfind' a✝) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
            some x
[PROOFSTEP]
case rfind' cf hf =>
  rcases h with ⟨y, ⟨hy₁, hy₂⟩, rfl⟩
  suffices ∃ k, y + n.unpair.2 ∈ evaln (k + 1) (rfind' cf) (Nat.pair n.unpair.1 n.unpair.2) by simpa [evaln, Bind.bind]
  revert hy₁ hy₂
  generalize n.unpair.2 = m
  intro hy₁ hy₂
  induction' y with y IH generalizing m <;> simp [evaln, Bind.bind]
  · simp at hy₁ 
    rcases hf hy₁ with ⟨k, hk⟩
    exact ⟨_, Nat.le_of_lt_succ <| evaln_bound hk, _, hk, by simp; rfl⟩
  · rcases hy₂ (Nat.succ_pos _) with ⟨a, ha, a0⟩
    rcases hf ha with ⟨k₁, hk₁⟩
    rcases IH m.succ (by simpa [Nat.succ_eq_add_one, add_comm, add_left_comm] using hy₁) fun {i} hi => by
        simpa [Nat.succ_eq_add_one, add_comm, add_left_comm] using hy₂ (Nat.succ_lt_succ hi) with
      ⟨k₂, hk₂⟩
    use(max k₁ k₂).succ
    rw [zero_add] at hk₁ 
    use Nat.le_succ_of_le <| le_max_of_le_left <| Nat.le_of_lt_succ <| evaln_bound hk₁
    use a
    use evaln_mono (Nat.succ_le_succ <| Nat.le_succ_of_le <| le_max_left _ _) hk₁
    simpa [Nat.succ_eq_add_one, a0, -max_eq_left, -max_eq_right, add_comm, add_left_comm] using
      evaln_mono (Nat.succ_le_succ <| le_max_right _ _) hk₂
[GOAL]
cf : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
n x : ℕ
h :
  ∃ a,
    (0 ∈ eval cf (Nat.pair (unpair n).fst (a + (unpair n).snd)) ∧
        ∀ {m : ℕ}, m < a → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0) ∧
      a + (unpair n).snd = x
⊢ ∃ k,
    n ≤ k ∧
      ∃ a,
        evaln (k + 1) cf n = some a ∧
          (if a = 0 then some (unpair n).snd else evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
            some x
[PROOFSTEP]
case rfind' cf hf =>
  rcases h with ⟨y, ⟨hy₁, hy₂⟩, rfl⟩
  suffices ∃ k, y + n.unpair.2 ∈ evaln (k + 1) (rfind' cf) (Nat.pair n.unpair.1 n.unpair.2) by simpa [evaln, Bind.bind]
  revert hy₁ hy₂
  generalize n.unpair.2 = m
  intro hy₁ hy₂
  induction' y with y IH generalizing m <;> simp [evaln, Bind.bind]
  · simp at hy₁ 
    rcases hf hy₁ with ⟨k, hk⟩
    exact ⟨_, Nat.le_of_lt_succ <| evaln_bound hk, _, hk, by simp; rfl⟩
  · rcases hy₂ (Nat.succ_pos _) with ⟨a, ha, a0⟩
    rcases hf ha with ⟨k₁, hk₁⟩
    rcases IH m.succ (by simpa [Nat.succ_eq_add_one, add_comm, add_left_comm] using hy₁) fun {i} hi => by
        simpa [Nat.succ_eq_add_one, add_comm, add_left_comm] using hy₂ (Nat.succ_lt_succ hi) with
      ⟨k₂, hk₂⟩
    use(max k₁ k₂).succ
    rw [zero_add] at hk₁ 
    use Nat.le_succ_of_le <| le_max_of_le_left <| Nat.le_of_lt_succ <| evaln_bound hk₁
    use a
    use evaln_mono (Nat.succ_le_succ <| Nat.le_succ_of_le <| le_max_left _ _) hk₁
    simpa [Nat.succ_eq_add_one, a0, -max_eq_left, -max_eq_right, add_comm, add_left_comm] using
      evaln_mono (Nat.succ_le_succ <| le_max_right _ _) hk₂
[GOAL]
cf : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
n x : ℕ
h :
  ∃ a,
    (0 ∈ eval cf (Nat.pair (unpair n).fst (a + (unpair n).snd)) ∧
        ∀ {m : ℕ}, m < a → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0) ∧
      a + (unpair n).snd = x
⊢ ∃ k,
    n ≤ k ∧
      ∃ a,
        evaln (k + 1) cf n = some a ∧
          (if a = 0 then some (unpair n).snd else evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
            some x
[PROOFSTEP]
rcases h with ⟨y, ⟨hy₁, hy₂⟩, rfl⟩
[GOAL]
case intro.intro.intro
cf : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
n y : ℕ
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y + (unpair n).snd))
hy₂ : ∀ {m : ℕ}, m < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0
⊢ ∃ k,
    n ≤ k ∧
      ∃ a,
        evaln (k + 1) cf n = some a ∧
          (if a = 0 then some (unpair n).snd else evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
            some (y + (unpair n).snd)
[PROOFSTEP]
suffices ∃ k, y + n.unpair.2 ∈ evaln (k + 1) (rfind' cf) (Nat.pair n.unpair.1 n.unpair.2) by simpa [evaln, Bind.bind]
[GOAL]
cf : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
n y : ℕ
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y + (unpair n).snd))
hy₂ : ∀ {m : ℕ}, m < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0
this : ∃ k, y + (unpair n).snd ∈ evaln (k + 1) (rfind' cf) (Nat.pair (unpair n).fst (unpair n).snd)
⊢ ∃ k,
    n ≤ k ∧
      ∃ a,
        evaln (k + 1) cf n = some a ∧
          (if a = 0 then some (unpair n).snd else evaln k (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))) =
            some (y + (unpair n).snd)
[PROOFSTEP]
simpa [evaln, Bind.bind]
[GOAL]
case intro.intro.intro
cf : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
n y : ℕ
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y + (unpair n).snd))
hy₂ : ∀ {m : ℕ}, m < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0
⊢ ∃ k, y + (unpair n).snd ∈ evaln (k + 1) (rfind' cf) (Nat.pair (unpair n).fst (unpair n).snd)
[PROOFSTEP]
revert hy₁ hy₂
[GOAL]
case intro.intro.intro
cf : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
n y : ℕ
⊢ 0 ∈ eval cf (Nat.pair (unpair n).fst (y + (unpair n).snd)) →
    (∀ {m : ℕ}, m < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + (unpair n).snd)) ∧ ¬a = 0) →
      ∃ k, y + (unpair n).snd ∈ evaln (k + 1) (rfind' cf) (Nat.pair (unpair n).fst (unpair n).snd)
[PROOFSTEP]
generalize n.unpair.2 = m
[GOAL]
case intro.intro.intro
cf : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
n y m : ℕ
⊢ 0 ∈ eval cf (Nat.pair (unpair n).fst (y + m)) →
    (∀ {m_1 : ℕ}, m_1 < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0) →
      ∃ k, y + m ∈ evaln (k + 1) (rfind' cf) (Nat.pair (unpair n).fst m)
[PROOFSTEP]
intro hy₁ hy₂
[GOAL]
case intro.intro.intro
cf : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
n y m : ℕ
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y + m))
hy₂ : ∀ {m_1 : ℕ}, m_1 < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0
⊢ ∃ k, y + m ∈ evaln (k + 1) (rfind' cf) (Nat.pair (unpair n).fst m)
[PROOFSTEP]
induction' y with y IH generalizing m
[GOAL]
case intro.intro.intro.zero
cf : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
n y m✝ : ℕ
hy₁✝ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y + m✝))
hy₂✝ : ∀ {m : ℕ}, m < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + m✝)) ∧ ¬a = 0
m : ℕ
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst (Nat.zero + m))
hy₂ : ∀ {m_1 : ℕ}, m_1 < Nat.zero → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0
⊢ ∃ k, Nat.zero + m ∈ evaln (k + 1) (rfind' cf) (Nat.pair (unpair n).fst m)
[PROOFSTEP]
simp [evaln, Bind.bind]
[GOAL]
case intro.intro.intro.succ
cf : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
n y✝ m✝ : ℕ
hy₁✝ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y✝ + m✝))
hy₂✝ : ∀ {m : ℕ}, m < y✝ → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + m✝)) ∧ ¬a = 0
y : ℕ
IH :
  ∀ (m : ℕ),
    0 ∈ eval cf (Nat.pair (unpair n).fst (y + m)) →
      (∀ {m_1 : ℕ}, m_1 < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0) →
        ∃ k, y + m ∈ evaln (k + 1) (rfind' cf) (Nat.pair (unpair n).fst m)
m : ℕ
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst (Nat.succ y + m))
hy₂ : ∀ {m_1 : ℕ}, m_1 < Nat.succ y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0
⊢ ∃ k, Nat.succ y + m ∈ evaln (k + 1) (rfind' cf) (Nat.pair (unpair n).fst m)
[PROOFSTEP]
simp [evaln, Bind.bind]
[GOAL]
case intro.intro.intro.zero
cf : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
n y m✝ : ℕ
hy₁✝ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y + m✝))
hy₂✝ : ∀ {m : ℕ}, m < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + m✝)) ∧ ¬a = 0
m : ℕ
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst (Nat.zero + m))
hy₂ : ∀ {m_1 : ℕ}, m_1 < Nat.zero → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0
⊢ ∃ k,
    Nat.pair (unpair n).fst m ≤ k ∧
      ∃ a,
        evaln (k + 1) cf (Nat.pair (unpair n).fst m) = some a ∧
          (if a = 0 then pure m else evaln k (rfind' cf) (Nat.pair (unpair n).fst (m + 1))) = some m
[PROOFSTEP]
simp at hy₁ 
[GOAL]
case intro.intro.intro.zero
cf : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
n y m✝ : ℕ
hy₁✝ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y + m✝))
hy₂✝ : ∀ {m : ℕ}, m < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + m✝)) ∧ ¬a = 0
m : ℕ
hy₂ : ∀ {m_1 : ℕ}, m_1 < Nat.zero → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst m)
⊢ ∃ k,
    Nat.pair (unpair n).fst m ≤ k ∧
      ∃ a,
        evaln (k + 1) cf (Nat.pair (unpair n).fst m) = some a ∧
          (if a = 0 then pure m else evaln k (rfind' cf) (Nat.pair (unpair n).fst (m + 1))) = some m
[PROOFSTEP]
rcases hf hy₁ with ⟨k, hk⟩
[GOAL]
case intro.intro.intro.zero.intro
cf : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
n y m✝ : ℕ
hy₁✝ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y + m✝))
hy₂✝ : ∀ {m : ℕ}, m < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + m✝)) ∧ ¬a = 0
m : ℕ
hy₂ : ∀ {m_1 : ℕ}, m_1 < Nat.zero → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst m)
k : ℕ
hk : 0 ∈ evaln (k + 1) cf (Nat.pair (unpair n).fst m)
⊢ ∃ k,
    Nat.pair (unpair n).fst m ≤ k ∧
      ∃ a,
        evaln (k + 1) cf (Nat.pair (unpair n).fst m) = some a ∧
          (if a = 0 then pure m else evaln k (rfind' cf) (Nat.pair (unpair n).fst (m + 1))) = some m
[PROOFSTEP]
exact ⟨_, Nat.le_of_lt_succ <| evaln_bound hk, _, hk, by simp; rfl⟩
[GOAL]
cf : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
n y m✝ : ℕ
hy₁✝ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y + m✝))
hy₂✝ : ∀ {m : ℕ}, m < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + m✝)) ∧ ¬a = 0
m : ℕ
hy₂ : ∀ {m_1 : ℕ}, m_1 < Nat.zero → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst m)
k : ℕ
hk : 0 ∈ evaln (k + 1) cf (Nat.pair (unpair n).fst m)
⊢ (if 0 = 0 then pure m else evaln k (rfind' cf) (Nat.pair (unpair n).fst (m + 1))) = some m
[PROOFSTEP]
simp
[GOAL]
cf : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
n y m✝ : ℕ
hy₁✝ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y + m✝))
hy₂✝ : ∀ {m : ℕ}, m < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + m✝)) ∧ ¬a = 0
m : ℕ
hy₂ : ∀ {m_1 : ℕ}, m_1 < Nat.zero → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst m)
k : ℕ
hk : 0 ∈ evaln (k + 1) cf (Nat.pair (unpair n).fst m)
⊢ pure m = some m
[PROOFSTEP]
rfl
[GOAL]
case intro.intro.intro.succ
cf : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
n y✝ m✝ : ℕ
hy₁✝ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y✝ + m✝))
hy₂✝ : ∀ {m : ℕ}, m < y✝ → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + m✝)) ∧ ¬a = 0
y : ℕ
IH :
  ∀ (m : ℕ),
    0 ∈ eval cf (Nat.pair (unpair n).fst (y + m)) →
      (∀ {m_1 : ℕ}, m_1 < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0) →
        ∃ k, y + m ∈ evaln (k + 1) (rfind' cf) (Nat.pair (unpair n).fst m)
m : ℕ
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst (Nat.succ y + m))
hy₂ : ∀ {m_1 : ℕ}, m_1 < Nat.succ y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0
⊢ ∃ k,
    Nat.pair (unpair n).fst m ≤ k ∧
      ∃ a,
        evaln (k + 1) cf (Nat.pair (unpair n).fst m) = some a ∧
          (if a = 0 then pure m else evaln k (rfind' cf) (Nat.pair (unpair n).fst (m + 1))) = some (Nat.succ y + m)
[PROOFSTEP]
rcases hy₂ (Nat.succ_pos _) with ⟨a, ha, a0⟩
[GOAL]
case intro.intro.intro.succ.intro.intro
cf : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
n y✝ m✝ : ℕ
hy₁✝ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y✝ + m✝))
hy₂✝ : ∀ {m : ℕ}, m < y✝ → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + m✝)) ∧ ¬a = 0
y : ℕ
IH :
  ∀ (m : ℕ),
    0 ∈ eval cf (Nat.pair (unpair n).fst (y + m)) →
      (∀ {m_1 : ℕ}, m_1 < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0) →
        ∃ k, y + m ∈ evaln (k + 1) (rfind' cf) (Nat.pair (unpair n).fst m)
m : ℕ
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst (Nat.succ y + m))
hy₂ : ∀ {m_1 : ℕ}, m_1 < Nat.succ y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0
a : ℕ
ha : a ∈ eval cf (Nat.pair (unpair n).fst (0 + m))
a0 : ¬a = 0
⊢ ∃ k,
    Nat.pair (unpair n).fst m ≤ k ∧
      ∃ a,
        evaln (k + 1) cf (Nat.pair (unpair n).fst m) = some a ∧
          (if a = 0 then pure m else evaln k (rfind' cf) (Nat.pair (unpair n).fst (m + 1))) = some (Nat.succ y + m)
[PROOFSTEP]
rcases hf ha with ⟨k₁, hk₁⟩
[GOAL]
case intro.intro.intro.succ.intro.intro.intro
cf : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
n y✝ m✝ : ℕ
hy₁✝ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y✝ + m✝))
hy₂✝ : ∀ {m : ℕ}, m < y✝ → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + m✝)) ∧ ¬a = 0
y : ℕ
IH :
  ∀ (m : ℕ),
    0 ∈ eval cf (Nat.pair (unpair n).fst (y + m)) →
      (∀ {m_1 : ℕ}, m_1 < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0) →
        ∃ k, y + m ∈ evaln (k + 1) (rfind' cf) (Nat.pair (unpair n).fst m)
m : ℕ
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst (Nat.succ y + m))
hy₂ : ∀ {m_1 : ℕ}, m_1 < Nat.succ y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0
a : ℕ
ha : a ∈ eval cf (Nat.pair (unpair n).fst (0 + m))
a0 : ¬a = 0
k₁ : ℕ
hk₁ : a ∈ evaln (k₁ + 1) cf (Nat.pair (unpair n).fst (0 + m))
⊢ ∃ k,
    Nat.pair (unpair n).fst m ≤ k ∧
      ∃ a,
        evaln (k + 1) cf (Nat.pair (unpair n).fst m) = some a ∧
          (if a = 0 then pure m else evaln k (rfind' cf) (Nat.pair (unpair n).fst (m + 1))) = some (Nat.succ y + m)
[PROOFSTEP]
rcases IH m.succ (by simpa [Nat.succ_eq_add_one, add_comm, add_left_comm] using hy₁) fun {i} hi => by
    simpa [Nat.succ_eq_add_one, add_comm, add_left_comm] using hy₂ (Nat.succ_lt_succ hi) with
  ⟨k₂, hk₂⟩
[GOAL]
cf : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
n y✝ m✝ : ℕ
hy₁✝ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y✝ + m✝))
hy₂✝ : ∀ {m : ℕ}, m < y✝ → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + m✝)) ∧ ¬a = 0
y : ℕ
IH :
  ∀ (m : ℕ),
    0 ∈ eval cf (Nat.pair (unpair n).fst (y + m)) →
      (∀ {m_1 : ℕ}, m_1 < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0) →
        ∃ k, y + m ∈ evaln (k + 1) (rfind' cf) (Nat.pair (unpair n).fst m)
m : ℕ
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst (Nat.succ y + m))
hy₂ : ∀ {m_1 : ℕ}, m_1 < Nat.succ y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0
a : ℕ
ha : a ∈ eval cf (Nat.pair (unpair n).fst (0 + m))
a0 : ¬a = 0
k₁ : ℕ
hk₁ : a ∈ evaln (k₁ + 1) cf (Nat.pair (unpair n).fst (0 + m))
⊢ 0 ∈ eval cf (Nat.pair (unpair n).fst (y + Nat.succ m))
[PROOFSTEP]
simpa [Nat.succ_eq_add_one, add_comm, add_left_comm] using hy₁
[GOAL]
cf : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
n y✝ m✝ : ℕ
hy₁✝ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y✝ + m✝))
hy₂✝ : ∀ {m : ℕ}, m < y✝ → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + m✝)) ∧ ¬a = 0
y : ℕ
IH :
  ∀ (m : ℕ),
    0 ∈ eval cf (Nat.pair (unpair n).fst (y + m)) →
      (∀ {m_1 : ℕ}, m_1 < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0) →
        ∃ k, y + m ∈ evaln (k + 1) (rfind' cf) (Nat.pair (unpair n).fst m)
m : ℕ
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst (Nat.succ y + m))
hy₂ : ∀ {m_1 : ℕ}, m_1 < Nat.succ y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0
a : ℕ
ha : a ∈ eval cf (Nat.pair (unpair n).fst (0 + m))
a0 : ¬a = 0
k₁ : ℕ
hk₁ : a ∈ evaln (k₁ + 1) cf (Nat.pair (unpair n).fst (0 + m))
i : ℕ
hi : i < y
⊢ ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (i + Nat.succ m)) ∧ ¬a = 0
[PROOFSTEP]
simpa [Nat.succ_eq_add_one, add_comm, add_left_comm] using hy₂ (Nat.succ_lt_succ hi)
[GOAL]
case intro.intro.intro.succ.intro.intro.intro.intro
cf : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
n y✝ m✝ : ℕ
hy₁✝ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y✝ + m✝))
hy₂✝ : ∀ {m : ℕ}, m < y✝ → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + m✝)) ∧ ¬a = 0
y : ℕ
IH :
  ∀ (m : ℕ),
    0 ∈ eval cf (Nat.pair (unpair n).fst (y + m)) →
      (∀ {m_1 : ℕ}, m_1 < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0) →
        ∃ k, y + m ∈ evaln (k + 1) (rfind' cf) (Nat.pair (unpair n).fst m)
m : ℕ
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst (Nat.succ y + m))
hy₂ : ∀ {m_1 : ℕ}, m_1 < Nat.succ y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0
a : ℕ
ha : a ∈ eval cf (Nat.pair (unpair n).fst (0 + m))
a0 : ¬a = 0
k₁ : ℕ
hk₁ : a ∈ evaln (k₁ + 1) cf (Nat.pair (unpair n).fst (0 + m))
k₂ : ℕ
hk₂ : y + Nat.succ m ∈ evaln (k₂ + 1) (rfind' cf) (Nat.pair (unpair n).fst (Nat.succ m))
⊢ ∃ k,
    Nat.pair (unpair n).fst m ≤ k ∧
      ∃ a,
        evaln (k + 1) cf (Nat.pair (unpair n).fst m) = some a ∧
          (if a = 0 then pure m else evaln k (rfind' cf) (Nat.pair (unpair n).fst (m + 1))) = some (Nat.succ y + m)
[PROOFSTEP]
use(max k₁ k₂).succ
[GOAL]
case h
cf : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
n y✝ m✝ : ℕ
hy₁✝ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y✝ + m✝))
hy₂✝ : ∀ {m : ℕ}, m < y✝ → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + m✝)) ∧ ¬a = 0
y : ℕ
IH :
  ∀ (m : ℕ),
    0 ∈ eval cf (Nat.pair (unpair n).fst (y + m)) →
      (∀ {m_1 : ℕ}, m_1 < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0) →
        ∃ k, y + m ∈ evaln (k + 1) (rfind' cf) (Nat.pair (unpair n).fst m)
m : ℕ
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst (Nat.succ y + m))
hy₂ : ∀ {m_1 : ℕ}, m_1 < Nat.succ y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0
a : ℕ
ha : a ∈ eval cf (Nat.pair (unpair n).fst (0 + m))
a0 : ¬a = 0
k₁ : ℕ
hk₁ : a ∈ evaln (k₁ + 1) cf (Nat.pair (unpair n).fst (0 + m))
k₂ : ℕ
hk₂ : y + Nat.succ m ∈ evaln (k₂ + 1) (rfind' cf) (Nat.pair (unpair n).fst (Nat.succ m))
⊢ Nat.pair (unpair n).fst m ≤ Nat.succ (max k₁ k₂) ∧
    ∃ a,
      evaln (Nat.succ (max k₁ k₂) + 1) cf (Nat.pair (unpair n).fst m) = some a ∧
        (if a = 0 then pure m else evaln (Nat.succ (max k₁ k₂)) (rfind' cf) (Nat.pair (unpair n).fst (m + 1))) =
          some (Nat.succ y + m)
[PROOFSTEP]
rw [zero_add] at hk₁ 
[GOAL]
case h
cf : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
n y✝ m✝ : ℕ
hy₁✝ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y✝ + m✝))
hy₂✝ : ∀ {m : ℕ}, m < y✝ → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + m✝)) ∧ ¬a = 0
y : ℕ
IH :
  ∀ (m : ℕ),
    0 ∈ eval cf (Nat.pair (unpair n).fst (y + m)) →
      (∀ {m_1 : ℕ}, m_1 < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0) →
        ∃ k, y + m ∈ evaln (k + 1) (rfind' cf) (Nat.pair (unpair n).fst m)
m : ℕ
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst (Nat.succ y + m))
hy₂ : ∀ {m_1 : ℕ}, m_1 < Nat.succ y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0
a : ℕ
ha : a ∈ eval cf (Nat.pair (unpair n).fst (0 + m))
a0 : ¬a = 0
k₁ : ℕ
hk₁ : a ∈ evaln (k₁ + 1) cf (Nat.pair (unpair n).fst m)
k₂ : ℕ
hk₂ : y + Nat.succ m ∈ evaln (k₂ + 1) (rfind' cf) (Nat.pair (unpair n).fst (Nat.succ m))
⊢ Nat.pair (unpair n).fst m ≤ Nat.succ (max k₁ k₂) ∧
    ∃ a,
      evaln (Nat.succ (max k₁ k₂) + 1) cf (Nat.pair (unpair n).fst m) = some a ∧
        (if a = 0 then pure m else evaln (Nat.succ (max k₁ k₂)) (rfind' cf) (Nat.pair (unpair n).fst (m + 1))) =
          some (Nat.succ y + m)
[PROOFSTEP]
use Nat.le_succ_of_le <| le_max_of_le_left <| Nat.le_of_lt_succ <| evaln_bound hk₁
[GOAL]
case right
cf : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
n y✝ m✝ : ℕ
hy₁✝ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y✝ + m✝))
hy₂✝ : ∀ {m : ℕ}, m < y✝ → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + m✝)) ∧ ¬a = 0
y : ℕ
IH :
  ∀ (m : ℕ),
    0 ∈ eval cf (Nat.pair (unpair n).fst (y + m)) →
      (∀ {m_1 : ℕ}, m_1 < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0) →
        ∃ k, y + m ∈ evaln (k + 1) (rfind' cf) (Nat.pair (unpair n).fst m)
m : ℕ
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst (Nat.succ y + m))
hy₂ : ∀ {m_1 : ℕ}, m_1 < Nat.succ y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0
a : ℕ
ha : a ∈ eval cf (Nat.pair (unpair n).fst (0 + m))
a0 : ¬a = 0
k₁ : ℕ
hk₁ : a ∈ evaln (k₁ + 1) cf (Nat.pair (unpair n).fst m)
k₂ : ℕ
hk₂ : y + Nat.succ m ∈ evaln (k₂ + 1) (rfind' cf) (Nat.pair (unpair n).fst (Nat.succ m))
⊢ ∃ a,
    evaln (Nat.succ (max k₁ k₂) + 1) cf (Nat.pair (unpair n).fst m) = some a ∧
      (if a = 0 then pure m else evaln (Nat.succ (max k₁ k₂)) (rfind' cf) (Nat.pair (unpair n).fst (m + 1))) =
        some (Nat.succ y + m)
[PROOFSTEP]
use a
[GOAL]
case h
cf : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
n y✝ m✝ : ℕ
hy₁✝ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y✝ + m✝))
hy₂✝ : ∀ {m : ℕ}, m < y✝ → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + m✝)) ∧ ¬a = 0
y : ℕ
IH :
  ∀ (m : ℕ),
    0 ∈ eval cf (Nat.pair (unpair n).fst (y + m)) →
      (∀ {m_1 : ℕ}, m_1 < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0) →
        ∃ k, y + m ∈ evaln (k + 1) (rfind' cf) (Nat.pair (unpair n).fst m)
m : ℕ
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst (Nat.succ y + m))
hy₂ : ∀ {m_1 : ℕ}, m_1 < Nat.succ y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0
a : ℕ
ha : a ∈ eval cf (Nat.pair (unpair n).fst (0 + m))
a0 : ¬a = 0
k₁ : ℕ
hk₁ : a ∈ evaln (k₁ + 1) cf (Nat.pair (unpair n).fst m)
k₂ : ℕ
hk₂ : y + Nat.succ m ∈ evaln (k₂ + 1) (rfind' cf) (Nat.pair (unpair n).fst (Nat.succ m))
⊢ evaln (Nat.succ (max k₁ k₂) + 1) cf (Nat.pair (unpair n).fst m) = some a ∧
    (if a = 0 then pure m else evaln (Nat.succ (max k₁ k₂)) (rfind' cf) (Nat.pair (unpair n).fst (m + 1))) =
      some (Nat.succ y + m)
[PROOFSTEP]
use evaln_mono (Nat.succ_le_succ <| Nat.le_succ_of_le <| le_max_left _ _) hk₁
[GOAL]
case right
cf : Code
hf : ∀ {n x : ℕ}, x ∈ eval cf n → ∃ k, x ∈ evaln (k + 1) cf n
n y✝ m✝ : ℕ
hy₁✝ : 0 ∈ eval cf (Nat.pair (unpair n).fst (y✝ + m✝))
hy₂✝ : ∀ {m : ℕ}, m < y✝ → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m + m✝)) ∧ ¬a = 0
y : ℕ
IH :
  ∀ (m : ℕ),
    0 ∈ eval cf (Nat.pair (unpair n).fst (y + m)) →
      (∀ {m_1 : ℕ}, m_1 < y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0) →
        ∃ k, y + m ∈ evaln (k + 1) (rfind' cf) (Nat.pair (unpair n).fst m)
m : ℕ
hy₁ : 0 ∈ eval cf (Nat.pair (unpair n).fst (Nat.succ y + m))
hy₂ : ∀ {m_1 : ℕ}, m_1 < Nat.succ y → ∃ a, a ∈ eval cf (Nat.pair (unpair n).fst (m_1 + m)) ∧ ¬a = 0
a : ℕ
ha : a ∈ eval cf (Nat.pair (unpair n).fst (0 + m))
a0 : ¬a = 0
k₁ : ℕ
hk₁ : a ∈ evaln (k₁ + 1) cf (Nat.pair (unpair n).fst m)
k₂ : ℕ
hk₂ : y + Nat.succ m ∈ evaln (k₂ + 1) (rfind' cf) (Nat.pair (unpair n).fst (Nat.succ m))
⊢ (if a = 0 then pure m else evaln (Nat.succ (max k₁ k₂)) (rfind' cf) (Nat.pair (unpair n).fst (m + 1))) =
    some (Nat.succ y + m)
[PROOFSTEP]
simpa [Nat.succ_eq_add_one, a0, -max_eq_left, -max_eq_right, add_comm, add_left_comm] using
  evaln_mono (Nat.succ_le_succ <| le_max_right _ _) hk₂
[GOAL]
⊢ Primrec Nat.Partrec.Code.G
[PROOFSTEP]
have a := (Primrec.ofNat (ℕ × Code)).comp (Primrec.list_length (α := List (Option ℕ)))
[GOAL]
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
⊢ Primrec Nat.Partrec.Code.G
[PROOFSTEP]
have k := Primrec.fst.comp a
[GOAL]
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a)).fst
⊢ Primrec Nat.Partrec.Code.G
[PROOFSTEP]
refine' Primrec.option_some.comp (Primrec.list_map (Primrec.list_range.comp k) (_ : Primrec _))
[GOAL]
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a)).fst
⊢ Primrec fun p =>
    (fun a n =>
        Nat.casesOn (ofNat (ℕ × Code) (List.length a)).fst Option.none fun k' =>
          Code.recOn (ofNat (ℕ × Code) (List.length a)).snd (some 0) (some (Nat.succ n)) (some (unpair n).fst)
            (some (unpair n).snd)
            (fun cf cg x x => do
              let x ← Nat.Partrec.Code.lup a ((ofNat (ℕ × Code) (List.length a)).fst, cf) n
              let y ← Nat.Partrec.Code.lup a ((ofNat (ℕ × Code) (List.length a)).fst, cg) n
              some (Nat.pair x y))
            (fun cf cg x x => do
              let x ← Nat.Partrec.Code.lup a ((ofNat (ℕ × Code) (List.length a)).fst, cg) n
              Nat.Partrec.Code.lup a ((ofNat (ℕ × Code) (List.length a)).fst, cf) x)
            (fun cf cg x x =>
              let z := (unpair n).fst;
              Nat.casesOn (unpair n).snd (Nat.Partrec.Code.lup a ((ofNat (ℕ × Code) (List.length a)).fst, cf) z)
                fun y => do
                let i ← Nat.Partrec.Code.lup a (k', (ofNat (ℕ × Code) (List.length a)).snd) (Nat.pair z y)
                Nat.Partrec.Code.lup a ((ofNat (ℕ × Code) (List.length a)).fst, cg) (Nat.pair z (Nat.pair y i)))
            fun cf x =>
            let z := (unpair n).fst;
            let m := (unpair n).snd;
            do
            let x ← Nat.Partrec.Code.lup a ((ofNat (ℕ × Code) (List.length a)).fst, cf) (Nat.pair z m)
            Nat.casesOn x (some m) fun x =>
                Nat.Partrec.Code.lup a (k', (ofNat (ℕ × Code) (List.length a)).snd) (Nat.pair z (m + 1)))
      p.fst p.snd
[PROOFSTEP]
replace k := k.comp (Primrec.fst (β := ℕ))
[GOAL]
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
⊢ Primrec fun p =>
    (fun a n =>
        Nat.casesOn (ofNat (ℕ × Code) (List.length a)).fst Option.none fun k' =>
          Code.recOn (ofNat (ℕ × Code) (List.length a)).snd (some 0) (some (Nat.succ n)) (some (unpair n).fst)
            (some (unpair n).snd)
            (fun cf cg x x => do
              let x ← Nat.Partrec.Code.lup a ((ofNat (ℕ × Code) (List.length a)).fst, cf) n
              let y ← Nat.Partrec.Code.lup a ((ofNat (ℕ × Code) (List.length a)).fst, cg) n
              some (Nat.pair x y))
            (fun cf cg x x => do
              let x ← Nat.Partrec.Code.lup a ((ofNat (ℕ × Code) (List.length a)).fst, cg) n
              Nat.Partrec.Code.lup a ((ofNat (ℕ × Code) (List.length a)).fst, cf) x)
            (fun cf cg x x =>
              let z := (unpair n).fst;
              Nat.casesOn (unpair n).snd (Nat.Partrec.Code.lup a ((ofNat (ℕ × Code) (List.length a)).fst, cf) z)
                fun y => do
                let i ← Nat.Partrec.Code.lup a (k', (ofNat (ℕ × Code) (List.length a)).snd) (Nat.pair z y)
                Nat.Partrec.Code.lup a ((ofNat (ℕ × Code) (List.length a)).fst, cg) (Nat.pair z (Nat.pair y i)))
            fun cf x =>
            let z := (unpair n).fst;
            let m := (unpair n).snd;
            do
            let x ← Nat.Partrec.Code.lup a ((ofNat (ℕ × Code) (List.length a)).fst, cf) (Nat.pair z m)
            Nat.casesOn x (some m) fun x =>
                Nat.Partrec.Code.lup a (k', (ofNat (ℕ × Code) (List.length a)).snd) (Nat.pair z (m + 1)))
      p.fst p.snd
[PROOFSTEP]
have n := Primrec.snd (α := List (List (Option ℕ))) (β := ℕ)
[GOAL]
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n : Primrec Prod.snd
⊢ Primrec fun p =>
    (fun a n =>
        Nat.casesOn (ofNat (ℕ × Code) (List.length a)).fst Option.none fun k' =>
          Code.recOn (ofNat (ℕ × Code) (List.length a)).snd (some 0) (some (Nat.succ n)) (some (unpair n).fst)
            (some (unpair n).snd)
            (fun cf cg x x => do
              let x ← Nat.Partrec.Code.lup a ((ofNat (ℕ × Code) (List.length a)).fst, cf) n
              let y ← Nat.Partrec.Code.lup a ((ofNat (ℕ × Code) (List.length a)).fst, cg) n
              some (Nat.pair x y))
            (fun cf cg x x => do
              let x ← Nat.Partrec.Code.lup a ((ofNat (ℕ × Code) (List.length a)).fst, cg) n
              Nat.Partrec.Code.lup a ((ofNat (ℕ × Code) (List.length a)).fst, cf) x)
            (fun cf cg x x =>
              let z := (unpair n).fst;
              Nat.casesOn (unpair n).snd (Nat.Partrec.Code.lup a ((ofNat (ℕ × Code) (List.length a)).fst, cf) z)
                fun y => do
                let i ← Nat.Partrec.Code.lup a (k', (ofNat (ℕ × Code) (List.length a)).snd) (Nat.pair z y)
                Nat.Partrec.Code.lup a ((ofNat (ℕ × Code) (List.length a)).fst, cg) (Nat.pair z (Nat.pair y i)))
            fun cf x =>
            let z := (unpair n).fst;
            let m := (unpair n).snd;
            do
            let x ← Nat.Partrec.Code.lup a ((ofNat (ℕ × Code) (List.length a)).fst, cf) (Nat.pair z m)
            Nat.casesOn x (some m) fun x =>
                Nat.Partrec.Code.lup a (k', (ofNat (ℕ × Code) (List.length a)).snd) (Nat.pair z (m + 1)))
      p.fst p.snd
[PROOFSTEP]
refine' Primrec.nat_casesOn k (_root_.Primrec.const Option.none) (_ : Primrec _)
[GOAL]
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n : Primrec Prod.snd
⊢ Primrec fun p =>
    (fun p n =>
        (fun k' =>
            Code.recOn (ofNat (ℕ × Code) (List.length p.fst)).snd (some 0) (some (Nat.succ p.snd))
              (some (unpair p.snd).fst) (some (unpair p.snd).snd)
              (fun cf cg x x => do
                let x ← Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cf) p.snd
                let y ← Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cg) p.snd
                some (Nat.pair x y))
              (fun cf cg x x => do
                let x ← Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cg) p.snd
                Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cf) x)
              (fun cf cg x x =>
                let z := (unpair p.snd).fst;
                Nat.casesOn (unpair p.snd).snd
                  (Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cf) z) fun y => do
                  let i ← Nat.Partrec.Code.lup p.fst (k', (ofNat (ℕ × Code) (List.length p.fst)).snd) (Nat.pair z y)
                  Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cg)
                      (Nat.pair z (Nat.pair y i)))
              fun cf x =>
              let z := (unpair p.snd).fst;
              let m := (unpair p.snd).snd;
              do
              let x ← Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cf) (Nat.pair z m)
              Nat.casesOn x (some m) fun x =>
                  Nat.Partrec.Code.lup p.fst (k', (ofNat (ℕ × Code) (List.length p.fst)).snd) (Nat.pair z (m + 1)))
          n)
      p.fst p.snd
[PROOFSTEP]
have k := k.comp (Primrec.fst (β := ℕ))
[GOAL]
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n : Primrec Prod.snd
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
⊢ Primrec fun p =>
    (fun p n =>
        (fun k' =>
            Code.recOn (ofNat (ℕ × Code) (List.length p.fst)).snd (some 0) (some (Nat.succ p.snd))
              (some (unpair p.snd).fst) (some (unpair p.snd).snd)
              (fun cf cg x x => do
                let x ← Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cf) p.snd
                let y ← Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cg) p.snd
                some (Nat.pair x y))
              (fun cf cg x x => do
                let x ← Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cg) p.snd
                Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cf) x)
              (fun cf cg x x =>
                let z := (unpair p.snd).fst;
                Nat.casesOn (unpair p.snd).snd
                  (Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cf) z) fun y => do
                  let i ← Nat.Partrec.Code.lup p.fst (k', (ofNat (ℕ × Code) (List.length p.fst)).snd) (Nat.pair z y)
                  Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cg)
                      (Nat.pair z (Nat.pair y i)))
              fun cf x =>
              let z := (unpair p.snd).fst;
              let m := (unpair p.snd).snd;
              do
              let x ← Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cf) (Nat.pair z m)
              Nat.casesOn x (some m) fun x =>
                  Nat.Partrec.Code.lup p.fst (k', (ofNat (ℕ × Code) (List.length p.fst)).snd) (Nat.pair z (m + 1)))
          n)
      p.fst p.snd
[PROOFSTEP]
have n := n.comp (Primrec.fst (β := ℕ))
[GOAL]
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝ : Primrec Prod.snd
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n : Primrec fun a => a.fst.snd
⊢ Primrec fun p =>
    (fun p n =>
        (fun k' =>
            Code.recOn (ofNat (ℕ × Code) (List.length p.fst)).snd (some 0) (some (Nat.succ p.snd))
              (some (unpair p.snd).fst) (some (unpair p.snd).snd)
              (fun cf cg x x => do
                let x ← Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cf) p.snd
                let y ← Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cg) p.snd
                some (Nat.pair x y))
              (fun cf cg x x => do
                let x ← Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cg) p.snd
                Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cf) x)
              (fun cf cg x x =>
                let z := (unpair p.snd).fst;
                Nat.casesOn (unpair p.snd).snd
                  (Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cf) z) fun y => do
                  let i ← Nat.Partrec.Code.lup p.fst (k', (ofNat (ℕ × Code) (List.length p.fst)).snd) (Nat.pair z y)
                  Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cg)
                      (Nat.pair z (Nat.pair y i)))
              fun cf x =>
              let z := (unpair p.snd).fst;
              let m := (unpair p.snd).snd;
              do
              let x ← Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cf) (Nat.pair z m)
              Nat.casesOn x (some m) fun x =>
                  Nat.Partrec.Code.lup p.fst (k', (ofNat (ℕ × Code) (List.length p.fst)).snd) (Nat.pair z (m + 1)))
          n)
      p.fst p.snd
[PROOFSTEP]
have k' := Primrec.snd (α := List (List (Option ℕ)) × ℕ) (β := ℕ)
[GOAL]
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝ : Primrec Prod.snd
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
⊢ Primrec fun p =>
    (fun p n =>
        (fun k' =>
            Code.recOn (ofNat (ℕ × Code) (List.length p.fst)).snd (some 0) (some (Nat.succ p.snd))
              (some (unpair p.snd).fst) (some (unpair p.snd).snd)
              (fun cf cg x x => do
                let x ← Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cf) p.snd
                let y ← Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cg) p.snd
                some (Nat.pair x y))
              (fun cf cg x x => do
                let x ← Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cg) p.snd
                Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cf) x)
              (fun cf cg x x =>
                let z := (unpair p.snd).fst;
                Nat.casesOn (unpair p.snd).snd
                  (Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cf) z) fun y => do
                  let i ← Nat.Partrec.Code.lup p.fst (k', (ofNat (ℕ × Code) (List.length p.fst)).snd) (Nat.pair z y)
                  Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cg)
                      (Nat.pair z (Nat.pair y i)))
              fun cf x =>
              let z := (unpair p.snd).fst;
              let m := (unpair p.snd).snd;
              do
              let x ← Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cf) (Nat.pair z m)
              Nat.casesOn x (some m) fun x =>
                  Nat.Partrec.Code.lup p.fst (k', (ofNat (ℕ × Code) (List.length p.fst)).snd) (Nat.pair z (m + 1)))
          n)
      p.fst p.snd
[PROOFSTEP]
have c := Primrec.snd.comp (a.comp <| (Primrec.fst (β := ℕ)).comp (Primrec.fst (β := ℕ)))
[GOAL]
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝ : Primrec Prod.snd
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
⊢ Primrec fun p =>
    (fun p n =>
        (fun k' =>
            Code.recOn (ofNat (ℕ × Code) (List.length p.fst)).snd (some 0) (some (Nat.succ p.snd))
              (some (unpair p.snd).fst) (some (unpair p.snd).snd)
              (fun cf cg x x => do
                let x ← Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cf) p.snd
                let y ← Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cg) p.snd
                some (Nat.pair x y))
              (fun cf cg x x => do
                let x ← Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cg) p.snd
                Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cf) x)
              (fun cf cg x x =>
                let z := (unpair p.snd).fst;
                Nat.casesOn (unpair p.snd).snd
                  (Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cf) z) fun y => do
                  let i ← Nat.Partrec.Code.lup p.fst (k', (ofNat (ℕ × Code) (List.length p.fst)).snd) (Nat.pair z y)
                  Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cg)
                      (Nat.pair z (Nat.pair y i)))
              fun cf x =>
              let z := (unpair p.snd).fst;
              let m := (unpair p.snd).snd;
              do
              let x ← Nat.Partrec.Code.lup p.fst ((ofNat (ℕ × Code) (List.length p.fst)).fst, cf) (Nat.pair z m)
              Nat.casesOn x (some m) fun x =>
                  Nat.Partrec.Code.lup p.fst (k', (ofNat (ℕ × Code) (List.length p.fst)).snd) (Nat.pair z (m + 1)))
          n)
      p.fst p.snd
[PROOFSTEP]
apply
  Nat.Partrec.Code.rec_prim c (_root_.Primrec.const (some 0)) (Primrec.option_some.comp (_root_.Primrec.succ.comp n))
    (Primrec.option_some.comp (Primrec.fst.comp <| Primrec.unpair.comp n))
    (Primrec.option_some.comp (Primrec.snd.comp <| Primrec.unpair.comp n))
[GOAL]
case hpr
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝ : Primrec Prod.snd
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
⊢ Primrec fun a => do
    let x ←
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) a.fst.fst.snd
    let y ←
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
          a.fst.fst.snd
    some (Nat.pair x y)
[PROOFSTEP]
have L :=
  (Primrec.fst.comp Primrec.fst).comp
    (Primrec.fst (α := (List (List (Option ℕ)) × ℕ) × ℕ) (β := Code × Code × Option ℕ × Option ℕ))
[GOAL]
case hpr
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝ : Primrec Prod.snd
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
⊢ Primrec fun a => do
    let x ←
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) a.fst.fst.snd
    let y ←
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
          a.fst.fst.snd
    some (Nat.pair x y)
[PROOFSTEP]
have k := k.comp (Primrec.fst (β := Code × Code × Option ℕ × Option ℕ))
[GOAL]
case hpr
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
⊢ Primrec fun a => do
    let x ←
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) a.fst.fst.snd
    let y ←
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
          a.fst.fst.snd
    some (Nat.pair x y)
[PROOFSTEP]
have n := n.comp (Primrec.fst (β := Code × Code × Option ℕ × Option ℕ))
[GOAL]
case hpr
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
⊢ Primrec fun a => do
    let x ←
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) a.fst.fst.snd
    let y ←
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
          a.fst.fst.snd
    some (Nat.pair x y)
[PROOFSTEP]
have cf :=
  Primrec.fst.comp (Primrec.snd (α := (List (List (Option ℕ)) × ℕ) × ℕ) (β := Code × Code × Option ℕ × Option ℕ))
[GOAL]
case hpr
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
⊢ Primrec fun a => do
    let x ←
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) a.fst.fst.snd
    let y ←
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
          a.fst.fst.snd
    some (Nat.pair x y)
[PROOFSTEP]
have cg :=
  (Primrec.fst.comp Primrec.snd).comp
    (Primrec.snd (α := (List (List (Option ℕ)) × ℕ) × ℕ) (β := Code × Code × Option ℕ × Option ℕ))
[GOAL]
case hpr
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
⊢ Primrec fun a => do
    let x ←
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) a.fst.fst.snd
    let y ←
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
          a.fst.fst.snd
    some (Nat.pair x y)
[PROOFSTEP]
refine Primrec.option_bind (hlup.comp <| L.pair <| (k.pair cf).pair n) ?_
[GOAL]
case hpr
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
⊢ Primrec₂ fun a x => do
    let y ←
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
          a.fst.fst.snd
    some (Nat.pair x y)
[PROOFSTEP]
unfold Primrec₂
[GOAL]
case hpr
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
⊢ Primrec fun p =>
    (fun a x => do
        let y ←
          Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
              a.fst.fst.snd
        some (Nat.pair x y))
      p.fst p.snd
[PROOFSTEP]
conv =>
  congr
  · ext p
    dsimp only []
    erw [Option.bind_eq_bind, ← Option.map_eq_bind]
[GOAL]
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
| Primrec fun p =>
    (fun a x => do
        let y ←
          Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
              a.fst.fst.snd
        some (Nat.pair x y))
      p.fst p.snd
[PROOFSTEP]
  congr
  · ext p
    dsimp only []
    erw [Option.bind_eq_bind, ← Option.map_eq_bind]
[GOAL]
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
| Primrec fun p =>
    (fun a x => do
        let y ←
          Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
              a.fst.fst.snd
        some (Nat.pair x y))
      p.fst p.snd
[PROOFSTEP]
  congr
  · ext p
    dsimp only []
    erw [Option.bind_eq_bind, ← Option.map_eq_bind]
[GOAL]
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
| Primrec fun p =>
    (fun a x => do
        let y ←
          Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
              a.fst.fst.snd
        some (Nat.pair x y))
      p.fst p.snd
[PROOFSTEP]
congr
[GOAL]
case f
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
| fun p =>
    (fun a x => do
        let y ←
          Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
              a.fst.fst.snd
        some (Nat.pair x y))
      p.fst p.snd
[PROOFSTEP]
· ext p
  dsimp only []
  erw [Option.bind_eq_bind, ← Option.map_eq_bind]
[GOAL]
case f
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
| fun p =>
    (fun a x => do
        let y ←
          Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
              a.fst.fst.snd
        some (Nat.pair x y))
      p.fst p.snd
[PROOFSTEP]
  ext p
  dsimp only []
  erw [Option.bind_eq_bind, ← Option.map_eq_bind]
[GOAL]
case f
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
| fun p =>
    (fun a x => do
        let y ←
          Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
              a.fst.fst.snd
        some (Nat.pair x y))
      p.fst p.snd
[PROOFSTEP]
  ext p
  dsimp only []
  erw [Option.bind_eq_bind, ← Option.map_eq_bind]
[GOAL]
case f
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
| fun p =>
    (fun a x => do
        let y ←
          Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
              a.fst.fst.snd
        some (Nat.pair x y))
      p.fst p.snd
[PROOFSTEP]
ext p
[GOAL]
case f.h
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
p : (((List (List (Option ℕ)) × ℕ) × ℕ) × Code × Code × Option ℕ × Option ℕ) × ℕ
| (fun a x => do
      let y ←
        Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
            a.fst.fst.snd
      some (Nat.pair x y))
    p.fst p.snd
[PROOFSTEP]
dsimp only []
[GOAL]
case f.h
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
p : (((List (List (Option ℕ)) × ℕ) × ℕ) × Code × Code × Option ℕ × Option ℕ) × ℕ
| do
    let y ←
      Nat.Partrec.Code.lup p.fst.fst.fst.fst ((ofNat (ℕ × Code) (List.length p.fst.fst.fst.fst)).fst, p.fst.snd.snd.fst)
          p.fst.fst.fst.snd
    some (Nat.pair p.snd y)
[PROOFSTEP]
erw [Option.bind_eq_bind, ← Option.map_eq_bind]
[GOAL]
case hpr
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
⊢ Primrec fun p =>
    Option.map (fun y => Nat.pair p.snd y)
      (Nat.Partrec.Code.lup p.fst.fst.fst.fst
        ((ofNat (ℕ × Code) (List.length p.fst.fst.fst.fst)).fst, p.fst.snd.snd.fst) p.fst.fst.fst.snd)
[PROOFSTEP]
refine Primrec.option_map ((hlup.comp <| L.pair <| (k.pair cg).pair n).comp Primrec.fst) ?_
[GOAL]
case hpr
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
⊢ Primrec₂ fun p y => Nat.pair p.snd y
[PROOFSTEP]
unfold Primrec₂
[GOAL]
case hpr
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
⊢ Primrec fun p => (fun p y => Nat.pair p.snd y) p.fst p.snd
[PROOFSTEP]
exact Primrec₂.natPair.comp (Primrec.snd.comp Primrec.fst) Primrec.snd
[GOAL]
case hco
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝ : Primrec Prod.snd
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
⊢ Primrec fun a => do
    let x ←
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
          a.fst.fst.snd
    Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) x
[PROOFSTEP]
have L :=
  (Primrec.fst.comp Primrec.fst).comp
    (Primrec.fst (α := (List (List (Option ℕ)) × ℕ) × ℕ) (β := Code × Code × Option ℕ × Option ℕ))
[GOAL]
case hco
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝ : Primrec Prod.snd
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
⊢ Primrec fun a => do
    let x ←
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
          a.fst.fst.snd
    Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) x
[PROOFSTEP]
have k := k.comp (Primrec.fst (β := Code × Code × Option ℕ × Option ℕ))
[GOAL]
case hco
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
⊢ Primrec fun a => do
    let x ←
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
          a.fst.fst.snd
    Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) x
[PROOFSTEP]
have n := n.comp (Primrec.fst (β := Code × Code × Option ℕ × Option ℕ))
[GOAL]
case hco
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
⊢ Primrec fun a => do
    let x ←
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
          a.fst.fst.snd
    Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) x
[PROOFSTEP]
have cf :=
  Primrec.fst.comp (Primrec.snd (α := (List (List (Option ℕ)) × ℕ) × ℕ) (β := Code × Code × Option ℕ × Option ℕ))
[GOAL]
case hco
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
⊢ Primrec fun a => do
    let x ←
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
          a.fst.fst.snd
    Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) x
[PROOFSTEP]
have cg :=
  (Primrec.fst.comp Primrec.snd).comp
    (Primrec.snd (α := (List (List (Option ℕ)) × ℕ) × ℕ) (β := Code × Code × Option ℕ × Option ℕ))
[GOAL]
case hco
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
⊢ Primrec fun a => do
    let x ←
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
          a.fst.fst.snd
    Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) x
[PROOFSTEP]
refine Primrec.option_bind (hlup.comp <| L.pair <| (k.pair cg).pair n) ?_
[GOAL]
case hco
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
⊢ Primrec₂ fun a x =>
    Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) x
[PROOFSTEP]
unfold Primrec₂
[GOAL]
case hco
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
⊢ Primrec fun p =>
    (fun a x => Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) x)
      p.fst p.snd
[PROOFSTEP]
have h := hlup.comp ((L.comp Primrec.fst).pair <| ((k.pair cf).comp Primrec.fst).pair Primrec.snd)
[GOAL]
case hco
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
h :
  Primrec fun a =>
    Nat.Partrec.Code.lup
      (a.fst.fst.fst.fst, ((ofNat (ℕ × Code) (List.length a.fst.fst.fst.fst)).fst, a.fst.snd.fst), a.snd).fst
      (a.fst.fst.fst.fst, ((ofNat (ℕ × Code) (List.length a.fst.fst.fst.fst)).fst, a.fst.snd.fst), a.snd).snd.fst
      (a.fst.fst.fst.fst, ((ofNat (ℕ × Code) (List.length a.fst.fst.fst.fst)).fst, a.fst.snd.fst), a.snd).snd.snd
⊢ Primrec fun p =>
    (fun a x => Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) x)
      p.fst p.snd
[PROOFSTEP]
exact h
[GOAL]
case hpc
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝ : Primrec Prod.snd
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
⊢ Primrec fun a =>
    let z := (unpair a.fst.fst.snd).fst;
    Nat.casesOn (unpair a.fst.fst.snd).snd
      (Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) z) fun y => do
      let i ←
        Nat.Partrec.Code.lup a.fst.fst.fst (a.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).snd)
            (Nat.pair z y)
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
          (Nat.pair z (Nat.pair y i))
[PROOFSTEP]
have L :=
  (Primrec.fst.comp Primrec.fst).comp
    (Primrec.fst (α := (List (List (Option ℕ)) × ℕ) × ℕ) (β := Code × Code × Option ℕ × Option ℕ))
[GOAL]
case hpc
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝ : Primrec Prod.snd
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
⊢ Primrec fun a =>
    let z := (unpair a.fst.fst.snd).fst;
    Nat.casesOn (unpair a.fst.fst.snd).snd
      (Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) z) fun y => do
      let i ←
        Nat.Partrec.Code.lup a.fst.fst.fst (a.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).snd)
            (Nat.pair z y)
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
          (Nat.pair z (Nat.pair y i))
[PROOFSTEP]
have k := k.comp (Primrec.fst (β := Code × Code × Option ℕ × Option ℕ))
[GOAL]
case hpc
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
⊢ Primrec fun a =>
    let z := (unpair a.fst.fst.snd).fst;
    Nat.casesOn (unpair a.fst.fst.snd).snd
      (Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) z) fun y => do
      let i ←
        Nat.Partrec.Code.lup a.fst.fst.fst (a.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).snd)
            (Nat.pair z y)
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
          (Nat.pair z (Nat.pair y i))
[PROOFSTEP]
have n := n.comp (Primrec.fst (β := Code × Code × Option ℕ × Option ℕ))
[GOAL]
case hpc
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
⊢ Primrec fun a =>
    let z := (unpair a.fst.fst.snd).fst;
    Nat.casesOn (unpair a.fst.fst.snd).snd
      (Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) z) fun y => do
      let i ←
        Nat.Partrec.Code.lup a.fst.fst.fst (a.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).snd)
            (Nat.pair z y)
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
          (Nat.pair z (Nat.pair y i))
[PROOFSTEP]
have cf :=
  Primrec.fst.comp (Primrec.snd (α := (List (List (Option ℕ)) × ℕ) × ℕ) (β := Code × Code × Option ℕ × Option ℕ))
[GOAL]
case hpc
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
⊢ Primrec fun a =>
    let z := (unpair a.fst.fst.snd).fst;
    Nat.casesOn (unpair a.fst.fst.snd).snd
      (Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) z) fun y => do
      let i ←
        Nat.Partrec.Code.lup a.fst.fst.fst (a.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).snd)
            (Nat.pair z y)
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
          (Nat.pair z (Nat.pair y i))
[PROOFSTEP]
have cg :=
  (Primrec.fst.comp Primrec.snd).comp
    (Primrec.snd (α := (List (List (Option ℕ)) × ℕ) × ℕ) (β := Code × Code × Option ℕ × Option ℕ))
[GOAL]
case hpc
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
⊢ Primrec fun a =>
    let z := (unpair a.fst.fst.snd).fst;
    Nat.casesOn (unpair a.fst.fst.snd).snd
      (Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) z) fun y => do
      let i ←
        Nat.Partrec.Code.lup a.fst.fst.fst (a.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).snd)
            (Nat.pair z y)
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
          (Nat.pair z (Nat.pair y i))
[PROOFSTEP]
have z := Primrec.fst.comp (Primrec.unpair.comp n)
[GOAL]
case hpc
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
z : Primrec fun a => (unpair a.fst.fst.snd).fst
⊢ Primrec fun a =>
    let z := (unpair a.fst.fst.snd).fst;
    Nat.casesOn (unpair a.fst.fst.snd).snd
      (Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) z) fun y => do
      let i ←
        Nat.Partrec.Code.lup a.fst.fst.fst (a.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).snd)
            (Nat.pair z y)
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
          (Nat.pair z (Nat.pair y i))
[PROOFSTEP]
refine'
  Primrec.nat_casesOn (Primrec.snd.comp (Primrec.unpair.comp n)) (hlup.comp <| L.pair <| (k.pair cf).pair z)
    (_ : Primrec _)
[GOAL]
case hpc
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
z : Primrec fun a => (unpair a.fst.fst.snd).fst
⊢ Primrec fun p =>
    (fun a n =>
        (fun y => do
            let i ←
              Nat.Partrec.Code.lup a.fst.fst.fst (a.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).snd)
                  (Nat.pair (unpair a.fst.fst.snd).fst y)
            Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
                (Nat.pair (unpair a.fst.fst.snd).fst (Nat.pair y i)))
          n)
      p.fst p.snd
[PROOFSTEP]
have L := L.comp (Primrec.fst (β := ℕ))
[GOAL]
case hpc
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L✝ : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
z : Primrec fun a => (unpair a.fst.fst.snd).fst
L : Primrec fun a => a.fst.fst.fst.fst
⊢ Primrec fun p =>
    (fun a n =>
        (fun y => do
            let i ←
              Nat.Partrec.Code.lup a.fst.fst.fst (a.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).snd)
                  (Nat.pair (unpair a.fst.fst.snd).fst y)
            Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
                (Nat.pair (unpair a.fst.fst.snd).fst (Nat.pair y i)))
          n)
      p.fst p.snd
[PROOFSTEP]
have z := z.comp (Primrec.fst (β := ℕ))
[GOAL]
case hpc
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L✝ : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
z✝ : Primrec fun a => (unpair a.fst.fst.snd).fst
L : Primrec fun a => a.fst.fst.fst.fst
z : Primrec fun a => (unpair a.fst.fst.fst.snd).fst
⊢ Primrec fun p =>
    (fun a n =>
        (fun y => do
            let i ←
              Nat.Partrec.Code.lup a.fst.fst.fst (a.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).snd)
                  (Nat.pair (unpair a.fst.fst.snd).fst y)
            Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
                (Nat.pair (unpair a.fst.fst.snd).fst (Nat.pair y i)))
          n)
      p.fst p.snd
[PROOFSTEP]
have y := Primrec.snd (α := ((List (List (Option ℕ)) × ℕ) × ℕ) × Code × Code × Option ℕ × Option ℕ) (β := ℕ)
[GOAL]
case hpc
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L✝ : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
z✝ : Primrec fun a => (unpair a.fst.fst.snd).fst
L : Primrec fun a => a.fst.fst.fst.fst
z : Primrec fun a => (unpair a.fst.fst.fst.snd).fst
y : Primrec Prod.snd
⊢ Primrec fun p =>
    (fun a n =>
        (fun y => do
            let i ←
              Nat.Partrec.Code.lup a.fst.fst.fst (a.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).snd)
                  (Nat.pair (unpair a.fst.fst.snd).fst y)
            Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
                (Nat.pair (unpair a.fst.fst.snd).fst (Nat.pair y i)))
          n)
      p.fst p.snd
[PROOFSTEP]
have h₁ := hlup.comp <| L.pair <| (((k'.pair c).comp Primrec.fst).comp Primrec.fst).pair (Primrec₂.natPair.comp z y)
[GOAL]
case hpc
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L✝ : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
z✝ : Primrec fun a => (unpair a.fst.fst.snd).fst
L : Primrec fun a => a.fst.fst.fst.fst
z : Primrec fun a => (unpair a.fst.fst.fst.snd).fst
y : Primrec Prod.snd
h₁ :
  Primrec fun a =>
    Nat.Partrec.Code.lup
      (a.fst.fst.fst.fst, (a.fst.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst.fst)).snd),
          Nat.pair (unpair a.fst.fst.fst.snd).fst a.snd).fst
      (a.fst.fst.fst.fst, (a.fst.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst.fst)).snd),
            Nat.pair (unpair a.fst.fst.fst.snd).fst a.snd).snd.fst
      (a.fst.fst.fst.fst, (a.fst.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst.fst)).snd),
            Nat.pair (unpair a.fst.fst.fst.snd).fst a.snd).snd.snd
⊢ Primrec fun p =>
    (fun a n =>
        (fun y => do
            let i ←
              Nat.Partrec.Code.lup a.fst.fst.fst (a.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).snd)
                  (Nat.pair (unpair a.fst.fst.snd).fst y)
            Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.snd.fst)
                (Nat.pair (unpair a.fst.fst.snd).fst (Nat.pair y i)))
          n)
      p.fst p.snd
[PROOFSTEP]
refine' Primrec.option_bind h₁ (_ : Primrec _)
[GOAL]
case hpc
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L✝ : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
z✝ : Primrec fun a => (unpair a.fst.fst.snd).fst
L : Primrec fun a => a.fst.fst.fst.fst
z : Primrec fun a => (unpair a.fst.fst.fst.snd).fst
y : Primrec Prod.snd
h₁ :
  Primrec fun a =>
    Nat.Partrec.Code.lup
      (a.fst.fst.fst.fst, (a.fst.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst.fst)).snd),
          Nat.pair (unpair a.fst.fst.fst.snd).fst a.snd).fst
      (a.fst.fst.fst.fst, (a.fst.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst.fst)).snd),
            Nat.pair (unpair a.fst.fst.fst.snd).fst a.snd).snd.fst
      (a.fst.fst.fst.fst, (a.fst.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst.fst)).snd),
            Nat.pair (unpair a.fst.fst.fst.snd).fst a.snd).snd.snd
⊢ Primrec fun p =>
    (fun p i =>
        Nat.Partrec.Code.lup p.fst.fst.fst.fst
          ((ofNat (ℕ × Code) (List.length p.fst.fst.fst.fst)).fst, p.fst.snd.snd.fst)
          (Nat.pair (unpair p.fst.fst.fst.snd).fst (Nat.pair p.snd i)))
      p.fst p.snd
[PROOFSTEP]
have z := z.comp (Primrec.fst (β := ℕ))
[GOAL]
case hpc
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L✝ : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
z✝¹ : Primrec fun a => (unpair a.fst.fst.snd).fst
L : Primrec fun a => a.fst.fst.fst.fst
z✝ : Primrec fun a => (unpair a.fst.fst.fst.snd).fst
y : Primrec Prod.snd
h₁ :
  Primrec fun a =>
    Nat.Partrec.Code.lup
      (a.fst.fst.fst.fst, (a.fst.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst.fst)).snd),
          Nat.pair (unpair a.fst.fst.fst.snd).fst a.snd).fst
      (a.fst.fst.fst.fst, (a.fst.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst.fst)).snd),
            Nat.pair (unpair a.fst.fst.fst.snd).fst a.snd).snd.fst
      (a.fst.fst.fst.fst, (a.fst.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst.fst)).snd),
            Nat.pair (unpair a.fst.fst.fst.snd).fst a.snd).snd.snd
z : Primrec fun a => (unpair a.fst.fst.fst.fst.snd).fst
⊢ Primrec fun p =>
    (fun p i =>
        Nat.Partrec.Code.lup p.fst.fst.fst.fst
          ((ofNat (ℕ × Code) (List.length p.fst.fst.fst.fst)).fst, p.fst.snd.snd.fst)
          (Nat.pair (unpair p.fst.fst.fst.snd).fst (Nat.pair p.snd i)))
      p.fst p.snd
[PROOFSTEP]
have y := y.comp (Primrec.fst (β := ℕ))
[GOAL]
case hpc
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L✝ : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
z✝¹ : Primrec fun a => (unpair a.fst.fst.snd).fst
L : Primrec fun a => a.fst.fst.fst.fst
z✝ : Primrec fun a => (unpair a.fst.fst.fst.snd).fst
y✝ : Primrec Prod.snd
h₁ :
  Primrec fun a =>
    Nat.Partrec.Code.lup
      (a.fst.fst.fst.fst, (a.fst.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst.fst)).snd),
          Nat.pair (unpair a.fst.fst.fst.snd).fst a.snd).fst
      (a.fst.fst.fst.fst, (a.fst.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst.fst)).snd),
            Nat.pair (unpair a.fst.fst.fst.snd).fst a.snd).snd.fst
      (a.fst.fst.fst.fst, (a.fst.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst.fst)).snd),
            Nat.pair (unpair a.fst.fst.fst.snd).fst a.snd).snd.snd
z : Primrec fun a => (unpair a.fst.fst.fst.fst.snd).fst
y : Primrec fun a => a.fst.snd
⊢ Primrec fun p =>
    (fun p i =>
        Nat.Partrec.Code.lup p.fst.fst.fst.fst
          ((ofNat (ℕ × Code) (List.length p.fst.fst.fst.fst)).fst, p.fst.snd.snd.fst)
          (Nat.pair (unpair p.fst.fst.fst.snd).fst (Nat.pair p.snd i)))
      p.fst p.snd
[PROOFSTEP]
have i := Primrec.snd (α := (((List (List (Option ℕ)) × ℕ) × ℕ) × Code × Code × Option ℕ × Option ℕ) × ℕ) (β := ℕ)
[GOAL]
case hpc
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L✝ : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
z✝¹ : Primrec fun a => (unpair a.fst.fst.snd).fst
L : Primrec fun a => a.fst.fst.fst.fst
z✝ : Primrec fun a => (unpair a.fst.fst.fst.snd).fst
y✝ : Primrec Prod.snd
h₁ :
  Primrec fun a =>
    Nat.Partrec.Code.lup
      (a.fst.fst.fst.fst, (a.fst.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst.fst)).snd),
          Nat.pair (unpair a.fst.fst.fst.snd).fst a.snd).fst
      (a.fst.fst.fst.fst, (a.fst.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst.fst)).snd),
            Nat.pair (unpair a.fst.fst.fst.snd).fst a.snd).snd.fst
      (a.fst.fst.fst.fst, (a.fst.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst.fst)).snd),
            Nat.pair (unpair a.fst.fst.fst.snd).fst a.snd).snd.snd
z : Primrec fun a => (unpair a.fst.fst.fst.fst.snd).fst
y : Primrec fun a => a.fst.snd
i : Primrec Prod.snd
⊢ Primrec fun p =>
    (fun p i =>
        Nat.Partrec.Code.lup p.fst.fst.fst.fst
          ((ofNat (ℕ × Code) (List.length p.fst.fst.fst.fst)).fst, p.fst.snd.snd.fst)
          (Nat.pair (unpair p.fst.fst.fst.snd).fst (Nat.pair p.snd i)))
      p.fst p.snd
[PROOFSTEP]
have h₂ :=
  hlup.comp
    ((L.comp Primrec.fst).pair <|
      ((k.pair cg).comp <| Primrec.fst.comp Primrec.fst).pair <| Primrec₂.natPair.comp z <| Primrec₂.natPair.comp y i)
[GOAL]
case hpc
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L✝ : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
cg : Primrec fun a => a.snd.snd.fst
z✝¹ : Primrec fun a => (unpair a.fst.fst.snd).fst
L : Primrec fun a => a.fst.fst.fst.fst
z✝ : Primrec fun a => (unpair a.fst.fst.fst.snd).fst
y✝ : Primrec Prod.snd
h₁ :
  Primrec fun a =>
    Nat.Partrec.Code.lup
      (a.fst.fst.fst.fst, (a.fst.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst.fst)).snd),
          Nat.pair (unpair a.fst.fst.fst.snd).fst a.snd).fst
      (a.fst.fst.fst.fst, (a.fst.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst.fst)).snd),
            Nat.pair (unpair a.fst.fst.fst.snd).fst a.snd).snd.fst
      (a.fst.fst.fst.fst, (a.fst.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst.fst)).snd),
            Nat.pair (unpair a.fst.fst.fst.snd).fst a.snd).snd.snd
z : Primrec fun a => (unpair a.fst.fst.fst.fst.snd).fst
y : Primrec fun a => a.fst.snd
i : Primrec Prod.snd
h₂ :
  Primrec fun a =>
    Nat.Partrec.Code.lup
      (a.fst.fst.fst.fst.fst, ((ofNat (ℕ × Code) (List.length a.fst.fst.fst.fst.fst)).fst, a.fst.fst.snd.snd.fst),
          Nat.pair (unpair a.fst.fst.fst.fst.snd).fst (Nat.pair a.fst.snd a.snd)).fst
      (a.fst.fst.fst.fst.fst, ((ofNat (ℕ × Code) (List.length a.fst.fst.fst.fst.fst)).fst, a.fst.fst.snd.snd.fst),
            Nat.pair (unpair a.fst.fst.fst.fst.snd).fst (Nat.pair a.fst.snd a.snd)).snd.fst
      (a.fst.fst.fst.fst.fst, ((ofNat (ℕ × Code) (List.length a.fst.fst.fst.fst.fst)).fst, a.fst.fst.snd.snd.fst),
            Nat.pair (unpair a.fst.fst.fst.fst.snd).fst (Nat.pair a.fst.snd a.snd)).snd.snd
⊢ Primrec fun p =>
    (fun p i =>
        Nat.Partrec.Code.lup p.fst.fst.fst.fst
          ((ofNat (ℕ × Code) (List.length p.fst.fst.fst.fst)).fst, p.fst.snd.snd.fst)
          (Nat.pair (unpair p.fst.fst.fst.snd).fst (Nat.pair p.snd i)))
      p.fst p.snd
[PROOFSTEP]
exact h₂
[GOAL]
case hrf
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝ : Primrec Prod.snd
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
⊢ Primrec fun a =>
    let z := (unpair a.fst.fst.snd).fst;
    let m := (unpair a.fst.fst.snd).snd;
    do
    let x ←
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) (Nat.pair z m)
    Nat.casesOn x (some m) fun x =>
        Nat.Partrec.Code.lup a.fst.fst.fst (a.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).snd)
          (Nat.pair z (m + 1))
[PROOFSTEP]
have L :=
  (Primrec.fst.comp Primrec.fst).comp (Primrec.fst (α := (List (List (Option ℕ)) × ℕ) × ℕ) (β := Code × Option ℕ))
[GOAL]
case hrf
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝ : Primrec Prod.snd
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
⊢ Primrec fun a =>
    let z := (unpair a.fst.fst.snd).fst;
    let m := (unpair a.fst.fst.snd).snd;
    do
    let x ←
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) (Nat.pair z m)
    Nat.casesOn x (some m) fun x =>
        Nat.Partrec.Code.lup a.fst.fst.fst (a.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).snd)
          (Nat.pair z (m + 1))
[PROOFSTEP]
have k := k.comp (Primrec.fst (β := Code × Option ℕ))
[GOAL]
case hrf
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
⊢ Primrec fun a =>
    let z := (unpair a.fst.fst.snd).fst;
    let m := (unpair a.fst.fst.snd).snd;
    do
    let x ←
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) (Nat.pair z m)
    Nat.casesOn x (some m) fun x =>
        Nat.Partrec.Code.lup a.fst.fst.fst (a.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).snd)
          (Nat.pair z (m + 1))
[PROOFSTEP]
have n := n.comp (Primrec.fst (β := Code × Option ℕ))
[GOAL]
case hrf
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
⊢ Primrec fun a =>
    let z := (unpair a.fst.fst.snd).fst;
    let m := (unpair a.fst.fst.snd).snd;
    do
    let x ←
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) (Nat.pair z m)
    Nat.casesOn x (some m) fun x =>
        Nat.Partrec.Code.lup a.fst.fst.fst (a.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).snd)
          (Nat.pair z (m + 1))
[PROOFSTEP]
have cf := Primrec.fst.comp (Primrec.snd (α := (List (List (Option ℕ)) × ℕ) × ℕ) (β := Code × Option ℕ))
[GOAL]
case hrf
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
⊢ Primrec fun a =>
    let z := (unpair a.fst.fst.snd).fst;
    let m := (unpair a.fst.fst.snd).snd;
    do
    let x ←
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) (Nat.pair z m)
    Nat.casesOn x (some m) fun x =>
        Nat.Partrec.Code.lup a.fst.fst.fst (a.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).snd)
          (Nat.pair z (m + 1))
[PROOFSTEP]
have z := Primrec.fst.comp (Primrec.unpair.comp n)
[GOAL]
case hrf
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
z : Primrec fun a => (unpair a.fst.fst.snd).fst
⊢ Primrec fun a =>
    let z := (unpair a.fst.fst.snd).fst;
    let m := (unpair a.fst.fst.snd).snd;
    do
    let x ←
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) (Nat.pair z m)
    Nat.casesOn x (some m) fun x =>
        Nat.Partrec.Code.lup a.fst.fst.fst (a.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).snd)
          (Nat.pair z (m + 1))
[PROOFSTEP]
have m := Primrec.snd.comp (Primrec.unpair.comp n)
[GOAL]
case hrf
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
z : Primrec fun a => (unpair a.fst.fst.snd).fst
m : Primrec fun a => (unpair a.fst.fst.snd).snd
⊢ Primrec fun a =>
    let z := (unpair a.fst.fst.snd).fst;
    let m := (unpair a.fst.fst.snd).snd;
    do
    let x ←
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) (Nat.pair z m)
    Nat.casesOn x (some m) fun x =>
        Nat.Partrec.Code.lup a.fst.fst.fst (a.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).snd)
          (Nat.pair z (m + 1))
[PROOFSTEP]
have h₁ := hlup.comp <| L.pair <| (k.pair cf).pair (Primrec₂.natPair.comp z m)
[GOAL]
case hrf
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
z : Primrec fun a => (unpair a.fst.fst.snd).fst
m : Primrec fun a => (unpair a.fst.fst.snd).snd
h₁ :
  Primrec fun a =>
    Nat.Partrec.Code.lup
      (a.fst.fst.fst, ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst),
          Nat.pair (unpair a.fst.fst.snd).fst (unpair a.fst.fst.snd).snd).fst
      (a.fst.fst.fst, ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst),
            Nat.pair (unpair a.fst.fst.snd).fst (unpair a.fst.fst.snd).snd).snd.fst
      (a.fst.fst.fst, ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst),
            Nat.pair (unpair a.fst.fst.snd).fst (unpair a.fst.fst.snd).snd).snd.snd
⊢ Primrec fun a =>
    let z := (unpair a.fst.fst.snd).fst;
    let m := (unpair a.fst.fst.snd).snd;
    do
    let x ←
      Nat.Partrec.Code.lup a.fst.fst.fst ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst) (Nat.pair z m)
    Nat.casesOn x (some m) fun x =>
        Nat.Partrec.Code.lup a.fst.fst.fst (a.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).snd)
          (Nat.pair z (m + 1))
[PROOFSTEP]
refine' Primrec.option_bind h₁ (_ : Primrec _)
[GOAL]
case hrf
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
z : Primrec fun a => (unpair a.fst.fst.snd).fst
m : Primrec fun a => (unpair a.fst.fst.snd).snd
h₁ :
  Primrec fun a =>
    Nat.Partrec.Code.lup
      (a.fst.fst.fst, ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst),
          Nat.pair (unpair a.fst.fst.snd).fst (unpair a.fst.fst.snd).snd).fst
      (a.fst.fst.fst, ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst),
            Nat.pair (unpair a.fst.fst.snd).fst (unpair a.fst.fst.snd).snd).snd.fst
      (a.fst.fst.fst, ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst),
            Nat.pair (unpair a.fst.fst.snd).fst (unpair a.fst.fst.snd).snd).snd.snd
⊢ Primrec fun p =>
    (fun a x =>
        Nat.casesOn x (some (unpair a.fst.fst.snd).snd) fun x =>
          Nat.Partrec.Code.lup a.fst.fst.fst (a.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).snd)
            (Nat.pair (unpair a.fst.fst.snd).fst ((unpair a.fst.fst.snd).snd + 1)))
      p.fst p.snd
[PROOFSTEP]
have m := m.comp (Primrec.fst (β := ℕ))
[GOAL]
case hrf
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
z : Primrec fun a => (unpair a.fst.fst.snd).fst
m✝ : Primrec fun a => (unpair a.fst.fst.snd).snd
h₁ :
  Primrec fun a =>
    Nat.Partrec.Code.lup
      (a.fst.fst.fst, ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst),
          Nat.pair (unpair a.fst.fst.snd).fst (unpair a.fst.fst.snd).snd).fst
      (a.fst.fst.fst, ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst),
            Nat.pair (unpair a.fst.fst.snd).fst (unpair a.fst.fst.snd).snd).snd.fst
      (a.fst.fst.fst, ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst),
            Nat.pair (unpair a.fst.fst.snd).fst (unpair a.fst.fst.snd).snd).snd.snd
m : Primrec fun a => (unpair a.fst.fst.fst.snd).snd
⊢ Primrec fun p =>
    (fun a x =>
        Nat.casesOn x (some (unpair a.fst.fst.snd).snd) fun x =>
          Nat.Partrec.Code.lup a.fst.fst.fst (a.fst.snd, (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).snd)
            (Nat.pair (unpair a.fst.fst.snd).fst ((unpair a.fst.fst.snd).snd + 1)))
      p.fst p.snd
[PROOFSTEP]
refine Primrec.nat_casesOn Primrec.snd (Primrec.option_some.comp m) ?_
[GOAL]
case hrf
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
z : Primrec fun a => (unpair a.fst.fst.snd).fst
m✝ : Primrec fun a => (unpair a.fst.fst.snd).snd
h₁ :
  Primrec fun a =>
    Nat.Partrec.Code.lup
      (a.fst.fst.fst, ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst),
          Nat.pair (unpair a.fst.fst.snd).fst (unpair a.fst.fst.snd).snd).fst
      (a.fst.fst.fst, ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst),
            Nat.pair (unpair a.fst.fst.snd).fst (unpair a.fst.fst.snd).snd).snd.fst
      (a.fst.fst.fst, ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst),
            Nat.pair (unpair a.fst.fst.snd).fst (unpair a.fst.fst.snd).snd).snd.snd
m : Primrec fun a => (unpair a.fst.fst.fst.snd).snd
⊢ Primrec₂ fun p n =>
    (fun x =>
        Nat.Partrec.Code.lup p.fst.fst.fst.fst (p.fst.fst.snd, (ofNat (ℕ × Code) (List.length p.fst.fst.fst.fst)).snd)
          (Nat.pair (unpair p.fst.fst.fst.snd).fst ((unpair p.fst.fst.fst.snd).snd + 1)))
      n
[PROOFSTEP]
unfold Primrec₂
[GOAL]
case hrf
a : Primrec fun a => ofNat (ℕ × Code) (List.length a)
k✝¹ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst)).fst
n✝¹ : Primrec Prod.snd
k✝ : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).fst
n✝ : Primrec fun a => a.fst.snd
k' : Primrec Prod.snd
c : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst)).snd
L : Primrec fun a => a.fst.fst.fst
k : Primrec fun a => (ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst
n : Primrec fun a => a.fst.fst.snd
cf : Primrec fun a => a.snd.fst
z : Primrec fun a => (unpair a.fst.fst.snd).fst
m✝ : Primrec fun a => (unpair a.fst.fst.snd).snd
h₁ :
  Primrec fun a =>
    Nat.Partrec.Code.lup
      (a.fst.fst.fst, ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst),
          Nat.pair (unpair a.fst.fst.snd).fst (unpair a.fst.fst.snd).snd).fst
      (a.fst.fst.fst, ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst),
            Nat.pair (unpair a.fst.fst.snd).fst (unpair a.fst.fst.snd).snd).snd.fst
      (a.fst.fst.fst, ((ofNat (ℕ × Code) (List.length a.fst.fst.fst)).fst, a.snd.fst),
            Nat.pair (unpair a.fst.fst.snd).fst (unpair a.fst.fst.snd).snd).snd.snd
m : Primrec fun a => (unpair a.fst.fst.fst.snd).snd
⊢ Primrec fun p =>
    (fun p n =>
        (fun x =>
            Nat.Partrec.Code.lup p.fst.fst.fst.fst
              (p.fst.fst.snd, (ofNat (ℕ × Code) (List.length p.fst.fst.fst.fst)).snd)
              (Nat.pair (unpair p.fst.fst.fst.snd).fst ((unpair p.fst.fst.fst.snd).snd + 1)))
          n)
      p.fst p.snd
[PROOFSTEP]
exact
  (hlup.comp
        ((L.comp Primrec.fst).pair <|
          ((k'.pair c).comp <| Primrec.fst.comp Primrec.fst).pair
            (Primrec₂.natPair.comp (z.comp Primrec.fst) (_root_.Primrec.succ.comp m)))).comp
    Primrec.fst
[GOAL]
k : ℕ
c : Code
n : ℕ
⊢ (Option.bind (Option.map (evaln k c) (List.get? (List.range k) n)) fun b => b) = evaln k c n
[PROOFSTEP]
by_cases kn : n < k
[GOAL]
case pos
k : ℕ
c : Code
n : ℕ
kn : n < k
⊢ (Option.bind (Option.map (evaln k c) (List.get? (List.range k) n)) fun b => b) = evaln k c n
[PROOFSTEP]
simp [List.get?_range kn]
[GOAL]
case neg
k : ℕ
c : Code
n : ℕ
kn : ¬n < k
⊢ (Option.bind (Option.map (evaln k c) (List.get? (List.range k) n)) fun b => b) = evaln k c n
[PROOFSTEP]
rw [List.get?_len_le]
[GOAL]
case neg
k : ℕ
c : Code
n : ℕ
kn : ¬n < k
⊢ (Option.bind (Option.map (evaln k c) Option.none) fun b => b) = evaln k c n
[PROOFSTEP]
cases e : evaln k c n
[GOAL]
case neg.none
k : ℕ
c : Code
n : ℕ
kn : ¬n < k
e : evaln k c n = Option.none
⊢ (Option.bind (Option.map (evaln k c) Option.none) fun b => b) = Option.none
[PROOFSTEP]
rfl
[GOAL]
case neg.some
k : ℕ
c : Code
n : ℕ
kn : ¬n < k
val✝ : ℕ
e : evaln k c n = some val✝
⊢ (Option.bind (Option.map (evaln k c) Option.none) fun b => b) = some val✝
[PROOFSTEP]
exact kn.elim (evaln_bound e)
[GOAL]
case neg
k : ℕ
c : Code
n : ℕ
kn : ¬n < k
⊢ List.length (List.range k) ≤ n
[PROOFSTEP]
simpa using kn
[GOAL]
x✝ : Unit
p : ℕ
⊢ Nat.Partrec.Code.G
      (x✝,
          List.map
            (fun n =>
              let a := ofNat (ℕ × Code) n;
              List.map (evaln a.fst a.snd) (List.range a.fst))
            (List.range p)).snd =
    some
      (let a := ofNat (ℕ × Code) p;
      List.map (evaln a.fst a.snd) (List.range a.fst))
[PROOFSTEP]
simp only [G, prod_ofNat_val, ofNat_nat, List.length_map, List.length_range, Nat.pair_unpair, Option.some_inj]
[GOAL]
x✝ : Unit
p : ℕ
⊢ List.map
      (fun n =>
        Nat.rec Option.none
          (fun n_1 n_ih =>
            rec (some 0) (some (Nat.succ n)) (some (unpair n).fst) (some (unpair n).snd)
              (fun cf cg x x => do
                let x ←
                  Nat.Partrec.Code.lup
                      (List.map
                        (fun n =>
                          List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                        (List.range p))
                      ((unpair p).fst, cf) n
                let y ←
                  Nat.Partrec.Code.lup
                      (List.map
                        (fun n =>
                          List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                        (List.range p))
                      ((unpair p).fst, cg) n
                some (Nat.pair x y))
              (fun cf cg x x => do
                let x ←
                  Nat.Partrec.Code.lup
                      (List.map
                        (fun n =>
                          List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                        (List.range p))
                      ((unpair p).fst, cg) n
                Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range p))
                    ((unpair p).fst, cf) x)
              (fun cf cg x x =>
                Nat.rec
                  (Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range p))
                    ((unpair p).fst, cf) (unpair n).fst)
                  (fun n_2 n_ih => do
                    let i ←
                      Nat.Partrec.Code.lup
                          (List.map
                            (fun n =>
                              List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                            (List.range p))
                          (n_1, ofNat Code (unpair p).snd) (Nat.pair (unpair n).fst n_2)
                    Nat.Partrec.Code.lup
                        (List.map
                          (fun n =>
                            List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                          (List.range p))
                        ((unpair p).fst, cg) (Nat.pair (unpair n).fst (Nat.pair n_2 i)))
                  (unpair n).snd)
              (fun cf x => do
                let x ←
                  Nat.Partrec.Code.lup
                      (List.map
                        (fun n =>
                          List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                        (List.range p))
                      ((unpair p).fst, cf) n
                Nat.rec (some (unpair n).snd)
                    (fun n_2 n_ih =>
                      Nat.Partrec.Code.lup
                        (List.map
                          (fun n =>
                            List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                          (List.range p))
                        (n_1, ofNat Code (unpair p).snd) (Nat.pair (unpair n).fst ((unpair n).snd + 1)))
                    x)
              (ofNat Code (unpair p).snd))
          (unpair p).fst)
      (List.range (unpair p).fst) =
    List.map (evaln (unpair p).fst (ofNat Code (unpair p).snd)) (List.range (unpair p).fst)
[PROOFSTEP]
refine List.map_congr fun n => ?_
[GOAL]
x✝ : Unit
p n : ℕ
⊢ n ∈ List.range (unpair p).fst →
    Nat.rec Option.none
        (fun n_1 n_ih =>
          rec (some 0) (some (Nat.succ n)) (some (unpair n).fst) (some (unpair n).snd)
            (fun cf cg x x => do
              let x ←
                Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range p))
                    ((unpair p).fst, cf) n
              let y ←
                Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range p))
                    ((unpair p).fst, cg) n
              some (Nat.pair x y))
            (fun cf cg x x => do
              let x ←
                Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range p))
                    ((unpair p).fst, cg) n
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range p))
                  ((unpair p).fst, cf) x)
            (fun cf cg x x =>
              Nat.rec
                (Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range p))
                  ((unpair p).fst, cf) (unpair n).fst)
                (fun n_2 n_ih => do
                  let i ←
                    Nat.Partrec.Code.lup
                        (List.map
                          (fun n =>
                            List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                          (List.range p))
                        (n_1, ofNat Code (unpair p).snd) (Nat.pair (unpair n).fst n_2)
                  Nat.Partrec.Code.lup
                      (List.map
                        (fun n =>
                          List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                        (List.range p))
                      ((unpair p).fst, cg) (Nat.pair (unpair n).fst (Nat.pair n_2 i)))
                (unpair n).snd)
            (fun cf x => do
              let x ←
                Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range p))
                    ((unpair p).fst, cf) n
              Nat.rec (some (unpair n).snd)
                  (fun n_2 n_ih =>
                    Nat.Partrec.Code.lup
                      (List.map
                        (fun n =>
                          List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                        (List.range p))
                      (n_1, ofNat Code (unpair p).snd) (Nat.pair (unpair n).fst ((unpair n).snd + 1)))
                  x)
            (ofNat Code (unpair p).snd))
        (unpair p).fst =
      evaln (unpair p).fst (ofNat Code (unpair p).snd) n
[PROOFSTEP]
have : List.range p = List.range (Nat.pair p.unpair.1 (encode (ofNat Code p.unpair.2))) := by simp
[GOAL]
x✝ : Unit
p n : ℕ
⊢ List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
[PROOFSTEP]
simp
[GOAL]
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
⊢ n ∈ List.range (unpair p).fst →
    Nat.rec Option.none
        (fun n_1 n_ih =>
          rec (some 0) (some (Nat.succ n)) (some (unpair n).fst) (some (unpair n).snd)
            (fun cf cg x x => do
              let x ←
                Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range p))
                    ((unpair p).fst, cf) n
              let y ←
                Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range p))
                    ((unpair p).fst, cg) n
              some (Nat.pair x y))
            (fun cf cg x x => do
              let x ←
                Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range p))
                    ((unpair p).fst, cg) n
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range p))
                  ((unpair p).fst, cf) x)
            (fun cf cg x x =>
              Nat.rec
                (Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range p))
                  ((unpair p).fst, cf) (unpair n).fst)
                (fun n_2 n_ih => do
                  let i ←
                    Nat.Partrec.Code.lup
                        (List.map
                          (fun n =>
                            List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                          (List.range p))
                        (n_1, ofNat Code (unpair p).snd) (Nat.pair (unpair n).fst n_2)
                  Nat.Partrec.Code.lup
                      (List.map
                        (fun n =>
                          List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                        (List.range p))
                      ((unpair p).fst, cg) (Nat.pair (unpair n).fst (Nat.pair n_2 i)))
                (unpair n).snd)
            (fun cf x => do
              let x ←
                Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range p))
                    ((unpair p).fst, cf) n
              Nat.rec (some (unpair n).snd)
                  (fun n_2 n_ih =>
                    Nat.Partrec.Code.lup
                      (List.map
                        (fun n =>
                          List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                        (List.range p))
                      (n_1, ofNat Code (unpair p).snd) (Nat.pair (unpair n).fst ((unpair n).snd + 1)))
                  x)
            (ofNat Code (unpair p).snd))
        (unpair p).fst =
      evaln (unpair p).fst (ofNat Code (unpair p).snd) n
[PROOFSTEP]
rw [this]
[GOAL]
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
⊢ n ∈ List.range (unpair p).fst →
    Nat.rec Option.none
        (fun n_1 n_ih =>
          rec (some 0) (some (Nat.succ n)) (some (unpair n).fst) (some (unpair n).snd)
            (fun cf cg x x => do
              let x ←
                Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))))
                    ((unpair p).fst, cf) n
              let y ←
                Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))))
                    ((unpair p).fst, cg) n
              some (Nat.pair x y))
            (fun cf cg x x => do
              let x ←
                Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))))
                    ((unpair p).fst, cg) n
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))))
                  ((unpair p).fst, cf) x)
            (fun cf cg x x =>
              Nat.rec
                (Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))))
                  ((unpair p).fst, cf) (unpair n).fst)
                (fun n_2 n_ih => do
                  let i ←
                    Nat.Partrec.Code.lup
                        (List.map
                          (fun n =>
                            List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                          (List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))))
                        (n_1, ofNat Code (unpair p).snd) (Nat.pair (unpair n).fst n_2)
                  Nat.Partrec.Code.lup
                      (List.map
                        (fun n =>
                          List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                        (List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))))
                      ((unpair p).fst, cg) (Nat.pair (unpair n).fst (Nat.pair n_2 i)))
                (unpair n).snd)
            (fun cf x => do
              let x ←
                Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))))
                    ((unpair p).fst, cf) n
              Nat.rec (some (unpair n).snd)
                  (fun n_2 n_ih =>
                    Nat.Partrec.Code.lup
                      (List.map
                        (fun n =>
                          List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                        (List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))))
                      (n_1, ofNat Code (unpair p).snd) (Nat.pair (unpair n).fst ((unpair n).snd + 1)))
                  x)
            (ofNat Code (unpair p).snd))
        (unpair p).fst =
      evaln (unpair p).fst (ofNat Code (unpair p).snd) n
[PROOFSTEP]
generalize p.unpair.1 = k
[GOAL]
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k : ℕ
⊢ n ∈ List.range k →
    Nat.rec Option.none
        (fun n_1 n_ih =>
          rec (some 0) (some (Nat.succ n)) (some (unpair n).fst) (some (unpair n).snd)
            (fun cf cg x x => do
              let x ←
                Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range (Nat.pair k (encode (ofNat Code (unpair p).snd)))))
                    (k, cf) n
              let y ←
                Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range (Nat.pair k (encode (ofNat Code (unpair p).snd)))))
                    (k, cg) n
              some (Nat.pair x y))
            (fun cf cg x x => do
              let x ←
                Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range (Nat.pair k (encode (ofNat Code (unpair p).snd)))))
                    (k, cg) n
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair k (encode (ofNat Code (unpair p).snd)))))
                  (k, cf) x)
            (fun cf cg x x =>
              Nat.rec
                (Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair k (encode (ofNat Code (unpair p).snd)))))
                  (k, cf) (unpair n).fst)
                (fun n_2 n_ih => do
                  let i ←
                    Nat.Partrec.Code.lup
                        (List.map
                          (fun n =>
                            List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                          (List.range (Nat.pair k (encode (ofNat Code (unpair p).snd)))))
                        (n_1, ofNat Code (unpair p).snd) (Nat.pair (unpair n).fst n_2)
                  Nat.Partrec.Code.lup
                      (List.map
                        (fun n =>
                          List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                        (List.range (Nat.pair k (encode (ofNat Code (unpair p).snd)))))
                      (k, cg) (Nat.pair (unpair n).fst (Nat.pair n_2 i)))
                (unpair n).snd)
            (fun cf x => do
              let x ←
                Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range (Nat.pair k (encode (ofNat Code (unpair p).snd)))))
                    (k, cf) n
              Nat.rec (some (unpair n).snd)
                  (fun n_2 n_ih =>
                    Nat.Partrec.Code.lup
                      (List.map
                        (fun n =>
                          List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                        (List.range (Nat.pair k (encode (ofNat Code (unpair p).snd)))))
                      (n_1, ofNat Code (unpair p).snd) (Nat.pair (unpair n).fst ((unpair n).snd + 1)))
                  x)
            (ofNat Code (unpair p).snd))
        k =
      evaln k (ofNat Code (unpair p).snd) n
[PROOFSTEP]
generalize ofNat Code p.unpair.2 = c
[GOAL]
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k : ℕ
c : Code
⊢ n ∈ List.range k →
    Nat.rec Option.none
        (fun n_1 n_ih =>
          rec (some 0) (some (Nat.succ n)) (some (unpair n).fst) (some (unpair n).snd)
            (fun cf cg x x => do
              let x ←
                Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range (Nat.pair k (encode c))))
                    (k, cf) n
              let y ←
                Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range (Nat.pair k (encode c))))
                    (k, cg) n
              some (Nat.pair x y))
            (fun cf cg x x => do
              let x ←
                Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range (Nat.pair k (encode c))))
                    (k, cg) n
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair k (encode c))))
                  (k, cf) x)
            (fun cf cg x x =>
              Nat.rec
                (Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair k (encode c))))
                  (k, cf) (unpair n).fst)
                (fun n_2 n_ih => do
                  let i ←
                    Nat.Partrec.Code.lup
                        (List.map
                          (fun n =>
                            List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                          (List.range (Nat.pair k (encode c))))
                        (n_1, c) (Nat.pair (unpair n).fst n_2)
                  Nat.Partrec.Code.lup
                      (List.map
                        (fun n =>
                          List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                        (List.range (Nat.pair k (encode c))))
                      (k, cg) (Nat.pair (unpair n).fst (Nat.pair n_2 i)))
                (unpair n).snd)
            (fun cf x => do
              let x ←
                Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range (Nat.pair k (encode c))))
                    (k, cf) n
              Nat.rec (some (unpair n).snd)
                  (fun n_2 n_ih =>
                    Nat.Partrec.Code.lup
                      (List.map
                        (fun n =>
                          List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                        (List.range (Nat.pair k (encode c))))
                      (n_1, c) (Nat.pair (unpair n).fst ((unpair n).snd + 1)))
                  x)
            c)
        k =
      evaln k c n
[PROOFSTEP]
intro nk
[GOAL]
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k : ℕ
c : Code
nk : n ∈ List.range k
⊢ Nat.rec Option.none
      (fun n_1 n_ih =>
        rec (some 0) (some (Nat.succ n)) (some (unpair n).fst) (some (unpair n).snd)
          (fun cf cg x x => do
            let x ←
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair k (encode c))))
                  (k, cf) n
            let y ←
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair k (encode c))))
                  (k, cg) n
            some (Nat.pair x y))
          (fun cf cg x x => do
            let x ←
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair k (encode c))))
                  (k, cg) n
            Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair k (encode c))))
                (k, cf) x)
          (fun cf cg x x =>
            Nat.rec
              (Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair k (encode c))))
                (k, cf) (unpair n).fst)
              (fun n_2 n_ih => do
                let i ←
                  Nat.Partrec.Code.lup
                      (List.map
                        (fun n =>
                          List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                        (List.range (Nat.pair k (encode c))))
                      (n_1, c) (Nat.pair (unpair n).fst n_2)
                Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range (Nat.pair k (encode c))))
                    (k, cg) (Nat.pair (unpair n).fst (Nat.pair n_2 i)))
              (unpair n).snd)
          (fun cf x => do
            let x ←
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair k (encode c))))
                  (k, cf) n
            Nat.rec (some (unpair n).snd)
                (fun n_2 n_ih =>
                  Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range (Nat.pair k (encode c))))
                    (n_1, c) (Nat.pair (unpair n).fst ((unpair n).snd + 1)))
                x)
          c)
      k =
    evaln k c n
[PROOFSTEP]
cases' k with k'
[GOAL]
case zero
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
c : Code
nk : n ∈ List.range Nat.zero
⊢ Nat.rec Option.none
      (fun n_1 n_ih =>
        rec (some 0) (some (Nat.succ n)) (some (unpair n).fst) (some (unpair n).snd)
          (fun cf cg x x => do
            let x ←
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair Nat.zero (encode c))))
                  (Nat.zero, cf) n
            let y ←
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair Nat.zero (encode c))))
                  (Nat.zero, cg) n
            some (Nat.pair x y))
          (fun cf cg x x => do
            let x ←
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair Nat.zero (encode c))))
                  (Nat.zero, cg) n
            Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair Nat.zero (encode c))))
                (Nat.zero, cf) x)
          (fun cf cg x x =>
            Nat.rec
              (Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair Nat.zero (encode c))))
                (Nat.zero, cf) (unpair n).fst)
              (fun n_2 n_ih => do
                let i ←
                  Nat.Partrec.Code.lup
                      (List.map
                        (fun n =>
                          List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                        (List.range (Nat.pair Nat.zero (encode c))))
                      (n_1, c) (Nat.pair (unpair n).fst n_2)
                Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range (Nat.pair Nat.zero (encode c))))
                    (Nat.zero, cg) (Nat.pair (unpair n).fst (Nat.pair n_2 i)))
              (unpair n).snd)
          (fun cf x => do
            let x ←
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair Nat.zero (encode c))))
                  (Nat.zero, cf) n
            Nat.rec (some (unpair n).snd)
                (fun n_2 n_ih =>
                  Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range (Nat.pair Nat.zero (encode c))))
                    (n_1, c) (Nat.pair (unpair n).fst ((unpair n).snd + 1)))
                x)
          c)
      Nat.zero =
    evaln Nat.zero c n
[PROOFSTEP]
simp [evaln]
[GOAL]
case succ
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
c : Code
k' : ℕ
nk : n ∈ List.range (Nat.succ k')
⊢ Nat.rec Option.none
      (fun n_1 n_ih =>
        rec (some 0) (some (Nat.succ n)) (some (unpair n).fst) (some (unpair n).snd)
          (fun cf cg x x => do
            let x ←
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair (Nat.succ k') (encode c))))
                  (Nat.succ k', cf) n
            let y ←
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair (Nat.succ k') (encode c))))
                  (Nat.succ k', cg) n
            some (Nat.pair x y))
          (fun cf cg x x => do
            let x ←
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair (Nat.succ k') (encode c))))
                  (Nat.succ k', cg) n
            Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair (Nat.succ k') (encode c))))
                (Nat.succ k', cf) x)
          (fun cf cg x x =>
            Nat.rec
              (Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair (Nat.succ k') (encode c))))
                (Nat.succ k', cf) (unpair n).fst)
              (fun n_2 n_ih => do
                let i ←
                  Nat.Partrec.Code.lup
                      (List.map
                        (fun n =>
                          List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                        (List.range (Nat.pair (Nat.succ k') (encode c))))
                      (n_1, c) (Nat.pair (unpair n).fst n_2)
                Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range (Nat.pair (Nat.succ k') (encode c))))
                    (Nat.succ k', cg) (Nat.pair (unpair n).fst (Nat.pair n_2 i)))
              (unpair n).snd)
          (fun cf x => do
            let x ←
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair (Nat.succ k') (encode c))))
                  (Nat.succ k', cf) n
            Nat.rec (some (unpair n).snd)
                (fun n_2 n_ih =>
                  Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range (Nat.pair (Nat.succ k') (encode c))))
                    (n_1, c) (Nat.pair (unpair n).fst ((unpair n).snd + 1)))
                x)
          c)
      (Nat.succ k') =
    evaln (Nat.succ k') c n
[PROOFSTEP]
let k := k' + 1
[GOAL]
case succ
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
c : Code
k' : ℕ
nk : n ∈ List.range (Nat.succ k')
k : ℕ := k' + 1
⊢ Nat.rec Option.none
      (fun n_1 n_ih =>
        rec (some 0) (some (Nat.succ n)) (some (unpair n).fst) (some (unpair n).snd)
          (fun cf cg x x => do
            let x ←
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair (Nat.succ k') (encode c))))
                  (Nat.succ k', cf) n
            let y ←
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair (Nat.succ k') (encode c))))
                  (Nat.succ k', cg) n
            some (Nat.pair x y))
          (fun cf cg x x => do
            let x ←
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair (Nat.succ k') (encode c))))
                  (Nat.succ k', cg) n
            Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair (Nat.succ k') (encode c))))
                (Nat.succ k', cf) x)
          (fun cf cg x x =>
            Nat.rec
              (Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair (Nat.succ k') (encode c))))
                (Nat.succ k', cf) (unpair n).fst)
              (fun n_2 n_ih => do
                let i ←
                  Nat.Partrec.Code.lup
                      (List.map
                        (fun n =>
                          List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                        (List.range (Nat.pair (Nat.succ k') (encode c))))
                      (n_1, c) (Nat.pair (unpair n).fst n_2)
                Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range (Nat.pair (Nat.succ k') (encode c))))
                    (Nat.succ k', cg) (Nat.pair (unpair n).fst (Nat.pair n_2 i)))
              (unpair n).snd)
          (fun cf x => do
            let x ←
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair (Nat.succ k') (encode c))))
                  (Nat.succ k', cf) n
            Nat.rec (some (unpair n).snd)
                (fun n_2 n_ih =>
                  Nat.Partrec.Code.lup
                    (List.map
                      (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                      (List.range (Nat.pair (Nat.succ k') (encode c))))
                    (n_1, c) (Nat.pair (unpair n).fst ((unpair n).snd + 1)))
                x)
          c)
      (Nat.succ k') =
    evaln (Nat.succ k') c n
[PROOFSTEP]
simp only [show k'.succ = k from rfl]
[GOAL]
case succ
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
c : Code
k' : ℕ
nk : n ∈ List.range (Nat.succ k')
k : ℕ := k' + 1
⊢ rec (some 0) (some (Nat.succ n)) (some (unpair n).fst) (some (unpair n).snd)
      (fun cf cg x x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode c))))
              (k' + 1, cf) n
        let y ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode c))))
              (k' + 1, cg) n
        some (Nat.pair x y))
      (fun cf cg x x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode c))))
              (k' + 1, cg) n
        Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode c))))
            (k' + 1, cf) x)
      (fun cf cg x x =>
        Nat.rec
          (Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode c))))
            (k' + 1, cf) (unpair n).fst)
          (fun n_1 n_ih => do
            let i ←
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair (k' + 1) (encode c))))
                  (k', c) (Nat.pair (unpair n).fst n_1)
            Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair (k' + 1) (encode c))))
                (k' + 1, cg) (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
          (unpair n).snd)
      (fun cf x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode c))))
              (k' + 1, cf) n
        Nat.rec (some (unpair n).snd)
            (fun n_1 n_ih =>
              Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair (k' + 1) (encode c))))
                (k', c) (Nat.pair (unpair n).fst ((unpair n).snd + 1)))
            x)
      c =
    evaln (k' + 1) c n
[PROOFSTEP]
simp [Nat.lt_succ_iff] at nk 
[GOAL]
case succ
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
c : Code
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
⊢ rec (some 0) (some (Nat.succ n)) (some (unpair n).fst) (some (unpair n).snd)
      (fun cf cg x x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode c))))
              (k' + 1, cf) n
        let y ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode c))))
              (k' + 1, cg) n
        some (Nat.pair x y))
      (fun cf cg x x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode c))))
              (k' + 1, cg) n
        Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode c))))
            (k' + 1, cf) x)
      (fun cf cg x x =>
        Nat.rec
          (Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode c))))
            (k' + 1, cf) (unpair n).fst)
          (fun n_1 n_ih => do
            let i ←
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair (k' + 1) (encode c))))
                  (k', c) (Nat.pair (unpair n).fst n_1)
            Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair (k' + 1) (encode c))))
                (k' + 1, cg) (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
          (unpair n).snd)
      (fun cf x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode c))))
              (k' + 1, cf) n
        Nat.rec (some (unpair n).snd)
            (fun n_1 n_ih =>
              Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair (k' + 1) (encode c))))
                (k', c) (Nat.pair (unpair n).fst ((unpair n).snd + 1)))
            x)
      c =
    evaln (k' + 1) c n
[PROOFSTEP]
have hg :
  ∀ {k' c' n},
    Nat.pair k' (encode c') < Nat.pair k (encode c) →
      lup
          ((List.range (Nat.pair k (encode c))).map fun n =>
            (List.range n.unpair.1).map (evaln n.unpair.1 (ofNat Code n.unpair.2)))
          (k', c') n =
        evaln k' c' n :=
  by
  intro k₁ c₁ n₁ hl
  simp [lup, List.get?_range hl, evaln_map, Bind.bind]
[GOAL]
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
c : Code
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
⊢ ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode c) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode c))))
          (k', c') n =
        evaln k' c' n
[PROOFSTEP]
intro k₁ c₁ n₁ hl
[GOAL]
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
c : Code
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
k₁ : ℕ
c₁ : Code
n₁ : ℕ
hl : Nat.pair k₁ (encode c₁) < Nat.pair k (encode c)
⊢ Nat.Partrec.Code.lup
      (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
        (List.range (Nat.pair k (encode c))))
      (k₁, c₁) n₁ =
    evaln k₁ c₁ n₁
[PROOFSTEP]
simp [lup, List.get?_range hl, evaln_map, Bind.bind]
[GOAL]
case succ
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
c : Code
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode c) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode c))))
          (k', c') n =
        evaln k' c' n
⊢ rec (some 0) (some (Nat.succ n)) (some (unpair n).fst) (some (unpair n).snd)
      (fun cf cg x x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode c))))
              (k' + 1, cf) n
        let y ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode c))))
              (k' + 1, cg) n
        some (Nat.pair x y))
      (fun cf cg x x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode c))))
              (k' + 1, cg) n
        Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode c))))
            (k' + 1, cf) x)
      (fun cf cg x x =>
        Nat.rec
          (Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode c))))
            (k' + 1, cf) (unpair n).fst)
          (fun n_1 n_ih => do
            let i ←
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair (k' + 1) (encode c))))
                  (k', c) (Nat.pair (unpair n).fst n_1)
            Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair (k' + 1) (encode c))))
                (k' + 1, cg) (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
          (unpair n).snd)
      (fun cf x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode c))))
              (k' + 1, cf) n
        Nat.rec (some (unpair n).snd)
            (fun n_1 n_ih =>
              Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair (k' + 1) (encode c))))
                (k', c) (Nat.pair (unpair n).fst ((unpair n).snd + 1)))
            x)
      c =
    evaln (k' + 1) c n
[PROOFSTEP]
cases' c with cf cg cf cg cf cg cf
[GOAL]
case succ.zero
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode zero) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode zero))))
          (k', c') n =
        evaln k' c' n
⊢ rec (some 0) (some (Nat.succ n)) (some (unpair n).fst) (some (unpair n).snd)
      (fun cf cg x x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode zero))))
              (k' + 1, cf) n
        let y ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode zero))))
              (k' + 1, cg) n
        some (Nat.pair x y))
      (fun cf cg x x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode zero))))
              (k' + 1, cg) n
        Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode zero))))
            (k' + 1, cf) x)
      (fun cf cg x x =>
        Nat.rec
          (Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode zero))))
            (k' + 1, cf) (unpair n).fst)
          (fun n_1 n_ih => do
            let i ←
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair (k' + 1) (encode zero))))
                  (k', zero) (Nat.pair (unpair n).fst n_1)
            Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair (k' + 1) (encode zero))))
                (k' + 1, cg) (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
          (unpair n).snd)
      (fun cf x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode zero))))
              (k' + 1, cf) n
        Nat.rec (some (unpair n).snd)
            (fun n_1 n_ih =>
              Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair (k' + 1) (encode zero))))
                (k', zero) (Nat.pair (unpair n).fst ((unpair n).snd + 1)))
            x)
      zero =
    evaln (k' + 1) zero n
[PROOFSTEP]
simp [evaln, nk, Bind.bind, Functor.map, Seq.seq, pure]
[GOAL]
case succ.succ
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode succ) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode succ))))
          (k', c') n =
        evaln k' c' n
⊢ rec (some 0) (some (Nat.succ n)) (some (unpair n).fst) (some (unpair n).snd)
      (fun cf cg x x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode succ))))
              (k' + 1, cf) n
        let y ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode succ))))
              (k' + 1, cg) n
        some (Nat.pair x y))
      (fun cf cg x x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode succ))))
              (k' + 1, cg) n
        Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode succ))))
            (k' + 1, cf) x)
      (fun cf cg x x =>
        Nat.rec
          (Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode succ))))
            (k' + 1, cf) (unpair n).fst)
          (fun n_1 n_ih => do
            let i ←
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair (k' + 1) (encode succ))))
                  (k', succ) (Nat.pair (unpair n).fst n_1)
            Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair (k' + 1) (encode succ))))
                (k' + 1, cg) (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
          (unpair n).snd)
      (fun cf x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode succ))))
              (k' + 1, cf) n
        Nat.rec (some (unpair n).snd)
            (fun n_1 n_ih =>
              Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair (k' + 1) (encode succ))))
                (k', succ) (Nat.pair (unpair n).fst ((unpair n).snd + 1)))
            x)
      succ =
    evaln (k' + 1) succ n
[PROOFSTEP]
simp [evaln, nk, Bind.bind, Functor.map, Seq.seq, pure]
[GOAL]
case succ.left
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode left) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode left))))
          (k', c') n =
        evaln k' c' n
⊢ rec (some 0) (some (Nat.succ n)) (some (unpair n).fst) (some (unpair n).snd)
      (fun cf cg x x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode left))))
              (k' + 1, cf) n
        let y ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode left))))
              (k' + 1, cg) n
        some (Nat.pair x y))
      (fun cf cg x x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode left))))
              (k' + 1, cg) n
        Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode left))))
            (k' + 1, cf) x)
      (fun cf cg x x =>
        Nat.rec
          (Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode left))))
            (k' + 1, cf) (unpair n).fst)
          (fun n_1 n_ih => do
            let i ←
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair (k' + 1) (encode left))))
                  (k', left) (Nat.pair (unpair n).fst n_1)
            Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair (k' + 1) (encode left))))
                (k' + 1, cg) (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
          (unpair n).snd)
      (fun cf x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode left))))
              (k' + 1, cf) n
        Nat.rec (some (unpair n).snd)
            (fun n_1 n_ih =>
              Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair (k' + 1) (encode left))))
                (k', left) (Nat.pair (unpair n).fst ((unpair n).snd + 1)))
            x)
      left =
    evaln (k' + 1) left n
[PROOFSTEP]
simp [evaln, nk, Bind.bind, Functor.map, Seq.seq, pure]
[GOAL]
case succ.right
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode right) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode right))))
          (k', c') n =
        evaln k' c' n
⊢ rec (some 0) (some (Nat.succ n)) (some (unpair n).fst) (some (unpair n).snd)
      (fun cf cg x x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode right))))
              (k' + 1, cf) n
        let y ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode right))))
              (k' + 1, cg) n
        some (Nat.pair x y))
      (fun cf cg x x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode right))))
              (k' + 1, cg) n
        Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode right))))
            (k' + 1, cf) x)
      (fun cf cg x x =>
        Nat.rec
          (Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode right))))
            (k' + 1, cf) (unpair n).fst)
          (fun n_1 n_ih => do
            let i ←
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair (k' + 1) (encode right))))
                  (k', right) (Nat.pair (unpair n).fst n_1)
            Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair (k' + 1) (encode right))))
                (k' + 1, cg) (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
          (unpair n).snd)
      (fun cf x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode right))))
              (k' + 1, cf) n
        Nat.rec (some (unpair n).snd)
            (fun n_1 n_ih =>
              Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair (k' + 1) (encode right))))
                (k', right) (Nat.pair (unpair n).fst ((unpair n).snd + 1)))
            x)
      right =
    evaln (k' + 1) right n
[PROOFSTEP]
simp [evaln, nk, Bind.bind, Functor.map, Seq.seq, pure]
[GOAL]
case succ.pair
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf cg : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (pair cf cg)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (pair cf cg)))))
          (k', c') n =
        evaln k' c' n
⊢ rec (some 0) (some (Nat.succ n)) (some (unpair n).fst) (some (unpair n).snd)
      (fun cf_1 cg_1 x x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode (pair cf cg)))))
              (k' + 1, cf_1) n
        let y ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode (pair cf cg)))))
              (k' + 1, cg_1) n
        some (Nat.pair x y))
      (fun cf_1 cg_1 x x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode (pair cf cg)))))
              (k' + 1, cg_1) n
        Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode (pair cf cg)))))
            (k' + 1, cf_1) x)
      (fun cf_1 cg_1 x x =>
        Nat.rec
          (Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode (pair cf cg)))))
            (k' + 1, cf_1) (unpair n).fst)
          (fun n_1 n_ih => do
            let i ←
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair (k' + 1) (encode (pair cf cg)))))
                  (k', pair cf cg) (Nat.pair (unpair n).fst n_1)
            Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair (k' + 1) (encode (pair cf cg)))))
                (k' + 1, cg_1) (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
          (unpair n).snd)
      (fun cf_1 x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode (pair cf cg)))))
              (k' + 1, cf_1) n
        Nat.rec (some (unpair n).snd)
            (fun n_1 n_ih =>
              Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair (k' + 1) (encode (pair cf cg)))))
                (k', pair cf cg) (Nat.pair (unpair n).fst ((unpair n).snd + 1)))
            x)
      (pair cf cg) =
    evaln (k' + 1) (pair cf cg) n
[PROOFSTEP]
simp [evaln, nk, Bind.bind, Functor.map, Seq.seq, pure]
[GOAL]
case succ.comp
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf cg : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (comp cf cg)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (comp cf cg)))))
          (k', c') n =
        evaln k' c' n
⊢ rec (some 0) (some (Nat.succ n)) (some (unpair n).fst) (some (unpair n).snd)
      (fun cf_1 cg_1 x x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode (comp cf cg)))))
              (k' + 1, cf_1) n
        let y ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode (comp cf cg)))))
              (k' + 1, cg_1) n
        some (Nat.pair x y))
      (fun cf_1 cg_1 x x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode (comp cf cg)))))
              (k' + 1, cg_1) n
        Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode (comp cf cg)))))
            (k' + 1, cf_1) x)
      (fun cf_1 cg_1 x x =>
        Nat.rec
          (Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode (comp cf cg)))))
            (k' + 1, cf_1) (unpair n).fst)
          (fun n_1 n_ih => do
            let i ←
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair (k' + 1) (encode (comp cf cg)))))
                  (k', comp cf cg) (Nat.pair (unpair n).fst n_1)
            Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair (k' + 1) (encode (comp cf cg)))))
                (k' + 1, cg_1) (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
          (unpair n).snd)
      (fun cf_1 x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode (comp cf cg)))))
              (k' + 1, cf_1) n
        Nat.rec (some (unpair n).snd)
            (fun n_1 n_ih =>
              Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair (k' + 1) (encode (comp cf cg)))))
                (k', comp cf cg) (Nat.pair (unpair n).fst ((unpair n).snd + 1)))
            x)
      (comp cf cg) =
    evaln (k' + 1) (comp cf cg) n
[PROOFSTEP]
simp [evaln, nk, Bind.bind, Functor.map, Seq.seq, pure]
[GOAL]
case succ.prec
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf cg : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (prec cf cg)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (prec cf cg)))))
          (k', c') n =
        evaln k' c' n
⊢ rec (some 0) (some (Nat.succ n)) (some (unpair n).fst) (some (unpair n).snd)
      (fun cf_1 cg_1 x x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode (prec cf cg)))))
              (k' + 1, cf_1) n
        let y ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode (prec cf cg)))))
              (k' + 1, cg_1) n
        some (Nat.pair x y))
      (fun cf_1 cg_1 x x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode (prec cf cg)))))
              (k' + 1, cg_1) n
        Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode (prec cf cg)))))
            (k' + 1, cf_1) x)
      (fun cf_1 cg_1 x x =>
        Nat.rec
          (Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode (prec cf cg)))))
            (k' + 1, cf_1) (unpair n).fst)
          (fun n_1 n_ih => do
            let i ←
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair (k' + 1) (encode (prec cf cg)))))
                  (k', prec cf cg) (Nat.pair (unpair n).fst n_1)
            Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair (k' + 1) (encode (prec cf cg)))))
                (k' + 1, cg_1) (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
          (unpair n).snd)
      (fun cf_1 x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode (prec cf cg)))))
              (k' + 1, cf_1) n
        Nat.rec (some (unpair n).snd)
            (fun n_1 n_ih =>
              Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair (k' + 1) (encode (prec cf cg)))))
                (k', prec cf cg) (Nat.pair (unpair n).fst ((unpair n).snd + 1)))
            x)
      (prec cf cg) =
    evaln (k' + 1) (prec cf cg) n
[PROOFSTEP]
simp [evaln, nk, Bind.bind, Functor.map, Seq.seq, pure]
[GOAL]
case succ.rfind'
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (rfind' cf)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (rfind' cf)))))
          (k', c') n =
        evaln k' c' n
⊢ rec (some 0) (some (Nat.succ n)) (some (unpair n).fst) (some (unpair n).snd)
      (fun cf_1 cg x x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode (rfind' cf)))))
              (k' + 1, cf_1) n
        let y ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode (rfind' cf)))))
              (k' + 1, cg) n
        some (Nat.pair x y))
      (fun cf_1 cg x x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode (rfind' cf)))))
              (k' + 1, cg) n
        Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode (rfind' cf)))))
            (k' + 1, cf_1) x)
      (fun cf_1 cg x x =>
        Nat.rec
          (Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode (rfind' cf)))))
            (k' + 1, cf_1) (unpair n).fst)
          (fun n_1 n_ih => do
            let i ←
              Nat.Partrec.Code.lup
                  (List.map
                    (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                    (List.range (Nat.pair (k' + 1) (encode (rfind' cf)))))
                  (k', rfind' cf) (Nat.pair (unpair n).fst n_1)
            Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair (k' + 1) (encode (rfind' cf)))))
                (k' + 1, cg) (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
          (unpair n).snd)
      (fun cf_1 x => do
        let x ←
          Nat.Partrec.Code.lup
              (List.map
                (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                (List.range (Nat.pair (k' + 1) (encode (rfind' cf)))))
              (k' + 1, cf_1) n
        Nat.rec (some (unpair n).snd)
            (fun n_1 n_ih =>
              Nat.Partrec.Code.lup
                (List.map
                  (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
                  (List.range (Nat.pair (k' + 1) (encode (rfind' cf)))))
                (k', rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1)))
            x)
      (rfind' cf) =
    evaln (k' + 1) (rfind' cf) n
[PROOFSTEP]
simp [evaln, nk, Bind.bind, Functor.map, Seq.seq, pure]
[GOAL]
case succ.pair
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf cg : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (pair cf cg)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (pair cf cg)))))
          (k', c') n =
        evaln k' c' n
⊢ (Option.bind
      (Nat.Partrec.Code.lup
        (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
          (List.range (Nat.pair (k' + 1) (encode (pair cf cg)))))
        (k' + 1, cf) n)
      fun x =>
      Option.bind
        (Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair (k' + 1) (encode (pair cf cg)))))
          (k' + 1, cg) n)
        fun y => some (Nat.pair x y)) =
    Option.bind (Option.map Nat.pair (evaln (k' + 1) cf n)) fun y => Option.map y (evaln (k' + 1) cg n)
[PROOFSTEP]
cases' encode_lt_pair cf cg with lf lg
[GOAL]
case succ.pair.intro
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf cg : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (pair cf cg)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (pair cf cg)))))
          (k', c') n =
        evaln k' c' n
lf : encode cf < encode (pair cf cg)
lg : encode cg < encode (pair cf cg)
⊢ (Option.bind
      (Nat.Partrec.Code.lup
        (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
          (List.range (Nat.pair (k' + 1) (encode (pair cf cg)))))
        (k' + 1, cf) n)
      fun x =>
      Option.bind
        (Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair (k' + 1) (encode (pair cf cg)))))
          (k' + 1, cg) n)
        fun y => some (Nat.pair x y)) =
    Option.bind (Option.map Nat.pair (evaln (k' + 1) cf n)) fun y => Option.map y (evaln (k' + 1) cg n)
[PROOFSTEP]
rw [hg (Nat.pair_lt_pair_right _ lf), hg (Nat.pair_lt_pair_right _ lg)]
[GOAL]
case succ.pair.intro
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf cg : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (pair cf cg)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (pair cf cg)))))
          (k', c') n =
        evaln k' c' n
lf : encode cf < encode (pair cf cg)
lg : encode cg < encode (pair cf cg)
⊢ (Option.bind (evaln k cf n) fun x => Option.bind (evaln k cg n) fun y => some (Nat.pair x y)) =
    Option.bind (Option.map Nat.pair (evaln (k' + 1) cf n)) fun y => Option.map y (evaln (k' + 1) cg n)
[PROOFSTEP]
cases evaln k cf n
[GOAL]
case succ.pair.intro.none
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf cg : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (pair cf cg)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (pair cf cg)))))
          (k', c') n =
        evaln k' c' n
lf : encode cf < encode (pair cf cg)
lg : encode cg < encode (pair cf cg)
⊢ (Option.bind Option.none fun x => Option.bind (evaln k cg n) fun y => some (Nat.pair x y)) =
    Option.bind (Option.map Nat.pair Option.none) fun y => Option.map y (evaln (k' + 1) cg n)
[PROOFSTEP]
rfl
[GOAL]
case succ.pair.intro.some
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf cg : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (pair cf cg)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (pair cf cg)))))
          (k', c') n =
        evaln k' c' n
lf : encode cf < encode (pair cf cg)
lg : encode cg < encode (pair cf cg)
val✝ : ℕ
⊢ (Option.bind (some val✝) fun x => Option.bind (evaln k cg n) fun y => some (Nat.pair x y)) =
    Option.bind (Option.map Nat.pair (some val✝)) fun y => Option.map y (evaln (k' + 1) cg n)
[PROOFSTEP]
cases evaln k cg n
[GOAL]
case succ.pair.intro.some.none
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf cg : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (pair cf cg)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (pair cf cg)))))
          (k', c') n =
        evaln k' c' n
lf : encode cf < encode (pair cf cg)
lg : encode cg < encode (pair cf cg)
val✝ : ℕ
⊢ (Option.bind (some val✝) fun x => Option.bind Option.none fun y => some (Nat.pair x y)) =
    Option.bind (Option.map Nat.pair (some val✝)) fun y => Option.map y Option.none
[PROOFSTEP]
rfl
[GOAL]
case succ.pair.intro.some.some
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf cg : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (pair cf cg)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (pair cf cg)))))
          (k', c') n =
        evaln k' c' n
lf : encode cf < encode (pair cf cg)
lg : encode cg < encode (pair cf cg)
val✝¹ val✝ : ℕ
⊢ (Option.bind (some val✝¹) fun x => Option.bind (some val✝) fun y => some (Nat.pair x y)) =
    Option.bind (Option.map Nat.pair (some val✝¹)) fun y => Option.map y (some val✝)
[PROOFSTEP]
rfl
[GOAL]
case succ.comp
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf cg : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (comp cf cg)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (comp cf cg)))))
          (k', c') n =
        evaln k' c' n
⊢ (Option.bind
      (Nat.Partrec.Code.lup
        (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
          (List.range (Nat.pair (k' + 1) (encode (comp cf cg)))))
        (k' + 1, cg) n)
      fun x =>
      Nat.Partrec.Code.lup
        (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
          (List.range (Nat.pair (k' + 1) (encode (comp cf cg)))))
        (k' + 1, cf) x) =
    Option.bind (evaln (k' + 1) cg n) fun x => evaln (k' + 1) cf x
[PROOFSTEP]
cases' encode_lt_comp cf cg with lf lg
[GOAL]
case succ.comp.intro
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf cg : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (comp cf cg)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (comp cf cg)))))
          (k', c') n =
        evaln k' c' n
lf : encode cf < encode (comp cf cg)
lg : encode cg < encode (comp cf cg)
⊢ (Option.bind
      (Nat.Partrec.Code.lup
        (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
          (List.range (Nat.pair (k' + 1) (encode (comp cf cg)))))
        (k' + 1, cg) n)
      fun x =>
      Nat.Partrec.Code.lup
        (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
          (List.range (Nat.pair (k' + 1) (encode (comp cf cg)))))
        (k' + 1, cf) x) =
    Option.bind (evaln (k' + 1) cg n) fun x => evaln (k' + 1) cf x
[PROOFSTEP]
rw [hg (Nat.pair_lt_pair_right _ lg)]
[GOAL]
case succ.comp.intro
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf cg : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (comp cf cg)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (comp cf cg)))))
          (k', c') n =
        evaln k' c' n
lf : encode cf < encode (comp cf cg)
lg : encode cg < encode (comp cf cg)
⊢ (Option.bind (evaln k cg n) fun x =>
      Nat.Partrec.Code.lup
        (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
          (List.range (Nat.pair (k' + 1) (encode (comp cf cg)))))
        (k' + 1, cf) x) =
    Option.bind (evaln (k' + 1) cg n) fun x => evaln (k' + 1) cf x
[PROOFSTEP]
cases evaln k cg n
[GOAL]
case succ.comp.intro.none
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf cg : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (comp cf cg)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (comp cf cg)))))
          (k', c') n =
        evaln k' c' n
lf : encode cf < encode (comp cf cg)
lg : encode cg < encode (comp cf cg)
⊢ (Option.bind Option.none fun x =>
      Nat.Partrec.Code.lup
        (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
          (List.range (Nat.pair (k' + 1) (encode (comp cf cg)))))
        (k' + 1, cf) x) =
    Option.bind Option.none fun x => evaln (k' + 1) cf x
[PROOFSTEP]
rfl
[GOAL]
case succ.comp.intro.some
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf cg : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (comp cf cg)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (comp cf cg)))))
          (k', c') n =
        evaln k' c' n
lf : encode cf < encode (comp cf cg)
lg : encode cg < encode (comp cf cg)
val✝ : ℕ
⊢ (Option.bind (some val✝) fun x =>
      Nat.Partrec.Code.lup
        (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
          (List.range (Nat.pair (k' + 1) (encode (comp cf cg)))))
        (k' + 1, cf) x) =
    Option.bind (some val✝) fun x => evaln (k' + 1) cf x
[PROOFSTEP]
simp [hg (Nat.pair_lt_pair_right _ lf)]
[GOAL]
case succ.prec
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf cg : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (prec cf cg)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (prec cf cg)))))
          (k', c') n =
        evaln k' c' n
⊢ Nat.rec
      (Nat.Partrec.Code.lup
        (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
          (List.range (Nat.pair (k' + 1) (encode (prec cf cg)))))
        (k' + 1, cf) (unpair n).fst)
      (fun n_1 n_ih =>
        Option.bind
          (Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode (prec cf cg)))))
            (k', prec cf cg) (Nat.pair (unpair n).fst n_1))
          fun i =>
          Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode (prec cf cg)))))
            (k' + 1, cg) (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
      (unpair n).snd =
    Nat.rec (evaln (k' + 1) cf (unpair n).fst)
      (fun n_1 n_ih =>
        Option.bind (evaln k' (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
          evaln (k' + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
      (unpair n).snd
[PROOFSTEP]
cases' encode_lt_prec cf cg with lf lg
[GOAL]
case succ.prec.intro
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf cg : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (prec cf cg)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (prec cf cg)))))
          (k', c') n =
        evaln k' c' n
lf : encode cf < encode (prec cf cg)
lg : encode cg < encode (prec cf cg)
⊢ Nat.rec
      (Nat.Partrec.Code.lup
        (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
          (List.range (Nat.pair (k' + 1) (encode (prec cf cg)))))
        (k' + 1, cf) (unpair n).fst)
      (fun n_1 n_ih =>
        Option.bind
          (Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode (prec cf cg)))))
            (k', prec cf cg) (Nat.pair (unpair n).fst n_1))
          fun i =>
          Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode (prec cf cg)))))
            (k' + 1, cg) (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
      (unpair n).snd =
    Nat.rec (evaln (k' + 1) cf (unpair n).fst)
      (fun n_1 n_ih =>
        Option.bind (evaln k' (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
          evaln (k' + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
      (unpair n).snd
[PROOFSTEP]
rw [hg (Nat.pair_lt_pair_right _ lf)]
[GOAL]
case succ.prec.intro
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf cg : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (prec cf cg)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (prec cf cg)))))
          (k', c') n =
        evaln k' c' n
lf : encode cf < encode (prec cf cg)
lg : encode cg < encode (prec cf cg)
⊢ Nat.rec (evaln k cf (unpair n).fst)
      (fun n_1 n_ih =>
        Option.bind
          (Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode (prec cf cg)))))
            (k', prec cf cg) (Nat.pair (unpair n).fst n_1))
          fun i =>
          Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode (prec cf cg)))))
            (k' + 1, cg) (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
      (unpair n).snd =
    Nat.rec (evaln (k' + 1) cf (unpair n).fst)
      (fun n_1 n_ih =>
        Option.bind (evaln k' (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
          evaln (k' + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
      (unpair n).snd
[PROOFSTEP]
cases n.unpair.2
[GOAL]
case succ.prec.intro.zero
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf cg : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (prec cf cg)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (prec cf cg)))))
          (k', c') n =
        evaln k' c' n
lf : encode cf < encode (prec cf cg)
lg : encode cg < encode (prec cf cg)
⊢ Nat.rec (evaln k cf (unpair n).fst)
      (fun n_1 n_ih =>
        Option.bind
          (Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode (prec cf cg)))))
            (k', prec cf cg) (Nat.pair (unpair n).fst n_1))
          fun i =>
          Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode (prec cf cg)))))
            (k' + 1, cg) (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
      Nat.zero =
    Nat.rec (evaln (k' + 1) cf (unpair n).fst)
      (fun n_1 n_ih =>
        Option.bind (evaln k' (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
          evaln (k' + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
      Nat.zero
[PROOFSTEP]
rfl
[GOAL]
case succ.prec.intro.succ
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf cg : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (prec cf cg)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (prec cf cg)))))
          (k', c') n =
        evaln k' c' n
lf : encode cf < encode (prec cf cg)
lg : encode cg < encode (prec cf cg)
n✝ : ℕ
⊢ Nat.rec (evaln k cf (unpair n).fst)
      (fun n_1 n_ih =>
        Option.bind
          (Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode (prec cf cg)))))
            (k', prec cf cg) (Nat.pair (unpair n).fst n_1))
          fun i =>
          Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode (prec cf cg)))))
            (k' + 1, cg) (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
      (Nat.succ n✝) =
    Nat.rec (evaln (k' + 1) cf (unpair n).fst)
      (fun n_1 n_ih =>
        Option.bind (evaln k' (prec cf cg) (Nat.pair (unpair n).fst n_1)) fun i =>
          evaln (k' + 1) cg (Nat.pair (unpair n).fst (Nat.pair n_1 i)))
      (Nat.succ n✝)
[PROOFSTEP]
simp
[GOAL]
case succ.prec.intro.succ
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf cg : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (prec cf cg)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (prec cf cg)))))
          (k', c') n =
        evaln k' c' n
lf : encode cf < encode (prec cf cg)
lg : encode cg < encode (prec cf cg)
n✝ : ℕ
⊢ (Option.bind
      (Nat.Partrec.Code.lup
        (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
          (List.range (Nat.pair (k' + 1) (encode (prec cf cg)))))
        (k', prec cf cg) (Nat.pair (unpair n).fst n✝))
      fun i =>
      Nat.Partrec.Code.lup
        (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
          (List.range (Nat.pair (k' + 1) (encode (prec cf cg)))))
        (k' + 1, cg) (Nat.pair (unpair n).fst (Nat.pair n✝ i))) =
    Option.bind (evaln k' (prec cf cg) (Nat.pair (unpair n).fst n✝)) fun i =>
      evaln (k' + 1) cg (Nat.pair (unpair n).fst (Nat.pair n✝ i))
[PROOFSTEP]
rw [hg (Nat.pair_lt_pair_left _ k'.lt_succ_self)]
[GOAL]
case succ.prec.intro.succ
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf cg : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (prec cf cg)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (prec cf cg)))))
          (k', c') n =
        evaln k' c' n
lf : encode cf < encode (prec cf cg)
lg : encode cg < encode (prec cf cg)
n✝ : ℕ
⊢ (Option.bind (evaln k' (prec cf cg) (Nat.pair (unpair n).fst n✝)) fun i =>
      Nat.Partrec.Code.lup
        (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
          (List.range (Nat.pair (k' + 1) (encode (prec cf cg)))))
        (k' + 1, cg) (Nat.pair (unpair n).fst (Nat.pair n✝ i))) =
    Option.bind (evaln k' (prec cf cg) (Nat.pair (unpair n).fst n✝)) fun i =>
      evaln (k' + 1) cg (Nat.pair (unpair n).fst (Nat.pair n✝ i))
[PROOFSTEP]
cases evaln k' _ _
[GOAL]
case succ.prec.intro.succ.none
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf cg : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (prec cf cg)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (prec cf cg)))))
          (k', c') n =
        evaln k' c' n
lf : encode cf < encode (prec cf cg)
lg : encode cg < encode (prec cf cg)
n✝ : ℕ
⊢ (Option.bind Option.none fun i =>
      Nat.Partrec.Code.lup
        (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
          (List.range (Nat.pair (k' + 1) (encode (prec cf cg)))))
        (k' + 1, cg) (Nat.pair (unpair n).fst (Nat.pair n✝ i))) =
    Option.bind Option.none fun i => evaln (k' + 1) cg (Nat.pair (unpair n).fst (Nat.pair n✝ i))
[PROOFSTEP]
rfl
[GOAL]
case succ.prec.intro.succ.some
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf cg : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (prec cf cg)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (prec cf cg)))))
          (k', c') n =
        evaln k' c' n
lf : encode cf < encode (prec cf cg)
lg : encode cg < encode (prec cf cg)
n✝ val✝ : ℕ
⊢ (Option.bind (some val✝) fun i =>
      Nat.Partrec.Code.lup
        (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
          (List.range (Nat.pair (k' + 1) (encode (prec cf cg)))))
        (k' + 1, cg) (Nat.pair (unpair n).fst (Nat.pair n✝ i))) =
    Option.bind (some val✝) fun i => evaln (k' + 1) cg (Nat.pair (unpair n).fst (Nat.pair n✝ i))
[PROOFSTEP]
simp [hg (Nat.pair_lt_pair_right _ lg)]
[GOAL]
case succ.rfind'
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (rfind' cf)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (rfind' cf)))))
          (k', c') n =
        evaln k' c' n
⊢ (Option.bind
      (Nat.Partrec.Code.lup
        (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
          (List.range (Nat.pair (k' + 1) (encode (rfind' cf)))))
        (k' + 1, cf) n)
      fun x =>
      Nat.rec (some (unpair n).snd)
        (fun n_1 n_ih =>
          Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode (rfind' cf)))))
            (k', rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1)))
        x) =
    Option.bind (evaln (k' + 1) cf n) fun x =>
      if x = 0 then some (unpair n).snd else evaln k' (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))
[PROOFSTEP]
have lf := encode_lt_rfind' cf
[GOAL]
case succ.rfind'
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (rfind' cf)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (rfind' cf)))))
          (k', c') n =
        evaln k' c' n
lf : encode cf < encode (rfind' cf)
⊢ (Option.bind
      (Nat.Partrec.Code.lup
        (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
          (List.range (Nat.pair (k' + 1) (encode (rfind' cf)))))
        (k' + 1, cf) n)
      fun x =>
      Nat.rec (some (unpair n).snd)
        (fun n_1 n_ih =>
          Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode (rfind' cf)))))
            (k', rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1)))
        x) =
    Option.bind (evaln (k' + 1) cf n) fun x =>
      if x = 0 then some (unpair n).snd else evaln k' (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))
[PROOFSTEP]
rw [hg (Nat.pair_lt_pair_right _ lf)]
[GOAL]
case succ.rfind'
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (rfind' cf)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (rfind' cf)))))
          (k', c') n =
        evaln k' c' n
lf : encode cf < encode (rfind' cf)
⊢ (Option.bind (evaln k cf n) fun x =>
      Nat.rec (some (unpair n).snd)
        (fun n_1 n_ih =>
          Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode (rfind' cf)))))
            (k', rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1)))
        x) =
    Option.bind (evaln (k' + 1) cf n) fun x =>
      if x = 0 then some (unpair n).snd else evaln k' (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))
[PROOFSTEP]
cases' evaln k cf n with x
[GOAL]
case succ.rfind'.none
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (rfind' cf)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (rfind' cf)))))
          (k', c') n =
        evaln k' c' n
lf : encode cf < encode (rfind' cf)
⊢ (Option.bind Option.none fun x =>
      Nat.rec (some (unpair n).snd)
        (fun n_1 n_ih =>
          Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode (rfind' cf)))))
            (k', rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1)))
        x) =
    Option.bind Option.none fun x =>
      if x = 0 then some (unpair n).snd else evaln k' (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))
[PROOFSTEP]
rfl
[GOAL]
case succ.rfind'.some
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (rfind' cf)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (rfind' cf)))))
          (k', c') n =
        evaln k' c' n
lf : encode cf < encode (rfind' cf)
x : ℕ
⊢ (Option.bind (some x) fun x =>
      Nat.rec (some (unpair n).snd)
        (fun n_1 n_ih =>
          Nat.Partrec.Code.lup
            (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
              (List.range (Nat.pair (k' + 1) (encode (rfind' cf)))))
            (k', rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1)))
        x) =
    Option.bind (some x) fun x =>
      if x = 0 then some (unpair n).snd else evaln k' (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))
[PROOFSTEP]
simp
[GOAL]
case succ.rfind'.some
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (rfind' cf)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (rfind' cf)))))
          (k', c') n =
        evaln k' c' n
lf : encode cf < encode (rfind' cf)
x : ℕ
⊢ Nat.rec (some (unpair n).snd)
      (fun n_1 n_ih =>
        Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair (k' + 1) (encode (rfind' cf)))))
          (k', rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1)))
      x =
    if x = 0 then some (unpair n).snd else evaln k' (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))
[PROOFSTEP]
cases x
[GOAL]
case succ.rfind'.some.zero
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (rfind' cf)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (rfind' cf)))))
          (k', c') n =
        evaln k' c' n
lf : encode cf < encode (rfind' cf)
⊢ Nat.rec (some (unpair n).snd)
      (fun n_1 n_ih =>
        Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair (k' + 1) (encode (rfind' cf)))))
          (k', rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1)))
      Nat.zero =
    if Nat.zero = 0 then some (unpair n).snd else evaln k' (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))
[PROOFSTEP]
simp [Nat.succ_ne_zero]
[GOAL]
case succ.rfind'.some.succ
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (rfind' cf)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (rfind' cf)))))
          (k', c') n =
        evaln k' c' n
lf : encode cf < encode (rfind' cf)
n✝ : ℕ
⊢ Nat.rec (some (unpair n).snd)
      (fun n_1 n_ih =>
        Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair (k' + 1) (encode (rfind' cf)))))
          (k', rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1)))
      (Nat.succ n✝) =
    if Nat.succ n✝ = 0 then some (unpair n).snd else evaln k' (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))
[PROOFSTEP]
simp [Nat.succ_ne_zero]
[GOAL]
case succ.rfind'.some.succ
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))
k' : ℕ
k : ℕ := k' + 1
nk : n ≤ k'
cf : Code
hg :
  ∀ {k' : ℕ} {c' : Code} {n : ℕ},
    Nat.pair k' (encode c') < Nat.pair k (encode (rfind' cf)) →
      Nat.Partrec.Code.lup
          (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
            (List.range (Nat.pair k (encode (rfind' cf)))))
          (k', c') n =
        evaln k' c' n
lf : encode cf < encode (rfind' cf)
n✝ : ℕ
⊢ Nat.Partrec.Code.lup
      (List.map (fun n => List.map (evaln (unpair n).fst (ofNat Code (unpair n).snd)) (List.range (unpair n).fst))
        (List.range (Nat.pair (k' + 1) (encode (rfind' cf)))))
      (k', rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1)) =
    evaln k' (rfind' cf) (Nat.pair (unpair n).fst ((unpair n).snd + 1))
[PROOFSTEP]
rw [hg (Nat.pair_lt_pair_left _ k'.lt_succ_self)]
[GOAL]
this :
  Primrec₂ fun x n =>
    let a := ofNat (ℕ × Code) n;
    List.map (evaln a.fst a.snd) (List.range a.fst)
x✝ : (ℕ × Code) × ℕ
k : ℕ
c : Code
n : ℕ
⊢ (Option.bind
      (List.get?
        (let a := ofNat (ℕ × Code) (encode ((k, c), n).fst);
        List.map (evaln a.fst a.snd) (List.range a.fst))
        ((k, c), n).snd)
      fun b => (((k, c), n), b).snd) =
    evaln ((k, c), n).fst.fst ((k, c), n).fst.snd ((k, c), n).snd
[PROOFSTEP]
simp [evaln_map]
[GOAL]
c : Code
n x : ℕ
⊢ x ∈ eval c n ↔ x ∈ rfindOpt fun k => evaln k c n
[PROOFSTEP]
refine' evaln_complete.trans (Nat.rfindOpt_mono _).symm
[GOAL]
c : Code
n x : ℕ
⊢ ∀ {a m n_1 : ℕ}, m ≤ n_1 → a ∈ evaln m c n → a ∈ evaln n_1 c n
[PROOFSTEP]
intro a m n hl
[GOAL]
c : Code
n✝ x a m n : ℕ
hl : m ≤ n
⊢ a ∈ evaln m c n✝ → a ∈ evaln n c n✝
[PROOFSTEP]
apply evaln_mono hl
[GOAL]
a : Code × ℕ
⊢ (rfindOpt fun b =>
      evaln (((a, b).snd, (a, b).fst.fst), (a, b).fst.snd).fst.fst
        (((a, b).snd, (a, b).fst.fst), (a, b).fst.snd).fst.snd (((a, b).snd, (a, b).fst.fst), (a, b).fst.snd).snd) =
    eval a.fst a.snd
[PROOFSTEP]
simp [eval_eq_rfindOpt]
[GOAL]
f : Code → Code
hf : Computable f
g : ℕ → ℕ → Part ℕ :=
  fun x y => do
    let b ← eval (ofNat Code x) x
    eval (ofNat Code b) y
this : Partrec₂ g
cg : Code
eg : eval cg = fun n => Part.bind ↑(decode n) fun a => Part.map encode ((fun p => g p.fst p.snd) a)
⊢ ∀ (a n : ℕ), eval cg (Nat.pair a n) = Part.map encode (g a n)
[PROOFSTEP]
simp [eg]
[GOAL]
f : Code → Code
hf : Computable f
g : ℕ → ℕ → Part ℕ :=
  fun x y => do
    let b ← eval (ofNat Code x) x
    eval (ofNat Code b) y
this✝ : Partrec₂ g
cg : Code
eg : eval cg = fun n => Part.bind ↑(decode n) fun a => Part.map encode ((fun p => g p.fst p.snd) a)
eg' : ∀ (a n : ℕ), eval cg (Nat.pair a n) = Part.map encode (g a n)
F : ℕ → Code := fun x => f (curry cg x)
this : Computable F
cF : Code
eF : eval cF = fun n => Part.bind ↑(decode n) fun a => Part.map encode (↑F a)
⊢ eval cF (encode cF) = Part.some (encode (F (encode cF)))
[PROOFSTEP]
simp [eF]
[GOAL]
f : Code → Code
hf : Computable f
g : ℕ → ℕ → Part ℕ :=
  fun x y => do
    let b ← eval (ofNat Code x) x
    eval (ofNat Code b) y
this✝ : Partrec₂ g
cg : Code
eg : eval cg = fun n => Part.bind ↑(decode n) fun a => Part.map encode ((fun p => g p.fst p.snd) a)
eg' : ∀ (a n : ℕ), eval cg (Nat.pair a n) = Part.map encode (g a n)
F : ℕ → Code := fun x => f (curry cg x)
this : Computable F
cF : Code
eF : eval cF = fun n => Part.bind ↑(decode n) fun a => Part.map encode (↑F a)
eF' : eval cF (encode cF) = Part.some (encode (F (encode cF)))
n : ℕ
⊢ eval (f (curry cg (encode cF))) n = eval (curry cg (encode cF)) n
[PROOFSTEP]
simp [eg', eF', Part.map_id']
[GOAL]
f : Code → ℕ →. ℕ
hf : Partrec₂ f
cf : Code
ef : eval cf = fun n => Part.bind ↑(decode n) fun a => Part.map encode ((fun p => f p.fst p.snd) a)
c : Code
e : eval (curry cf (encode c)) = eval c
n : ℕ
⊢ eval c n = f c n
[PROOFSTEP]
simp [e.symm, ef, Part.map_id']
