l3lab/ntp-mathlib huggingface dataset:
/-- The `Nat.Partrec.Code.evaln` function is primitive recursive. -/
theorem evaln_prim : Primrec fun a : (ℕ × Code) × ℕ => evaln a.1.1 a.1.2 a.2 :=
  have :
    Primrec₂ fun (_ : Unit) (n : ℕ) =>
      let a := ofNat (ℕ × Code) n
      (List.range a.1).map (evaln a.1 a.2) :=
    Primrec.nat_strong_rec _ (hG.comp Primrec.snd).to₂ fun _ p => by
      simp only [G, prod_ofNat_val, ofNat_nat, List.length_map, List.length_range,
        Nat.pair_unpair, Option.some_inj]
      refine List.map_congr fun n => ?_
      have : List.range p = List.range (Nat.pair p.unpair.1 (encode (ofNat Code p.unpair.2))) := by
        simp
      rw [this]
      generalize p.unpair.1 = k
      generalize ofNat Code p.unpair.2 = c
      intro nk
      cases' k with k'
      · simp [evaln]
      let k := k' + 1
      simp only [show k'.succ = k from rfl]
      simp? [Nat.lt_succ_iff] at nk says simp only [List.mem_range, lt_succ_iff] at nk
      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]
      cases' c with cf cg cf cg cf cg cf <;>
        simp [evaln, nk, Bind.bind, Functor.map, Seq.seq, pure]
      · cases' encode_lt_pair cf cg with lf lg
        rw [hg (Nat.pair_lt_pair_right _ lf), hg (Nat.pair_lt_pair_right _ lg)]
        cases evaln k cf n
        · rfl
        cases evaln k cg n <;> rfl
      · cases' encode_lt_comp cf cg with lf lg
        

