l3lab/ntp-mathlib huggingface dataset:
theorem exists_code {n} {f : Vector ℕ n →. ℕ} (hf : Nat.Partrec' f) :
    ∃ c : Code, ∀ v : Vector ℕ n, c.eval v.1 = pure <$> f v := by
  induction' hf with n f hf
  induction hf
  case prim.zero => exact ⟨zero', fun ⟨[], _⟩ => rfl⟩
  case prim.succ => exact ⟨succ, fun ⟨[v], _⟩ => rfl⟩
  case prim.get n i =>
    refine' Fin.succRec (fun n => _) (fun n i IH => _) i
    · exact ⟨head, fun ⟨List.cons a as, _⟩ => by simp [Bind.bind]; rfl⟩
    · obtain ⟨c, h⟩ := IH
      exact ⟨c.comp tail, fun v => by simpa [← Vector.get_tail, Bind.bind] using h v.tail⟩
  case prim.comp m n f g hf hg IHf IHg =>
    simpa [Part.bind_eq_bind] using exists_code.comp IHf IHg
  case prim.prec n f g _ _ IHf IHg =>
    obtain ⟨cf, hf⟩ := IHf
    obtain ⟨cg, hg⟩ := IHg
    simp only [Part.map_eq_map, Part.map_some, PFun.coe_val] at hf hg
    refine' ⟨prec cf cg, fun v => _⟩
    rw [← v.cons_head_tail]
    specialize hf v.tail
    replace hg := fun a b => hg (a ::ᵥ b ::ᵥ v.tail)
    simp only [Vector.cons_val, Vector.tail_val] at hf hg
    simp only [Part.map_eq_map, Part.map_some, Vector.cons_val, Vector.tail_cons, Vector.head_cons,
      PFun.coe_val, Vector.tail_val]
    simp only [← Part.pure_eq_some] at hf hg ⊢
    induction' v.head with n _ <;>
      simp [prec, hf, Part.bind_assoc, ← Part.bind_some_eq_map, Part.bind_some,
        show ∀ x, pure x = [x] from fun _ => rfl, Bind.bind, Functor.map]
    suffices ∀ a b, a + b = n →
      (n.succ :: 0 ::
        g (n ::ᵥ Nat.rec (f v.tail) (fun y IH => g (y ::ᵥ IH ::ᵥ v.tail)) n ::ᵥ v.tail) ::
            v.val.tail : List ℕ) ∈
        PFun.fix
          (fun v : List ℕ => Part.bind (cg.eval (v.headI :: v.tail.tail))
            (fun x => Part.some (if v.tail.headI = 0
              then Sum.inl
                (v.headI.succ :: v.tail.headI.pred :: x.headI :: v.tail.tail.tail : List ℕ)
              else Sum.inr
                (v.headI.succ :: v.tail.headI.pred :: x.headI :: v.tail.tail.tail))))
          (a :: b :: Nat.rec (f v.tail) (fun y IH => g (y ::ᵥ IH ::ᵥ v.tail)) a :: v.val.tail) by
      erw [Part.eq_some_iff.2 (this 0 n (zero_add n))]
      simp only [List.headI, Part.bind_some, List.tail_cons]
    intro a b e
    induction' b with b IH generalizing a
    · refine' PFun.mem_fix_iff.2 (Or.inl <| Part.eq_some_iff.1 _)
      simp only [hg, ← e, Part.bind_some, List.tail_cons, pure]
      rfl
    · refine' PFun.mem_fix_iff.2 (Or.inr ⟨_, _, IH (a + 1) (by rwa [add_right_comm])⟩)
      simp only [hg, eval, Part.bind_some, Nat.rec_add_one, List.tail_nil, List.tail_cons, pure]
      exact Part.mem_some_iff.2 rfl
  

Proof state:
n✝ : ℕ
f✝ : Vector ℕ n✝ →. ℕ
m n : ℕ
f : Vector ℕ n →. ℕ
g : Fin n → Vector ℕ m →. ℕ
a✝¹ : Nat.Partrec' f
a✝ : ∀ (i : Fin n), Nat.Partrec' (g i)
IHf : ∃ c, ∀ (v : Vector ℕ n), eval c ↑v = pure <$> f v
IHg : ∀ (i : Fin n), ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = pure <$> g i v
⊢ ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = pure <$> (fun v => (Vector.mOfFn fun i => g i v) >>= f) v

Next tactic:
case comp m n f g _ _ IHf IHg => exact exists_code.comp IHf IHg
theorem exists_code {n} {f : Vector ℕ n →. ℕ} (hf : Nat.Partrec' f) :
    ∃ c : Code, ∀ v : Vector ℕ n, c.eval v.1 = pure <$> f v := by
  induction' hf with n f hf
  induction hf
  case prim.zero => exact ⟨zero', fun ⟨[], _⟩ => rfl⟩
  case prim.succ => exact ⟨succ, fun ⟨[v], _⟩ => rfl⟩
  case prim.get n i =>
    refine' Fin.succRec (fun n => _) (fun n i IH => _) i
    · exact ⟨head, fun ⟨List.cons a as, _⟩ => by simp [Bind.bind]; rfl⟩
    · obtain ⟨c, h⟩ := IH
      exact ⟨c.comp tail, fun v => by simpa [← Vector.get_tail, Bind.bind] using h v.tail⟩
  case prim.comp m n f g hf hg IHf IHg =>
    simpa [Part.bind_eq_bind] using exists_code.comp IHf IHg
  case prim.prec n f g _ _ IHf IHg =>
    obtain ⟨cf, hf⟩ := IHf
    obtain ⟨cg, hg⟩ := IHg
    simp only [Part.map_eq_map, Part.map_some, PFun.coe_val] at hf hg
    refine' ⟨prec cf cg, fun v => _⟩
    rw [← v.cons_head_tail]
    specialize hf v.tail
    replace hg := fun a b => hg (a ::ᵥ b ::ᵥ v.tail)
    simp only [Vector.cons_val, Vector.tail_val] at hf hg
    simp only [Part.map_eq_map, Part.map_some, Vector.cons_val, Vector.tail_cons, Vector.head_cons,
      PFun.coe_val, Vector.tail_val]
    simp only [← Part.pure_eq_some] at hf hg ⊢
    induction' v.head with n _ <;>
      simp [prec, hf, Part.bind_assoc, ← Part.bind_some_eq_map, Part.bind_some,
        show ∀ x, pure x = [x] from fun _ => rfl, Bind.bind, Functor.map]
    suffices ∀ a b, a + b = n →
      (n.succ :: 0 ::
        g (n ::ᵥ Nat.rec (f v.tail) (fun y IH => g (y ::ᵥ IH ::ᵥ v.tail)) n ::ᵥ v.tail) ::
            v.val.tail : List ℕ) ∈
        PFun.fix
          (fun v : List ℕ => Part.bind (cg.eval (v.headI :: v.tail.tail))
            (fun x => Part.some (if v.tail.headI = 0
              then Sum.inl
                (v.headI.succ :: v.tail.headI.pred :: x.headI :: v.tail.tail.tail : List ℕ)
              else Sum.inr
                (v.headI.succ :: v.tail.headI.pred :: x.headI :: v.tail.tail.tail))))
          (a :: b :: Nat.rec (f v.tail) (fun y IH => g (y ::ᵥ IH ::ᵥ v.tail)) a :: v.val.tail) by
      erw [Part.eq_some_iff.2 (this 0 n (zero_add n))]
      simp only [List.headI, Part.bind_some, List.tail_cons]
    intro a b e
    induction' b with b IH generalizing a
    · refine' PFun.mem_fix_iff.2 (Or.inl <| Part.eq_some_iff.1 _)
      simp only [hg, ← e, Part.bind_some, List.tail_cons, pure]
      rfl
    · refine' PFun.mem_fix_iff.2 (Or.inr ⟨_, _, IH (a + 1) (by rwa [add_right_comm])⟩)
      simp only [hg, eval, Part.bind_some, Nat.rec_add_one, List.tail_nil, List.tail_cons, pure]
      exact Part.mem_some_iff.2 rfl
  case comp m n f g _ _ IHf IHg => 

Proof state:
n✝ : ℕ
f✝ : Vector ℕ n✝ →. ℕ
m n : ℕ
f : Vector ℕ n →. ℕ
g : Fin n → Vector ℕ m →. ℕ
a✝¹ : Nat.Partrec' f
a✝ : ∀ (i : Fin n), Nat.Partrec' (g i)
IHf : ∃ c, ∀ (v : Vector ℕ n), eval c ↑v = pure <$> f v
IHg : ∀ (i : Fin n), ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = pure <$> g i v
⊢ ∃ c, ∀ (v : Vector ℕ m), eval c ↑v = pure <$> (fun v => (Vector.mOfFn fun i => g i v) >>= f) v

Next tactic:
exact exists_code.comp IHf IHg
theorem exists_code {n} {f : Vector ℕ n →. ℕ} (hf : Nat.Partrec' f) :
    ∃ c : Code, ∀ v : Vector ℕ n, c.eval v.1 = pure <$> f v := by
  induction' hf with n f hf
  induction hf
  case prim.zero => exact ⟨zero', fun ⟨[], _⟩ => rfl⟩
  case prim.succ => exact ⟨succ, fun ⟨[v], _⟩ => rfl⟩
  case prim.get n i =>
    refine' Fin.succRec (fun n => _) (fun n i IH => _) i
    · exact ⟨head, fun ⟨List.cons a as, _⟩ => by simp [Bind.bind]; rfl⟩
    · obtain ⟨c, h⟩ := IH
      exact ⟨c.comp tail, fun v => by simpa [← Vector.get_tail, Bind.bind] using h v.tail⟩
  case prim.comp m n f g hf hg IHf IHg =>
    simpa [Part.bind_eq_bind] using exists_code.comp IHf IHg
  case prim.prec n f g _ _ IHf IHg =>
    obtain ⟨cf, hf⟩ := IHf
    obtain ⟨cg, hg⟩ := IHg
    simp only [Part.map_eq_map, Part.map_some, PFun.coe_val] at hf hg
    refine' ⟨prec cf cg, fun v => _⟩
    rw [← v.cons_head_tail]
    specialize hf v.tail
    replace hg := fun a b => hg (a ::ᵥ b ::ᵥ v.tail)
    simp only [Vector.cons_val, Vector.tail_val] at hf hg
    simp only [Part.map_eq_map, Part.map_some, Vector.cons_val, Vector.tail_cons, Vector.head_cons,
      PFun.coe_val, Vector.tail_val]
    simp only [← Part.pure_eq_some] at hf hg ⊢
    induction' v.head with n _ <;>
      simp [prec, hf, Part.bind_assoc, ← Part.bind_some_eq_map, Part.bind_some,
        show ∀ x, pure x = [x] from fun _ => rfl, Bind.bind, Functor.map]
    suffices ∀ a b, a + b = n →
      (n.succ :: 0 ::
        g (n ::ᵥ Nat.rec (f v.tail) (fun y IH => g (y ::ᵥ IH ::ᵥ v.tail)) n ::ᵥ v.tail) ::
            v.val.tail : List ℕ) ∈
        PFun.fix
          (fun v : List ℕ => Part.bind (cg.eval (v.headI :: v.tail.tail))
            (fun x => Part.some (if v.tail.headI = 0
              then Sum.inl
                (v.headI.succ :: v.tail.headI.pred :: x.headI :: v.tail.tail.tail : List ℕ)
              else Sum.inr
                (v.headI.succ :: v.tail.headI.pred :: x.headI :: v.tail.tail.tail))))
          (a :: b :: Nat.rec (f v.tail) (fun y IH => g (y ::ᵥ IH ::ᵥ v.tail)) a :: v.val.tail) by
      erw [Part.eq_some_iff.2 (this 0 n (zero_add n))]
      simp only [List.headI, Part.bind_some, List.tail_cons]
    intro a b e
    induction' b with b IH generalizing a
    · refine' PFun.mem_fix_iff.2 (Or.inl <| Part.eq_some_iff.1 _)
      simp only [hg, ← e, Part.bind_some, List.tail_cons, pure]
      rfl
    · refine' PFun.mem_fix_iff.2 (Or.inr ⟨_, _, IH (a + 1) (by rwa [add_right_comm])⟩)
      simp only [hg, eval, Part.bind_some, Nat.rec_add_one, List.tail_nil, List.tail_cons, pure]
      exact Part.mem_some_iff.2 rfl
  case comp m n f g _ _ IHf IHg => exact exists_code.comp IHf IHg
  case rfind n f _ IHf =>
    

Proof state:
n✝ : ℕ
f✝ : Vector ℕ n✝ →. ℕ
n : ℕ
f : Vector ℕ (n + 1) → ℕ
a✝ : Nat.Partrec' ↑f
IHf : ∃ c, ∀ (v : Vector ℕ (n + 1)), eval c ↑v = pure <$> ↑f v
⊢ ∃ c, ∀ (v : Vector ℕ n), eval c ↑v = pure <$> (fun v => Nat.rfind fun n_1 => Part.some (decide (f (n_1 ::ᵥ v) = 0))) v

Next tactic:
obtain ⟨cf, hf⟩ := IHf
theorem exists_code {n} {f : Vector ℕ n →. ℕ} (hf : Nat.Partrec' f) :
    ∃ c : Code, ∀ v : Vector ℕ n, c.eval v.1 = pure <$> f v := by
  induction' hf with n f hf
  induction hf
  case prim.zero => exact ⟨zero', fun ⟨[], _⟩ => rfl⟩
  case prim.succ => exact ⟨succ, fun ⟨[v], _⟩ => rfl⟩
  case prim.get n i =>
    refine' Fin.succRec (fun n => _) (fun n i IH => _) i
    · exact ⟨head, fun ⟨List.cons a as, _⟩ => by simp [Bind.bind]; rfl⟩
    · obtain ⟨c, h⟩ := IH
      exact ⟨c.comp tail, fun v => by simpa [← Vector.get_tail, Bind.bind] using h v.tail⟩
  case prim.comp m n f g hf hg IHf IHg =>
    simpa [Part.bind_eq_bind] using exists_code.comp IHf IHg
  case prim.prec n f g _ _ IHf IHg =>
    obtain ⟨cf, hf⟩ := IHf
    obtain ⟨cg, hg⟩ := IHg
    simp only [Part.map_eq_map, Part.map_some, PFun.coe_val] at hf hg
    refine' ⟨prec cf cg, fun v => _⟩
    rw [← v.cons_head_tail]
    specialize hf v.tail
    replace hg := fun a b => hg (a ::ᵥ b ::ᵥ v.tail)
    simp only [Vector.cons_val, Vector.tail_val] at hf hg
    simp only [Part.map_eq_map, Part.map_some, Vector.cons_val, Vector.tail_cons, Vector.head_cons,
      PFun.coe_val, Vector.tail_val]
    simp only [← Part.pure_eq_some] at hf hg ⊢
    induction' v.head with n _ <;>
      simp [prec, hf, Part.bind_assoc, ← Part.bind_some_eq_map, Part.bind_some,
        show ∀ x, pure x = [x] from fun _ => rfl, Bind.bind, Functor.map]
    suffices ∀ a b, a + b = n →
      (n.succ :: 0 ::
        g (n ::ᵥ Nat.rec (f v.tail) (fun y IH => g (y ::ᵥ IH ::ᵥ v.tail)) n ::ᵥ v.tail) ::
            v.val.tail : List ℕ) ∈
        PFun.fix
          (fun v : List ℕ => Part.bind (cg.eval (v.headI :: v.tail.tail))
            (fun x => Part.some (if v.tail.headI = 0
              then Sum.inl
                (v.headI.succ :: v.tail.headI.pred :: x.headI :: v.tail.tail.tail : List ℕ)
              else Sum.inr
                (v.headI.succ :: v.tail.headI.pred :: x.headI :: v.tail.tail.tail))))
          (a :: b :: Nat.rec (f v.tail) (fun y IH => g (y ::ᵥ IH ::ᵥ v.tail)) a :: v.val.tail) by
      erw [Part.eq_some_iff.2 (this 0 n (zero_add n))]
      simp only [List.headI, Part.bind_some, List.tail_cons]
    intro a b e
    induction' b with b IH generalizing a
    · refine' PFun.mem_fix_iff.2 (Or.inl <| Part.eq_some_iff.1 _)
      simp only [hg, ← e, Part.bind_some, List.tail_cons, pure]
      rfl
    · refine' PFun.mem_fix_iff.2 (Or.inr ⟨_, _, IH (a + 1) (by rwa [add_right_comm])⟩)
      simp only [hg, eval, Part.bind_some, Nat.rec_add_one, List.tail_nil, List.tail_cons, pure]
      exact Part.mem_some_iff.2 rfl
  case comp m n f g _ _ IHf IHg => exact exists_code.comp IHf IHg
  case rfind n f _ IHf =>
    obtain ⟨cf, hf⟩ := IHf; 

Proof state:
case intro
n✝ : ℕ
f✝ : Vector ℕ n✝ →. ℕ
n : ℕ
f : Vector ℕ (n + 1) → ℕ
a✝ : Nat.Partrec' ↑f
cf : Code
hf : ∀ (v : Vector ℕ (n + 1)), eval cf ↑v = pure <$> ↑f v
⊢ ∃ c, ∀ (v : Vector ℕ n), eval c ↑v = pure <$> (fun v => Nat.rfind fun n_1 => Part.some (decide (f (n_1 ::ᵥ v) = 0))) v

Next tactic:
refine' ⟨rfind cf, fun v => _⟩
theorem exists_code {n} {f : Vector ℕ n →. ℕ} (hf : Nat.Partrec' f) :
    ∃ c : Code, ∀ v : Vector ℕ n, c.eval v.1 = pure <$> f v := by
  induction' hf with n f hf
  induction hf
  case prim.zero => exact ⟨zero', fun ⟨[], _⟩ => rfl⟩
  case prim.succ => exact ⟨succ, fun ⟨[v], _⟩ => rfl⟩
  case prim.get n i =>
    refine' Fin.succRec (fun n => _) (fun n i IH => _) i
    · exact ⟨head, fun ⟨List.cons a as, _⟩ => by simp [Bind.bind]; rfl⟩
    · obtain ⟨c, h⟩ := IH
      exact ⟨c.comp tail, fun v => by simpa [← Vector.get_tail, Bind.bind] using h v.tail⟩
  case prim.comp m n f g hf hg IHf IHg =>
    simpa [Part.bind_eq_bind] using exists_code.comp IHf IHg
  case prim.prec n f g _ _ IHf IHg =>
    obtain ⟨cf, hf⟩ := IHf
    obtain ⟨cg, hg⟩ := IHg
    simp only [Part.map_eq_map, Part.map_some, PFun.coe_val] at hf hg
    refine' ⟨prec cf cg, fun v => _⟩
    rw [← v.cons_head_tail]
    specialize hf v.tail
    replace hg := fun a b => hg (a ::ᵥ b ::ᵥ v.tail)
    simp only [Vector.cons_val, Vector.tail_val] at hf hg
    simp only [Part.map_eq_map, Part.map_some, Vector.cons_val, Vector.tail_cons, Vector.head_cons,
      PFun.coe_val, Vector.tail_val]
    simp only [← Part.pure_eq_some] at hf hg ⊢
    induction' v.head with n _ <;>
      simp [prec, hf, Part.bind_assoc, ← Part.bind_some_eq_map, Part.bind_some,
        show ∀ x, pure x = [x] from fun _ => rfl, Bind.bind, Functor.map]
    suffices ∀ a b, a + b = n →
      (n.succ :: 0 ::
        g (n ::ᵥ Nat.rec (f v.tail) (fun y IH => g (y ::ᵥ IH ::ᵥ v.tail)) n ::ᵥ v.tail) ::
            v.val.tail : List ℕ) ∈
        PFun.fix
          (fun v : List ℕ => Part.bind (cg.eval (v.headI :: v.tail.tail))
            (fun x => Part.some (if v.tail.headI = 0
              then Sum.inl
                (v.headI.succ :: v.tail.headI.pred :: x.headI :: v.tail.tail.tail : List ℕ)
              else Sum.inr
                (v.headI.succ :: v.tail.headI.pred :: x.headI :: v.tail.tail.tail))))
          (a :: b :: Nat.rec (f v.tail) (fun y IH => g (y ::ᵥ IH ::ᵥ v.tail)) a :: v.val.tail) by
      erw [Part.eq_some_iff.2 (this 0 n (zero_add n))]
      simp only [List.headI, Part.bind_some, List.tail_cons]
    intro a b e
    induction' b with b IH generalizing a
    · refine' PFun.mem_fix_iff.2 (Or.inl <| Part.eq_some_iff.1 _)
      simp only [hg, ← e, Part.bind_some, List.tail_cons, pure]
      rfl
    · refine' PFun.mem_fix_iff.2 (Or.inr ⟨_, _, IH (a + 1) (by rwa [add_right_comm])⟩)
      simp only [hg, eval, Part.bind_some, Nat.rec_add_one, List.tail_nil, List.tail_cons, pure]
      exact Part.mem_some_iff.2 rfl
  case comp m n f g _ _ IHf IHg => exact exists_code.comp IHf IHg
  case rfind n f _ IHf =>
    obtain ⟨cf, hf⟩ := IHf; refine' ⟨rfind cf, fun v => _⟩
    

Proof state:
case intro
n✝ : ℕ
f✝ : Vector ℕ n✝ →. ℕ
n : ℕ
f : Vector ℕ (n + 1) → ℕ
a✝ : Nat.Partrec' ↑f
cf : Code
hf : ∀ (v : Vector ℕ (n + 1)), eval cf ↑v = pure <$> ↑f v
v : Vector ℕ n
⊢ eval (rfind cf) ↑v = pure <$> (fun v => Nat.rfind fun n_1 => Part.some (decide (f (n_1 ::ᵥ v) = 0))) v

Next tactic:
replace hf := fun a => hf (a ::ᵥ v)
theorem Cont.then_eval {k k' : Cont} {v} : (k.then k').eval v = k.eval v >>= k'.eval := by
  

Proof state:
k k' : Cont
v : List ℕ
⊢ eval (then k k') v = eval k v >>= eval k'

Next tactic:
induction' k with _ _ _ _ _ _ _ _ _ k_ih _ _ k_ih generalizing v
theorem Cont.then_eval {k k' : Cont} {v} : (k.then k').eval v = k.eval v >>= k'.eval := by
  induction' k with _ _ _ _ _ _ _ _ _ k_ih _ _ k_ih generalizing v <;>
    

Proof state:
case halt
k' : Cont
v : List ℕ
⊢ eval (then halt k') v = eval halt v >>= eval k'

Next tactic:
simp only [Cont.eval, Cont.then, bind_assoc, pure_bind, *]
theorem Cont.then_eval {k k' : Cont} {v} : (k.then k').eval v = k.eval v >>= k'.eval := by
  induction' k with _ _ _ _ _ _ _ _ _ k_ih _ _ k_ih generalizing v <;>
    

Proof state:
case cons₁
k' : Cont
a✝² : Code
a✝¹ : List ℕ
a✝ : Cont
a_ih✝ : ∀ {v : List ℕ}, eval (then a✝ k') v = eval a✝ v >>= eval k'
v : List ℕ
⊢ eval (then (cons₁ a✝² a✝¹ a✝) k') v = eval (cons₁ a✝² a✝¹ a✝) v >>= eval k'

Next tactic:
simp only [Cont.eval, Cont.then, bind_assoc, pure_bind, *]
theorem Cont.then_eval {k k' : Cont} {v} : (k.then k').eval v = k.eval v >>= k'.eval := by
  induction' k with _ _ _ _ _ _ _ _ _ k_ih _ _ k_ih generalizing v <;>
    

Proof state:
case cons₂
k' : Cont
a✝¹ : List ℕ
a✝ : Cont
a_ih✝ : ∀ {v : List ℕ}, eval (then a✝ k') v = eval a✝ v >>= eval k'
v : List ℕ
⊢ eval (then (cons₂ a✝¹ a✝) k') v = eval (cons₂ a✝¹ a✝) v >>= eval k'

Next tactic:
simp only [Cont.eval, Cont.then, bind_assoc, pure_bind, *]
theorem Cont.then_eval {k k' : Cont} {v} : (k.then k').eval v = k.eval v >>= k'.eval := by
  induction' k with _ _ _ _ _ _ _ _ _ k_ih _ _ k_ih generalizing v <;>
    

Proof state:
case comp
k' : Cont
a✝¹ : Code
a✝ : Cont
k_ih : ∀ {v : List ℕ}, eval (then a✝ k') v = eval a✝ v >>= eval k'
v : List ℕ
⊢ eval (then (comp a✝¹ a✝) k') v = eval (comp a✝¹ a✝) v >>= eval k'

Next tactic:
simp only [Cont.eval, Cont.then, bind_assoc, pure_bind, *]
theorem Cont.then_eval {k k' : Cont} {v} : (k.then k').eval v = k.eval v >>= k'.eval := by
  induction' k with _ _ _ _ _ _ _ _ _ k_ih _ _ k_ih generalizing v <;>
    

Proof state:
case fix
k' : Cont
a✝¹ : Code
a✝ : Cont
k_ih : ∀ {v : List ℕ}, eval (then a✝ k') v = eval a✝ v >>= eval k'
v : List ℕ
⊢ eval (then (fix a✝¹ a✝) k') v = eval (fix a✝¹ a✝) v >>= eval k'

Next tactic:
simp only [Cont.eval, Cont.then, bind_assoc, pure_bind, *]
theorem Cont.then_eval {k k' : Cont} {v} : (k.then k').eval v = k.eval v >>= k'.eval := by
  induction' k with _ _ _ _ _ _ _ _ _ k_ih _ _ k_ih generalizing v <;>
    simp only [Cont.eval, Cont.then, bind_assoc, pure_bind, *]
  · 

Proof state:
case comp
k' : Cont
a✝¹ : Code
a✝ : Cont
k_ih : ∀ {v : List ℕ}, eval (then a✝ k') v = eval a✝ v >>= eval k'
v : List ℕ
⊢ Code.eval a✝¹ v >>= eval (then a✝ k') = Code.eval a✝¹ v >>= fun x => eval a✝ x >>= eval k'

Next tactic:
simp only [← k_ih]
theorem Cont.then_eval {k k' : Cont} {v} : (k.then k').eval v = k.eval v >>= k'.eval := by
  induction' k with _ _ _ _ _ _ _ _ _ k_ih _ _ k_ih generalizing v <;>
    simp only [Cont.eval, Cont.then, bind_assoc, pure_bind, *]
  · simp only [← k_ih]
  · 

Proof state:
case fix
k' : Cont
a✝¹ : Code
a✝ : Cont
k_ih : ∀ {v : List ℕ}, eval (then a✝ k') v = eval a✝ v >>= eval k'
v : List ℕ
⊢ (if List.headI v = 0 then eval a✝ (List.tail v) >>= eval k'
    else Code.eval (Code.fix a✝¹) (List.tail v) >>= eval (then a✝ k')) =
    (if List.headI v = 0 then eval a✝ (List.tail v) else Code.eval (Code.fix a✝¹) (List.tail v) >>= eval a✝) >>= eval k'

Next tactic:
split_ifs <;> [rfl; simp only [← k_ih, bind_assoc]]
theorem Cont.then_eval {k k' : Cont} {v} : (k.then k').eval v = k.eval v >>= k'.eval := by
  induction' k with _ _ _ _ _ _ _ _ _ k_ih _ _ k_ih generalizing v <;>
    simp only [Cont.eval, Cont.then, bind_assoc, pure_bind, *]
  · simp only [← k_ih]
  · 

Proof state:
case fix
k' : Cont
a✝¹ : Code
a✝ : Cont
k_ih : ∀ {v : List ℕ}, eval (then a✝ k') v = eval a✝ v >>= eval k'
v : List ℕ
⊢ (if List.headI v = 0 then eval a✝ (List.tail v) >>= eval k'
    else Code.eval (Code.fix a✝¹) (List.tail v) >>= eval (then a✝ k')) =
    (if List.headI v = 0 then eval a✝ (List.tail v) else Code.eval (Code.fix a✝¹) (List.tail v) >>= eval a✝) >>= eval k'

Next tactic:
split_ifs
theorem Cont.then_eval {k k' : Cont} {v} : (k.then k').eval v = k.eval v >>= k'.eval := by
  induction' k with _ _ _ _ _ _ _ _ _ k_ih _ _ k_ih generalizing v <;>
    simp only [Cont.eval, Cont.then, bind_assoc, pure_bind, *]
  · simp only [← k_ih]
  · split_ifs <;> [

Proof state:
case pos
k' : Cont
a✝¹ : Code
a✝ : Cont
k_ih : ∀ {v : List ℕ}, eval (then a✝ k') v = eval a✝ v >>= eval k'
v : List ℕ
h✝ : List.headI v = 0
⊢ eval a✝ (List.tail v) >>= eval k' = eval a✝ (List.tail v) >>= eval k'

Next tactic:
rfl
theorem Cont.then_eval {k k' : Cont} {v} : (k.then k').eval v = k.eval v >>= k'.eval := by
  induction' k with _ _ _ _ _ _ _ _ _ k_ih _ _ k_ih generalizing v <;>
    simp only [Cont.eval, Cont.then, bind_assoc, pure_bind, *]
  · simp only [← k_ih]
  · split_ifs <;> [rfl; 

Proof state:
case neg
k' : Cont
a✝¹ : Code
a✝ : Cont
k_ih : ∀ {v : List ℕ}, eval (then a✝ k') v = eval a✝ v >>= eval k'
v : List ℕ
h✝ : ¬List.headI v = 0
⊢ Code.eval (Code.fix a✝¹) (List.tail v) >>= eval (then a✝ k') =
    Code.eval (Code.fix a✝¹) (List.tail v) >>= eval a✝ >>= eval k'

Next tactic:
simp only [← k_ih, bind_assoc]
/-- The `stepNormal` function respects the `then k'` homomorphism. Note that this is an exact
equality, not a simulation; the original and embedded machines move in lock-step until the
embedded machine reaches the halt state. -/
theorem stepNormal_then (c) (k k' : Cont) (v) :
    stepNormal c (k.then k') v = (stepNormal c k v).then k' := by
  

Proof state:
c : Code
k k' : Cont
v : List ℕ
⊢ stepNormal c (Cont.then k k') v = Cfg.then (stepNormal c k v) k'

Next tactic:
induction c generalizing k v
/-- The `stepNormal` function respects the `then k'` homomorphism. Note that this is an exact
equality, not a simulation; the original and embedded machines move in lock-step until the
embedded machine reaches the halt state. -/
theorem stepNormal_then (c) (k k' : Cont) (v) :
    stepNormal c (k.then k') v = (stepNormal c k v).then k' := by
  induction c generalizing k v <;> 

Proof state:
case zero'
k' k : Cont
v : List ℕ
⊢ stepNormal Code.zero' (Cont.then k k') v = Cfg.then (stepNormal Code.zero' k v) k'

Next tactic:
simp only [Cont.then, stepNormal, *]
/-- The `stepNormal` function respects the `then k'` homomorphism. Note that this is an exact
equality, not a simulation; the original and embedded machines move in lock-step until the
embedded machine reaches the halt state. -/
theorem stepNormal_then (c) (k k' : Cont) (v) :
    stepNormal c (k.then k') v = (stepNormal c k v).then k' := by
  induction c generalizing k v <;> 

Proof state:
case succ
k' k : Cont
v : List ℕ
⊢ stepNormal Code.succ (Cont.then k k') v = Cfg.then (stepNormal Code.succ k v) k'

Next tactic:
simp only [Cont.then, stepNormal, *]
/-- The `stepNormal` function respects the `then k'` homomorphism. Note that this is an exact
equality, not a simulation; the original and embedded machines move in lock-step until the
embedded machine reaches the halt state. -/
theorem stepNormal_then (c) (k k' : Cont) (v) :
    stepNormal c (k.then k') v = (stepNormal c k v).then k' := by
  induction c generalizing k v <;> 

Proof state:
case tail
k' k : Cont
v : List ℕ
⊢ stepNormal Code.tail (Cont.then k k') v = Cfg.then (stepNormal Code.tail k v) k'

Next tactic:
simp only [Cont.then, stepNormal, *]
/-- The `stepNormal` function respects the `then k'` homomorphism. Note that this is an exact
equality, not a simulation; the original and embedded machines move in lock-step until the
embedded machine reaches the halt state. -/
theorem stepNormal_then (c) (k k' : Cont) (v) :
    stepNormal c (k.then k') v = (stepNormal c k v).then k' := by
  induction c generalizing k v <;> 

Proof state:
case cons
k' : Cont
a✝¹ a✝ : Code
a_ih✝¹ : ∀ (k : Cont) (v : List ℕ), stepNormal a✝¹ (Cont.then k k') v = Cfg.then (stepNormal a✝¹ k v) k'
a_ih✝ : ∀ (k : Cont) (v : List ℕ), stepNormal a✝ (Cont.then k k') v = Cfg.then (stepNormal a✝ k v) k'
k : Cont
v : List ℕ
⊢ stepNormal (Code.cons a✝¹ a✝) (Cont.then k k') v = Cfg.then (stepNormal (Code.cons a✝¹ a✝) k v) k'

Next tactic:
simp only [Cont.then, stepNormal, *]
/-- The `stepNormal` function respects the `then k'` homomorphism. Note that this is an exact
equality, not a simulation; the original and embedded machines move in lock-step until the
embedded machine reaches the halt state. -/
theorem stepNormal_then (c) (k k' : Cont) (v) :
    stepNormal c (k.then k') v = (stepNormal c k v).then k' := by
  induction c generalizing k v <;> 

Proof state:
case comp
k' : Cont
a✝¹ a✝ : Code
a_ih✝¹ : ∀ (k : Cont) (v : List ℕ), stepNormal a✝¹ (Cont.then k k') v = Cfg.then (stepNormal a✝¹ k v) k'
a_ih✝ : ∀ (k : Cont) (v : List ℕ), stepNormal a✝ (Cont.then k k') v = Cfg.then (stepNormal a✝ k v) k'
k : Cont
v : List ℕ
⊢ stepNormal (Code.comp a✝¹ a✝) (Cont.then k k') v = Cfg.then (stepNormal (Code.comp a✝¹ a✝) k v) k'

Next tactic:
simp only [Cont.then, stepNormal, *]