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

tactic: simp only [G, prod_ofNat_val, ofNat_nat, List.length_map, List.length_range,
  Nat.pair_unpair, Option.some_inj]
state_before: 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))

tactic: refine List.map_congr fun n => ?_
state_before: 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)

tactic: have : List.range p = List.range (Nat.pair p.unpair.1 (encode (ofNat Code p.unpair.2))) := by
  simp
state_before: 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

tactic: rw [this]
state_before: 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

tactic: generalize p.unpair.1 = k
state_before: 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

tactic: generalize ofNat Code p.unpair.2 = c
state_before: 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

tactic: intro nk
state_before: 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

tactic: cases' k with k'
state_before: 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

tactic: let k := k' + 1
state_before: 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

tactic: simp only [show k'.succ = k from rfl]
state_before: 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

tactic: simp [Nat.lt_succ_iff] at nk
state_before: 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

tactic: 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]
state_before: 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

tactic: cases' c with cf cg cf cg cf cg cf <;>
  simp [evaln, nk, Bind.bind, Functor.map, Seq.seq, pure]
state_before: 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

tactic: simp
state_before: x✝ : Unit
p n : ℕ
⊢ List.range p = List.range (Nat.pair (unpair p).fst (encode (ofNat Code (unpair p).snd)))

tactic: simp [evaln]
state_before: 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

tactic: intro k₁ c₁ n₁ hl
state_before: 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

tactic: simp [lup, List.get?_range hl, evaln_map, Bind.bind]
state_before: 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₁

tactic: cases' encode_lt_pair cf cg with lf lg
state_before: 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)

tactic: rw [hg (Nat.pair_lt_pair_right _ lf), hg (Nat.pair_lt_pair_right _ lg)]
state_before: 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)

tactic: cases evaln k cf n
state_before: 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)

tactic: cases evaln k cg n <;> rfl
state_before: 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)

tactic: rfl
state_before: 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)

tactic: cases' encode_lt_comp cf cg with lf lg
state_before: 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

tactic: rw [hg (Nat.pair_lt_pair_right _ lg)]
state_before: 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

tactic: cases evaln k cg n
state_before: 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

tactic: simp [hg (Nat.pair_lt_pair_right _ lf)]
state_before: 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

tactic: rfl
state_before: 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

tactic: cases' encode_lt_prec cf cg with lf lg
state_before: 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

tactic: rw [hg (Nat.pair_lt_pair_right _ lf)]
state_before: 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

tactic: cases n.unpair.2
state_before: 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

tactic: simp
state_before: 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✝)

tactic: rw [hg (Nat.pair_lt_pair_left _ k'.lt_succ_self)]
state_before: 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))

tactic: cases evaln k' _ _
state_before: 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))

tactic: simp [hg (Nat.pair_lt_pair_right _ lg)]
state_before: 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))

tactic: rfl
state_before: 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

tactic: rfl
state_before: 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))

tactic: have lf := encode_lt_rfind' cf
state_before: 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))

tactic: rw [hg (Nat.pair_lt_pair_right _ lf)]
state_before: 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))

tactic: cases' evaln k cf n with x
state_before: 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))

tactic: simp
state_before: 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))

tactic: cases x <;> simp [Nat.succ_ne_zero]
state_before: 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))

tactic: rw [hg (Nat.pair_lt_pair_left _ k'.lt_succ_self)]
state_before: 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))

tactic: rfl
state_before: 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))

tactic: simp [evaln_map]
state_before: 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