Proof state:
case succ.comp.intro
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).1 (encode (ofNat Code (unpair p).2)))
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).1 (ofNat Code (unpair n).2)) (List.range (unpair n).1))
            (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).1 (ofNat Code (unpair n).2)) (List.range (unpair n).1))
          (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).1 (ofNat Code (unpair n).2)) (List.range (unpair n).1))
          (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

Next tactic:
rw [hg (Nat.pair_lt_pair_right _ lg)]
/-- The `Nat.Partrec.Code.evaln` function is primitive recursive. -/
theorem evaln_prim : Primrec fun a : (ℕ × Code) × ℕ => evaln a.1.1 a.1.2 a.2 :=
  have :
    Primrec₂ fun (_ : Unit) (n : ℕ) =>
      let a := ofNat (ℕ × Code) n
      (List.range a.1).map (evaln a.1 a.2) :=
    Primrec.nat_strong_rec _ (hG.comp Primrec.snd).to₂ fun _ p => by
      simp only [G, prod_ofNat_val, ofNat_nat, List.length_map, List.length_range,
        Nat.pair_unpair, Option.some_inj]
      refine List.map_congr fun n => ?_
      have : List.range p = List.range (Nat.pair p.unpair.1 (encode (ofNat Code p.unpair.2))) := by
        simp
      rw [this]
      generalize p.unpair.1 = k
      generalize ofNat Code p.unpair.2 = c
      intro nk
      cases' k with k'
      · simp [evaln]
      let k := k' + 1
      simp only [show k'.succ = k from rfl]
      simp? [Nat.lt_succ_iff] at nk says simp only [List.mem_range, lt_succ_iff] at nk
      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]
      cases' c with cf cg cf cg cf cg cf <;>
        simp [evaln, nk, Bind.bind, Functor.map, Seq.seq, pure]
      · cases' encode_lt_pair cf cg with lf lg
        rw [hg (Nat.pair_lt_pair_right _ lf), hg (Nat.pair_lt_pair_right _ lg)]
        cases evaln k cf n
        · rfl
        cases evaln k cg n <;> rfl
      · cases' encode_lt_comp cf cg with lf lg
        rw [hg (Nat.pair_lt_pair_right _ lg)]
        

Proof state:
case succ.comp.intro
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).1 (encode (ofNat Code (unpair p).2)))
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).1 (ofNat Code (unpair n).2)) (List.range (unpair n).1))
            (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).1 (ofNat Code (unpair n).2)) (List.range (unpair n).1))
          (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

Next tactic:
cases evaln k cg n
/-- The `Nat.Partrec.Code.evaln` function is primitive recursive. -/
theorem evaln_prim : Primrec fun a : (ℕ × Code) × ℕ => evaln a.1.1 a.1.2 a.2 :=
  have :
    Primrec₂ fun (_ : Unit) (n : ℕ) =>
      let a := ofNat (ℕ × Code) n
      (List.range a.1).map (evaln a.1 a.2) :=
    Primrec.nat_strong_rec _ (hG.comp Primrec.snd).to₂ fun _ p => by
      simp only [G, prod_ofNat_val, ofNat_nat, List.length_map, List.length_range,
        Nat.pair_unpair, Option.some_inj]
      refine List.map_congr fun n => ?_
      have : List.range p = List.range (Nat.pair p.unpair.1 (encode (ofNat Code p.unpair.2))) := by
        simp
      rw [this]
      generalize p.unpair.1 = k
      generalize ofNat Code p.unpair.2 = c
      intro nk
      cases' k with k'
      · simp [evaln]
      let k := k' + 1
      simp only [show k'.succ = k from rfl]
      simp? [Nat.lt_succ_iff] at nk says simp only [List.mem_range, lt_succ_iff] at nk
      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]
      cases' c with cf cg cf cg cf cg cf <;>
        simp [evaln, nk, Bind.bind, Functor.map, Seq.seq, pure]
      · cases' encode_lt_pair cf cg with lf lg
        rw [hg (Nat.pair_lt_pair_right _ lf), hg (Nat.pair_lt_pair_right _ lg)]
        cases evaln k cf n
        · rfl
        cases evaln k cg n <;> rfl
      · cases' encode_lt_comp cf cg with lf lg
        rw [hg (Nat.pair_lt_pair_right _ lg)]
        cases evaln k cg n
        · 

Proof state:
case succ.comp.intro.none
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).1 (encode (ofNat Code (unpair p).2)))
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).1 (ofNat Code (unpair n).2)) (List.range (unpair n).1))
            (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).1 (ofNat Code (unpair n).2)) (List.range (unpair n).1))
          (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

Next tactic:
rfl
/-- The `Nat.Partrec.Code.evaln` function is primitive recursive. -/
theorem evaln_prim : Primrec fun a : (ℕ × Code) × ℕ => evaln a.1.1 a.1.2 a.2 :=
  have :
    Primrec₂ fun (_ : Unit) (n : ℕ) =>
      let a := ofNat (ℕ × Code) n
      (List.range a.1).map (evaln a.1 a.2) :=
    Primrec.nat_strong_rec _ (hG.comp Primrec.snd).to₂ fun _ p => by
      simp only [G, prod_ofNat_val, ofNat_nat, List.length_map, List.length_range,
        Nat.pair_unpair, Option.some_inj]
      refine List.map_congr fun n => ?_
      have : List.range p = List.range (Nat.pair p.unpair.1 (encode (ofNat Code p.unpair.2))) := by
        simp
      rw [this]
      generalize p.unpair.1 = k
      generalize ofNat Code p.unpair.2 = c
      intro nk
      cases' k with k'
      · simp [evaln]
      let k := k' + 1
      simp only [show k'.succ = k from rfl]
      simp? [Nat.lt_succ_iff] at nk says simp only [List.mem_range, lt_succ_iff] at nk
      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]
      cases' c with cf cg cf cg cf cg cf <;>
        simp [evaln, nk, Bind.bind, Functor.map, Seq.seq, pure]
      · cases' encode_lt_pair cf cg with lf lg
        rw [hg (Nat.pair_lt_pair_right _ lf), hg (Nat.pair_lt_pair_right _ lg)]
        cases evaln k cf n
        · rfl
        cases evaln k cg n <;> rfl
      · cases' encode_lt_comp cf cg with lf lg
        rw [hg (Nat.pair_lt_pair_right _ lg)]
        cases evaln k cg n
        · rfl
        

Proof state:
case succ.comp.intro.some
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).1 (encode (ofNat Code (unpair p).2)))
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).1 (ofNat Code (unpair n).2)) (List.range (unpair n).1))
            (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).1 (ofNat Code (unpair n).2)) (List.range (unpair n).1))
          (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

Next tactic:
simp [hg (Nat.pair_lt_pair_right _ lf)]
/-- The `Nat.Partrec.Code.evaln` function is primitive recursive. -/
theorem evaln_prim : Primrec fun a : (ℕ × Code) × ℕ => evaln a.1.1 a.1.2 a.2 :=
  have :
    Primrec₂ fun (_ : Unit) (n : ℕ) =>
      let a := ofNat (ℕ × Code) n
      (List.range a.1).map (evaln a.1 a.2) :=
    Primrec.nat_strong_rec _ (hG.comp Primrec.snd).to₂ fun _ p => by
      simp only [G, prod_ofNat_val, ofNat_nat, List.length_map, List.length_range,
        Nat.pair_unpair, Option.some_inj]
      refine List.map_congr fun n => ?_
      have : List.range p = List.range (Nat.pair p.unpair.1 (encode (ofNat Code p.unpair.2))) := by
        simp
      rw [this]
      generalize p.unpair.1 = k
      generalize ofNat Code p.unpair.2 = c
      intro nk
      cases' k with k'
      · simp [evaln]
      let k := k' + 1
      simp only [show k'.succ = k from rfl]
      simp? [Nat.lt_succ_iff] at nk says simp only [List.mem_range, lt_succ_iff] at nk
      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]
      cases' c with cf cg cf cg cf cg cf <;>
        simp [evaln, nk, Bind.bind, Functor.map, Seq.seq, pure]
      · cases' encode_lt_pair cf cg with lf lg
        rw [hg (Nat.pair_lt_pair_right _ lf), hg (Nat.pair_lt_pair_right _ lg)]
        cases evaln k cf n
        · rfl
        cases evaln k cg n <;> rfl
      · cases' encode_lt_comp cf cg with lf lg
        rw [hg (Nat.pair_lt_pair_right _ lg)]
        cases evaln k cg n
        · rfl
        simp [hg (Nat.pair_lt_pair_right _ lf)]
      · cases' encode_lt_prec cf cg with lf lg
        rw [hg (Nat.pair_lt_pair_right _ lf)]
        cases n.unpair.2
        · rfl
        simp only [decode_eq_ofNat, Option.some.injEq]
        rw [hg (Nat.pair_lt_pair_left _ k'.lt_succ_self)]
        cases evaln k' _ _
        · 

Proof state:
case succ.prec.intro.succ.none
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).1 (encode (ofNat Code (unpair p).2)))
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).1 (ofNat Code (unpair n).2)) (List.range (unpair n).1))
            (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).1 (ofNat Code (unpair n).2)) (List.range (unpair n).1))
          (List.range (Nat.pair (k' + 1) (encode (prec cf cg)))))
        (k' + 1, cg) (Nat.pair (unpair n).1 (Nat.pair n✝ i))) =
    Option.bind Option.none fun i => evaln (k' + 1) cg (Nat.pair (unpair n).1 (Nat.pair n✝ i))

Next tactic:
rfl
/-- The `Nat.Partrec.Code.evaln` function is primitive recursive. -/
theorem evaln_prim : Primrec fun a : (ℕ × Code) × ℕ => evaln a.1.1 a.1.2 a.2 :=
  have :
    Primrec₂ fun (_ : Unit) (n : ℕ) =>
      let a := ofNat (ℕ × Code) n
      (List.range a.1).map (evaln a.1 a.2) :=
    Primrec.nat_strong_rec _ (hG.comp Primrec.snd).to₂ fun _ p => by
      simp only [G, prod_ofNat_val, ofNat_nat, List.length_map, List.length_range,
        Nat.pair_unpair, Option.some_inj]
      refine List.map_congr fun n => ?_
      have : List.range p = List.range (Nat.pair p.unpair.1 (encode (ofNat Code p.unpair.2))) := by
        simp
      rw [this]
      generalize p.unpair.1 = k
      generalize ofNat Code p.unpair.2 = c
      intro nk
      cases' k with k'
      · simp [evaln]
      let k := k' + 1
      simp only [show k'.succ = k from rfl]
      simp? [Nat.lt_succ_iff] at nk says simp only [List.mem_range, lt_succ_iff] at nk
      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]
      cases' c with cf cg cf cg cf cg cf <;>
        simp [evaln, nk, Bind.bind, Functor.map, Seq.seq, pure]
      · cases' encode_lt_pair cf cg with lf lg
        rw [hg (Nat.pair_lt_pair_right _ lf), hg (Nat.pair_lt_pair_right _ lg)]
        cases evaln k cf n
        · rfl
        cases evaln k cg n <;> rfl
      · cases' encode_lt_comp cf cg with lf lg
        rw [hg (Nat.pair_lt_pair_right _ lg)]
        cases evaln k cg n
        · rfl
        simp [hg (Nat.pair_lt_pair_right _ lf)]
      · cases' encode_lt_prec cf cg with lf lg
        rw [hg (Nat.pair_lt_pair_right _ lf)]
        cases n.unpair.2
        · rfl
        simp only [decode_eq_ofNat, Option.some.injEq]
        rw [hg (Nat.pair_lt_pair_left _ k'.lt_succ_self)]
        cases evaln k' _ _
        · rfl
        

Proof state:
case succ.prec.intro.succ.some
x✝ : Unit
p n : ℕ
this : List.range p = List.range (Nat.pair (unpair p).1 (encode (ofNat Code (unpair p).2)))
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).1 (ofNat Code (unpair n).2)) (List.range (unpair n).1))
            (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).1 (ofNat Code (unpair n).2)) (List.range (unpair n).1))
          (List.range (Nat.pair (k' + 1) (encode (prec cf cg)))))
        (k' + 1, cg) (Nat.pair (unpair n).1 (Nat.pair n✝ i))) =
    Option.bind (some val✝) fun i => evaln (k' + 1) cg (Nat.pair (unpair n).1 (Nat.pair n✝ i))

Next tactic:
simp [hg (Nat.pair_lt_pair_right _ lg)]
/-- The `Nat.Partrec.Code.evaln` function is primitive recursive. -/
theorem evaln_prim : Primrec fun a : (ℕ × Code) × ℕ => evaln a.1.1 a.1.2 a.2 :=
  have :
    Primrec₂ fun (_ : Unit) (n : ℕ) =>
      let a := ofNat (ℕ × Code) n
      (List.range a.1).map (evaln a.1 a.2) :=
    Primrec.nat_strong_rec _ (hG.comp Primrec.snd).to₂ fun _ p => by
      simp only [G, prod_ofNat_val, ofNat_nat, List.length_map, List.length_range,
        Nat.pair_unpair, Option.some_inj]
      refine List.map_congr fun n => ?_
      have : List.range p = List.range (Nat.pair p.unpair.1 (encode (ofNat Code p.unpair.2))) := by
        simp
      rw [this]
      generalize p.unpair.1 = k
      generalize ofNat Code p.unpair.2 = c
      intro nk
      cases' k with k'
      · simp [evaln]
      let k := k' + 1
      simp only [show k'.succ = k from rfl]
      simp? [Nat.lt_succ_iff] at nk says simp only [List.mem_range, lt_succ_iff] at nk
      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]
      cases' c with cf cg cf cg cf cg cf <;>
        simp [evaln, nk, Bind.bind, Functor.map, Seq.seq, pure]
      · cases' encode_lt_pair cf cg with lf lg
        rw [hg (Nat.pair_lt_pair_right _ lf), hg (Nat.pair_lt_pair_right _ lg)]
        cases evaln k cf n
        · rfl
        cases evaln k cg n <;> rfl
      · cases' encode_lt_comp cf cg with lf lg
        rw [hg (Nat.pair_lt_pair_right _ lg)]
        cases evaln k cg n
        · rfl
        simp [hg (Nat.pair_lt_pair_right _ lf)]
      · cases' encode_lt_prec cf cg with lf lg
        rw [hg (Nat.pair_lt_pair_right _ lf)]
        cases n.unpair.2
        · rfl
        simp only [decode_eq_ofNat, Option.some.injEq]
        rw [hg (Nat.pair_lt_pair_left _ k'.lt_succ_self)]
        cases evaln k' _ _
        · rfl
        simp [hg (Nat.pair_lt_pair_right _ lg)]
      · have lf := encode_lt_rfind' cf
        rw [hg (Nat.pair_lt_pair_right _ lf)]
        cases' evaln k cf n with x
        · rfl
        simp only [decode_eq_ofNat, Option.some.injEq, Option.some_bind]
        cases x <;> simp [Nat.succ_ne_zero]
        rw [hg (Nat.pair_lt_pair_left _ k'.lt_succ_self)]
  (Primrec.option_bind
    (Primrec.list_get?.comp (this.comp (_root_.Primrec.const ())
      (Primrec.encode_iff.2 Primrec.fst)) Primrec.snd) Primrec.snd.to₂).of_eq
    fun ⟨⟨k, c⟩, n⟩ => by 

Proof state:
this :
  Primrec₂ fun x n =>
    let a := ofNat (ℕ × Code) n;
    List.map (evaln a.1 a.2) (List.range a.1)
x✝ : (ℕ × Code) × ℕ
k : ℕ
c : Code
n : ℕ
⊢ (Option.bind
      (List.get?
        (let a := ofNat (ℕ × Code) (encode ((k, c), n).1);
        List.map (evaln a.1 a.2) (List.range a.1))
        ((k, c), n).2)
      fun b => (((k, c), n), b).2) =
    evaln ((k, c), n).1.1 ((k, c), n).1.2 ((k, c), n).2

Next tactic:
simp [evaln_map]
theorem eval_eq_rfindOpt (c n) : eval c n = Nat.rfindOpt fun k => evaln k c n :=
  Part.ext fun x => by
    

Proof state:
c : Code
n x : ℕ
⊢ x ∈ eval c n ↔ x ∈ rfindOpt fun k => evaln k c n

Next tactic:
refine' evaln_complete.trans (Nat.rfindOpt_mono _).symm
theorem eval_eq_rfindOpt (c n) : eval c n = Nat.rfindOpt fun k => evaln k c n :=
  Part.ext fun x => by
    refine' evaln_complete.trans (Nat.rfindOpt_mono _).symm
    

Proof state:
c : Code
n x : ℕ
⊢ ∀ {a m n_1 : ℕ}, m ≤ n_1 → a ∈ evaln m c n → a ∈ evaln n_1 c n

Next tactic:
intro a m n hl
theorem eval_eq_rfindOpt (c n) : eval c n = Nat.rfindOpt fun k => evaln k c n :=
  Part.ext fun x => by
    refine' evaln_complete.trans (Nat.rfindOpt_mono _).symm
    intro a m n hl; 

Proof state:
c : Code
n✝ x a m n : ℕ
hl : m ≤ n
⊢ a ∈ evaln m c n✝ → a ∈ evaln n c n✝

Next tactic:
apply evaln_mono hl
theorem eval_part : Partrec₂ eval :=
  (Partrec.rfindOpt
    (evaln_prim.to_comp.comp ((Computable.snd.pair (fst.comp fst)).pair (snd.comp fst))).to₂).of_eq
    fun a => by 

Proof state:
a : Code × ℕ
⊢ (rfindOpt fun b =>
      evaln (((a, b).2, (a, b).1.1), (a, b).1.2).1.1 (((a, b).2, (a, b).1.1), (a, b).1.2).1.2
        (((a, b).2, (a, b).1.1), (a, b).1.2).2) =
    eval a.1 a.2

Next tactic:
simp [eval_eq_rfindOpt]
/-- Roger's fixed-point theorem: Any total, computable `f` has a fixed point: That is, under the
interpretation given by `Nat.Partrec.Code.eval`, there is a code `c` such that `c` and `f c` have
the same evaluation.
-/
theorem fixed_point {f : Code → Code} (hf : Computable f) : ∃ c : Code, eval (f c) = eval c :=
  let g (x y : ℕ) : Part ℕ := eval (ofNat Code x) x >>= fun b => eval (ofNat Code b) y
  have : Partrec₂ g :=
    (eval_part.comp ((Computable.ofNat _).comp fst) fst).bind
      (eval_part.comp ((Computable.ofNat _).comp snd) (snd.comp fst)).to₂
  let ⟨cg, eg⟩ := exists_code.1 this
  have eg' : ∀ a n, eval cg (Nat.pair a n) = Part.map encode (g a n) := by 

Proof state:
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.1 p.2) a)
⊢ ∀ (a n : ℕ), eval cg (Nat.pair a n) = Part.map encode (g a n)

Next tactic:
simp [eg]
/-- Roger's fixed-point theorem: Any total, computable `f` has a fixed point: That is, under the
interpretation given by `Nat.Partrec.Code.eval`, there is a code `c` such that `c` and `f c` have
the same evaluation.
-/
theorem fixed_point {f : Code → Code} (hf : Computable f) : ∃ c : Code, eval (f c) = eval c :=
  let g (x y : ℕ) : Part ℕ := eval (ofNat Code x) x >>= fun b => eval (ofNat Code b) y
  have : Partrec₂ g :=
    (eval_part.comp ((Computable.ofNat _).comp fst) fst).bind
      (eval_part.comp ((Computable.ofNat _).comp snd) (snd.comp fst)).to₂
  let ⟨cg, eg⟩ := exists_code.1 this
  have eg' : ∀ a n, eval cg (Nat.pair a n) = Part.map encode (g a n) := by simp [eg]
  let F (x : ℕ) : Code := f (curry cg x)
  have : Computable F :=
    hf.comp (curry_prim.comp (_root_.Primrec.const cg) _root_.Primrec.id).to_comp
  let ⟨cF, eF⟩ := exists_code.1 this
  have eF' : eval cF (encode cF) = Part.some (encode (F (encode cF))) := by 

Proof state:
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.1 p.2) 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)))

Next tactic:
simp [eF]