l3lab/ntp-mathlib huggingface dataset:
theorem to_prim {n f} (pf : @Nat.Primrec' n f) : Primrec f := by
  induction pf
  case zero => exact .const 0
  

Proof state:
case succ
n : ℕ
f : Vector ℕ n → ℕ
⊢ Primrec fun v => Nat.succ (head v)
case get
n : ℕ
f : Vector ℕ n → ℕ
n✝ : ℕ
i✝ : Fin n✝
⊢ Primrec fun v => Vector.get v i✝
case comp
n : ℕ
f : Vector ℕ n → ℕ
m✝ n✝ : ℕ
f✝ : Vector ℕ n✝ → ℕ
g✝ : Fin n✝ → Vector ℕ m✝ → ℕ
a✝¹ : Primrec' f✝
a✝ : ∀ (i : Fin n✝), Primrec' (g✝ i)
a_ih✝¹ : Primrec f✝
a_ih✝ : ∀ (i : Fin n✝), Primrec (g✝ i)
⊢ Primrec fun a => f✝ (ofFn fun i => g✝ i a)
case prec
n : ℕ
f : Vector ℕ n → ℕ
n✝ : ℕ
f✝ : Vector ℕ n✝ → ℕ
g✝ : Vector ℕ (n✝ + 2) → ℕ
a✝¹ : Primrec' f✝
a✝ : Primrec' g✝
a_ih✝¹ : Primrec f✝
a_ih✝ : Primrec g✝
⊢ Primrec fun v => Nat.rec (f✝ (tail v)) (fun y IH => g✝ (y ::ᵥ IH ::ᵥ tail v)) (head v)

Next tactic:
case succ => exact _root_.Primrec.succ.comp .vector_head
theorem to_prim {n f} (pf : @Nat.Primrec' n f) : Primrec f := by
  induction pf
  case zero => exact .const 0
  

Proof state:
n : ℕ
f : Vector ℕ n → ℕ
⊢ Primrec fun v => Nat.succ (head v)

Next tactic:
case succ => exact _root_.Primrec.succ.comp .vector_head
theorem to_prim {n f} (pf : @Nat.Primrec' n f) : Primrec f := by
  induction pf
  case zero => exact .const 0
  case succ => 

Proof state:
n : ℕ
f : Vector ℕ n → ℕ
⊢ Primrec fun v => Nat.succ (head v)

Next tactic:
exact _root_.Primrec.succ.comp .vector_head
theorem to_prim {n f} (pf : @Nat.Primrec' n f) : Primrec f := by
  induction pf
  case zero => exact .const 0
  case succ => exact _root_.Primrec.succ.comp .vector_head
  

Proof state:
case get
n : ℕ
f : Vector ℕ n → ℕ
n✝ : ℕ
i✝ : Fin n✝
⊢ Primrec fun v => Vector.get v i✝
case comp
n : ℕ
f : Vector ℕ n → ℕ
m✝ n✝ : ℕ
f✝ : Vector ℕ n✝ → ℕ
g✝ : Fin n✝ → Vector ℕ m✝ → ℕ
a✝¹ : Primrec' f✝
a✝ : ∀ (i : Fin n✝), Primrec' (g✝ i)
a_ih✝¹ : Primrec f✝
a_ih✝ : ∀ (i : Fin n✝), Primrec (g✝ i)
⊢ Primrec fun a => f✝ (ofFn fun i => g✝ i a)
case prec
n : ℕ
f : Vector ℕ n → ℕ
n✝ : ℕ
f✝ : Vector ℕ n✝ → ℕ
g✝ : Vector ℕ (n✝ + 2) → ℕ
a✝¹ : Primrec' f✝
a✝ : Primrec' g✝
a_ih✝¹ : Primrec f✝
a_ih✝ : Primrec g✝
⊢ Primrec fun v => Nat.rec (f✝ (tail v)) (fun y IH => g✝ (y ::ᵥ IH ::ᵥ tail v)) (head v)

Next tactic:
case get n i => exact Primrec.vector_get.comp .id (.const i)
theorem to_prim {n f} (pf : @Nat.Primrec' n f) : Primrec f := by
  induction pf
  case zero => exact .const 0
  case succ => exact _root_.Primrec.succ.comp .vector_head
  

Proof state:
n✝ : ℕ
f : Vector ℕ n✝ → ℕ
n : ℕ
i : Fin n
⊢ Primrec fun v => Vector.get v i

Next tactic:
case get n i => exact Primrec.vector_get.comp .id (.const i)
theorem to_prim {n f} (pf : @Nat.Primrec' n f) : Primrec f := by
  induction pf
  case zero => exact .const 0
  case succ => exact _root_.Primrec.succ.comp .vector_head
  case get n i => 

Proof state:
n✝ : ℕ
f : Vector ℕ n✝ → ℕ
n : ℕ
i : Fin n
⊢ Primrec fun v => Vector.get v i

Next tactic:
exact Primrec.vector_get.comp .id (.const i)
theorem to_prim {n f} (pf : @Nat.Primrec' n f) : Primrec f := by
  induction pf
  case zero => exact .const 0
  case succ => exact _root_.Primrec.succ.comp .vector_head
  case get n i => exact Primrec.vector_get.comp .id (.const i)
  

Proof state:
case comp
n : ℕ
f : Vector ℕ n → ℕ
m✝ n✝ : ℕ
f✝ : Vector ℕ n✝ → ℕ
g✝ : Fin n✝ → Vector ℕ m✝ → ℕ
a✝¹ : Primrec' f✝
a✝ : ∀ (i : Fin n✝), Primrec' (g✝ i)
a_ih✝¹ : Primrec f✝
a_ih✝ : ∀ (i : Fin n✝), Primrec (g✝ i)
⊢ Primrec fun a => f✝ (ofFn fun i => g✝ i a)
case prec
n : ℕ
f : Vector ℕ n → ℕ
n✝ : ℕ
f✝ : Vector ℕ n✝ → ℕ
g✝ : Vector ℕ (n✝ + 2) → ℕ
a✝¹ : Primrec' f✝
a✝ : Primrec' g✝
a_ih✝¹ : Primrec f✝
a_ih✝ : Primrec g✝
⊢ Primrec fun v => Nat.rec (f✝ (tail v)) (fun y IH => g✝ (y ::ᵥ IH ::ᵥ tail v)) (head v)

Next tactic:
case comp m n f g _ _ hf hg => exact hf.comp (.vector_ofFn fun i => hg i)
theorem to_prim {n f} (pf : @Nat.Primrec' n f) : Primrec f := by
  induction pf
  case zero => exact .const 0
  case succ => exact _root_.Primrec.succ.comp .vector_head
  case get n i => exact Primrec.vector_get.comp .id (.const i)
  

Proof state:
n✝ : ℕ
f✝ : Vector ℕ n✝ → ℕ
m n : ℕ
f : Vector ℕ n → ℕ
g : Fin n → Vector ℕ m → ℕ
a✝¹ : Primrec' f
a✝ : ∀ (i : Fin n), Primrec' (g i)
hf : Primrec f
hg : ∀ (i : Fin n), Primrec (g i)
⊢ Primrec fun a => f (ofFn fun i => g i a)

Next tactic:
case comp m n f g _ _ hf hg => exact hf.comp (.vector_ofFn fun i => hg i)
theorem to_prim {n f} (pf : @Nat.Primrec' n f) : Primrec f := by
  induction pf
  case zero => exact .const 0
  case succ => exact _root_.Primrec.succ.comp .vector_head
  case get n i => exact Primrec.vector_get.comp .id (.const i)
  case comp m n f g _ _ hf hg => 

Proof state:
n✝ : ℕ
f✝ : Vector ℕ n✝ → ℕ
m n : ℕ
f : Vector ℕ n → ℕ
g : Fin n → Vector ℕ m → ℕ
a✝¹ : Primrec' f
a✝ : ∀ (i : Fin n), Primrec' (g i)
hf : Primrec f
hg : ∀ (i : Fin n), Primrec (g i)
⊢ Primrec fun a => f (ofFn fun i => g i a)

Next tactic:
exact hf.comp (.vector_ofFn fun i => hg i)
theorem to_prim {n f} (pf : @Nat.Primrec' n f) : Primrec f := by
  induction pf
  case zero => exact .const 0
  case succ => exact _root_.Primrec.succ.comp .vector_head
  case get n i => exact Primrec.vector_get.comp .id (.const i)
  case comp m n f g _ _ hf hg => exact hf.comp (.vector_ofFn fun i => hg i)
  

Proof state:
case prec
n : ℕ
f : Vector ℕ n → ℕ
n✝ : ℕ
f✝ : Vector ℕ n✝ → ℕ
g✝ : Vector ℕ (n✝ + 2) → ℕ
a✝¹ : Primrec' f✝
a✝ : Primrec' g✝
a_ih✝¹ : Primrec f✝
a_ih✝ : Primrec g✝
⊢ Primrec fun v => Nat.rec (f✝ (tail v)) (fun y IH => g✝ (y ::ᵥ IH ::ᵥ tail v)) (head v)

Next tactic:
case prec n f g _ _ hf hg =>
    exact
      .nat_rec' .vector_head (hf.comp Primrec.vector_tail)
        (hg.comp <|
          Primrec.vector_cons.comp (Primrec.fst.comp .snd) <|
          Primrec.vector_cons.comp (Primrec.snd.comp .snd) <|
            (@Primrec.vector_tail _ _ (n + 1)).comp .fst).to₂
theorem to_prim {n f} (pf : @Nat.Primrec' n f) : Primrec f := by
  induction pf
  case zero => exact .const 0
  case succ => exact _root_.Primrec.succ.comp .vector_head
  case get n i => exact Primrec.vector_get.comp .id (.const i)
  case comp m n f g _ _ hf hg => exact hf.comp (.vector_ofFn fun i => hg i)
  

Proof state:
n✝ : ℕ
f✝ : Vector ℕ n✝ → ℕ
n : ℕ
f : Vector ℕ n → ℕ
g : Vector ℕ (n + 2) → ℕ
a✝¹ : Primrec' f
a✝ : Primrec' g
hf : Primrec f
hg : Primrec g
⊢ Primrec fun v => Nat.rec (f (tail v)) (fun y IH => g (y ::ᵥ IH ::ᵥ tail v)) (head v)

Next tactic:
case prec n f g _ _ hf hg =>
    exact
      .nat_rec' .vector_head (hf.comp Primrec.vector_tail)
        (hg.comp <|
          Primrec.vector_cons.comp (Primrec.fst.comp .snd) <|
          Primrec.vector_cons.comp (Primrec.snd.comp .snd) <|
            (@Primrec.vector_tail _ _ (n + 1)).comp .fst).to₂
theorem to_prim {n f} (pf : @Nat.Primrec' n f) : Primrec f := by
  induction pf
  case zero => exact .const 0
  case succ => exact _root_.Primrec.succ.comp .vector_head
  case get n i => exact Primrec.vector_get.comp .id (.const i)
  case comp m n f g _ _ hf hg => exact hf.comp (.vector_ofFn fun i => hg i)
  case prec n f g _ _ hf hg =>
    

Proof state:
n✝ : ℕ
f✝ : Vector ℕ n✝ → ℕ
n : ℕ
f : Vector ℕ n → ℕ
g : Vector ℕ (n + 2) → ℕ
a✝¹ : Primrec' f
a✝ : Primrec' g
hf : Primrec f
hg : Primrec g
⊢ Primrec fun v => Nat.rec (f (tail v)) (fun y IH => g (y ::ᵥ IH ::ᵥ tail v)) (head v)

Next tactic:
exact
      .nat_rec' .vector_head (hf.comp Primrec.vector_tail)
        (hg.comp <|
          Primrec.vector_cons.comp (Primrec.fst.comp .snd) <|
          Primrec.vector_cons.comp (Primrec.snd.comp .snd) <|
            (@Primrec.vector_tail _ _ (n + 1)).comp .fst).to₂
theorem head {n : ℕ} : @Primrec' n.succ head :=
  (get 0).of_eq fun v => by 

Proof state:
n : ℕ
v : Vector ℕ (Nat.succ n)
⊢ Vector.get v 0 = Vector.head v

Next tactic:
simp [get_zero]
theorem tail {n f} (hf : @Primrec' n f) : @Primrec' n.succ fun v => f v.tail :=
  (hf.comp _ fun i => @get _ i.succ).of_eq fun v => by
    

Proof state:
n : ℕ
f : Vector ℕ n → ℕ
hf : Primrec' f
v : Vector ℕ (Nat.succ n)
⊢ f (ofFn fun i => Vector.get v (Fin.succ i)) = f (Vector.tail v)

Next tactic:
rw [← ofFn_get v.tail]
theorem tail {n f} (hf : @Primrec' n f) : @Primrec' n.succ fun v => f v.tail :=
  (hf.comp _ fun i => @get _ i.succ).of_eq fun v => by
    rw [← ofFn_get v.tail]; 

Proof state:
n : ℕ
f : Vector ℕ n → ℕ
hf : Primrec' f
v : Vector ℕ (Nat.succ n)
⊢ f (ofFn fun i => Vector.get v (Fin.succ i)) = f (ofFn (Vector.get (Vector.tail v)))

Next tactic:
congr
theorem tail {n f} (hf : @Primrec' n f) : @Primrec' n.succ fun v => f v.tail :=
  (hf.comp _ fun i => @get _ i.succ).of_eq fun v => by
    rw [← ofFn_get v.tail]; congr; 

Proof state:
case e_a.e_a
n : ℕ
f : Vector ℕ n → ℕ
hf : Primrec' f
v : Vector ℕ (Nat.succ n)
⊢ (fun i => Vector.get v (Fin.succ i)) = Vector.get (Vector.tail v)

Next tactic:
funext i
theorem tail {n f} (hf : @Primrec' n f) : @Primrec' n.succ fun v => f v.tail :=
  (hf.comp _ fun i => @get _ i.succ).of_eq fun v => by
    rw [← ofFn_get v.tail]; congr; funext i; 

Proof state:
case e_a.e_a.h
n : ℕ
f : Vector ℕ n → ℕ
hf : Primrec' f
v : Vector ℕ (Nat.succ n)
i : Fin n
⊢ Vector.get v (Fin.succ i) = Vector.get (Vector.tail v) i

Next tactic:
simp
protected theorem cons {n m f g} (hf : @Primrec' n f) (hg : @Vec n m g) :
    Vec fun v => f v ::ᵥ g v := fun i => Fin.cases (by 

Proof state:
n m : ℕ
f : Vector ℕ n → ℕ
g : Vector ℕ n → Vector ℕ m
hf : Primrec' f
hg : Vec g
i : Fin (Nat.succ m)
⊢ Primrec' fun v => Vector.get ((fun v => f v ::ᵥ g v) v) 0

Next tactic:
simp [*]
protected theorem cons {n m f g} (hf : @Primrec' n f) (hg : @Vec n m g) :
    Vec fun v => f v ::ᵥ g v := fun i => Fin.cases (by simp [*]) (fun i => by 

Proof state:
n m : ℕ
f : Vector ℕ n → ℕ
g : Vector ℕ n → Vector ℕ m
hf : Primrec' f
hg : Vec g
i✝ : Fin (Nat.succ m)
i : Fin m
⊢ Primrec' fun v => Vector.get ((fun v => f v ::ᵥ g v) v) (Fin.succ i)

Next tactic:
simp [hg i]
theorem comp' {n m f g} (hf : @Primrec' m f) (hg : @Vec n m g) : Primrec' fun v => f (g v) :=
  (hf.comp _ hg).of_eq fun v => by 

Proof state:
n m : ℕ
f : Vector ℕ m → ℕ
g : Vector ℕ n → Vector ℕ m
hf : Primrec' f
hg : Vec g
v : Vector ℕ n
⊢ f (ofFn fun i => Vector.get (g v) i) = f (g v)

Next tactic:
simp
theorem comp₂ (f : ℕ → ℕ → ℕ) (hf : @Primrec' 2 fun v => f v.head v.tail.head) {n g h}
    (hg : @Primrec' n g) (hh : @Primrec' n h) : Primrec' fun v => f (g v) (h v) := by
  

Proof state:
f : ℕ → ℕ → ℕ
hf : Primrec' fun v => f (Vector.head v) (Vector.head (Vector.tail v))
n : ℕ
g h : Vector ℕ n → ℕ
hg : Primrec' g
hh : Primrec' h
⊢ Primrec' fun v => f (g v) (h v)

Next tactic:
simpa using hf.comp' (hg.cons <| hh.cons Primrec'.nil)
theorem prec' {n f g h} (hf : @Primrec' n f) (hg : @Primrec' n g) (hh : @Primrec' (n + 2) h) :
    @Primrec' n fun v => (f v).rec (g v) fun y IH : ℕ => h (y ::ᵥ IH ::ᵥ v) := by
  

Proof state:
n : ℕ
f g : Vector ℕ n → ℕ
h : Vector ℕ (n + 2) → ℕ
hf : Primrec' f
hg : Primrec' g
hh : Primrec' h
⊢ Primrec' fun v => Nat.rec (g v) (fun y IH => h (y ::ᵥ IH ::ᵥ v)) (f v)

Next tactic:
simpa using comp' (prec hg hh) (hf.cons idv)
theorem pred : @Primrec' 1 fun v => v.head.pred :=
  (prec' head (const 0) head).of_eq fun v => by 

Proof state:
v : Vector ℕ (Nat.succ 0)
⊢ Nat.rec 0 (fun y IH => Vector.head (y ::ᵥ IH ::ᵥ v)) (Vector.head v) = Nat.pred (Vector.head v)

Next tactic:
simp
theorem pred : @Primrec' 1 fun v => v.head.pred :=
  (prec' head (const 0) head).of_eq fun v => by simp; 

Proof state:
v : Vector ℕ (Nat.succ 0)
⊢ Nat.rec 0 (fun y IH => y) (Vector.head v) = Nat.pred (Vector.head v)

Next tactic:
cases v.head
theorem pred : @Primrec' 1 fun v => v.head.pred :=
  (prec' head (const 0) head).of_eq fun v => by simp; cases v.head <;> 

Proof state:
case zero
v : Vector ℕ (Nat.succ 0)
⊢ Nat.rec 0 (fun y IH => y) Nat.zero = Nat.pred Nat.zero

Next tactic:
rfl
theorem pred : @Primrec' 1 fun v => v.head.pred :=
  (prec' head (const 0) head).of_eq fun v => by simp; cases v.head <;> 

Proof state:
case succ
v : Vector ℕ (Nat.succ 0)
n✝ : ℕ
⊢ Nat.rec 0 (fun y IH => y) (Nat.succ n✝) = Nat.pred (Nat.succ n✝)

Next tactic:
rfl
theorem add : @Primrec' 2 fun v => v.head + v.tail.head :=
  (prec head (succ.comp₁ _ (tail head))).of_eq fun v => by
    

Proof state:
v : Vector ℕ (Nat.succ 0 + 1)
⊢ Nat.rec (Vector.head (Vector.tail v)) (fun y IH => Nat.succ (Vector.head (Vector.tail (y ::ᵥ IH ::ᵥ Vector.tail v))))
      (Vector.head v) =
    Vector.head v + Vector.head (Vector.tail v)

Next tactic:
simp
theorem add : @Primrec' 2 fun v => v.head + v.tail.head :=
  (prec head (succ.comp₁ _ (tail head))).of_eq fun v => by
    simp; 

Proof state:
v : Vector ℕ (Nat.succ 0 + 1)
⊢ Nat.rec (Vector.head (Vector.tail v)) (fun y IH => Nat.succ IH) (Vector.head v) =
    Vector.head v + Vector.head (Vector.tail v)

Next tactic:
induction v.head
theorem add : @Primrec' 2 fun v => v.head + v.tail.head :=
  (prec head (succ.comp₁ _ (tail head))).of_eq fun v => by
    simp; induction v.head <;> 

Proof state:
case zero
v : Vector ℕ (Nat.succ 0 + 1)
⊢ Nat.rec (Vector.head (Vector.tail v)) (fun y IH => Nat.succ IH) Nat.zero = Nat.zero + Vector.head (Vector.tail v)

Next tactic:
simp [*, Nat.succ_add]
theorem add : @Primrec' 2 fun v => v.head + v.tail.head :=
  (prec head (succ.comp₁ _ (tail head))).of_eq fun v => by
    simp; induction v.head <;> 

Proof state:
case succ
v : Vector ℕ (Nat.succ 0 + 1)
n✝ : ℕ
n_ih✝ : Nat.rec (Vector.head (Vector.tail v)) (fun y IH => Nat.succ IH) n✝ = n✝ + Vector.head (Vector.tail v)
⊢ Nat.rec (Vector.head (Vector.tail v)) (fun y IH => Nat.succ IH) (Nat.succ n✝) =
    Nat.succ n✝ + Vector.head (Vector.tail v)

Next tactic:
simp [*, Nat.succ_add]
theorem sub : @Primrec' 2 fun v => v.head - v.tail.head := by
  

Proof state:
⊢ Primrec' fun v => Vector.head v - Vector.head (Vector.tail v)

Next tactic:
suffices
theorem sub : @Primrec' 2 fun v => v.head - v.tail.head := by
  suffices; 

Proof state:
this : ?m.395888
⊢ Primrec' fun v => Vector.head v - Vector.head (Vector.tail v)
case this ⊢ ?m.395888

Next tactic:
simpa using comp₂ (fun a b => b - a) this (tail head) head
theorem sub : @Primrec' 2 fun v => v.head - v.tail.head := by
  suffices; simpa using comp₂ (fun a b => b - a) this (tail head) head
  

Proof state:
case this
⊢ Primrec' fun v => (fun a b => b - a) (Vector.head v) (Vector.head (Vector.tail v))

Next tactic:
refine' (prec head (pred.comp₁ _ (tail head))).of_eq fun v => _
theorem sub : @Primrec' 2 fun v => v.head - v.tail.head := by
  suffices; simpa using comp₂ (fun a b => b - a) this (tail head) head
  refine' (prec head (pred.comp₁ _ (tail head))).of_eq fun v => _
  

Proof state:
case this
v : Vector ℕ (Nat.succ 0 + 1)
⊢ Nat.rec (Vector.head (Vector.tail v)) (fun y IH => Nat.pred (Vector.head (Vector.tail (y ::ᵥ IH ::ᵥ Vector.tail v))))
      (Vector.head v) =
    (fun a b => b - a) (Vector.head v) (Vector.head (Vector.tail v))

Next tactic:
simp
theorem sub : @Primrec' 2 fun v => v.head - v.tail.head := by
  suffices; simpa using comp₂ (fun a b => b - a) this (tail head) head
  refine' (prec head (pred.comp₁ _ (tail head))).of_eq fun v => _
  simp; 

Proof state:
case this
v : Vector ℕ (Nat.succ 0 + 1)
⊢ Nat.rec (Vector.head (Vector.tail v)) (fun y IH => Nat.pred IH) (Vector.head v) =
    Vector.head (Vector.tail v) - Vector.head v

Next tactic:
induction v.head
theorem sub : @Primrec' 2 fun v => v.head - v.tail.head := by
  suffices; simpa using comp₂ (fun a b => b - a) this (tail head) head
  refine' (prec head (pred.comp₁ _ (tail head))).of_eq fun v => _
  simp; induction v.head <;> 

Proof state:
case this.zero
v : Vector ℕ (Nat.succ 0 + 1)
⊢ Nat.rec (Vector.head (Vector.tail v)) (fun y IH => Nat.pred IH) Nat.zero = Vector.head (Vector.tail v) - Nat.zero

Next tactic:
simp [*, Nat.sub_succ]
theorem sub : @Primrec' 2 fun v => v.head - v.tail.head := by
  suffices; simpa using comp₂ (fun a b => b - a) this (tail head) head
  refine' (prec head (pred.comp₁ _ (tail head))).of_eq fun v => _
  simp; induction v.head <;> 

Proof state:
case this.succ
v : Vector ℕ (Nat.succ 0 + 1)
n✝ : ℕ
n_ih✝ : Nat.rec (Vector.head (Vector.tail v)) (fun y IH => Nat.pred IH) n✝ = Vector.head (Vector.tail v) - n✝
⊢ Nat.rec (Vector.head (Vector.tail v)) (fun y IH => Nat.pred IH) (Nat.succ n✝) =
    Vector.head (Vector.tail v) - Nat.succ n✝

Next tactic:
simp [*, Nat.sub_succ]
theorem mul : @Primrec' 2 fun v => v.head * v.tail.head :=
  (prec (const 0) (tail (add.comp₂ _ (tail head) head))).of_eq fun v => by
    

Proof state:
v : Vector ℕ (Nat.succ 0 + 1)
⊢ Nat.rec 0
      (fun y IH =>
        Vector.head (Vector.tail (Vector.tail (y ::ᵥ IH ::ᵥ Vector.tail v))) +
          Vector.head (Vector.tail (y ::ᵥ IH ::ᵥ Vector.tail v)))
      (Vector.head v) =
    Vector.head v * Vector.head (Vector.tail v)

Next tactic:
simp
theorem mul : @Primrec' 2 fun v => v.head * v.tail.head :=
  (prec (const 0) (tail (add.comp₂ _ (tail head) head))).of_eq fun v => by
    simp; 

Proof state:
v : Vector ℕ (Nat.succ 0 + 1)
⊢ Nat.rec 0 (fun y IH => Vector.head (Vector.tail v) + IH) (Vector.head v) = Vector.head v * Vector.head (Vector.tail v)

Next tactic:
induction v.head
theorem mul : @Primrec' 2 fun v => v.head * v.tail.head :=
  (prec (const 0) (tail (add.comp₂ _ (tail head) head))).of_eq fun v => by
    simp; induction v.head <;> 

Proof state:
case zero
v : Vector ℕ (Nat.succ 0 + 1)
⊢ Nat.rec 0 (fun y IH => Vector.head (Vector.tail v) + IH) Nat.zero = Nat.zero * Vector.head (Vector.tail v)

Next tactic:
simp [*, Nat.succ_mul]
theorem mul : @Primrec' 2 fun v => v.head * v.tail.head :=
  (prec (const 0) (tail (add.comp₂ _ (tail head) head))).of_eq fun v => by
    simp; induction v.head <;> 

Proof state:
case succ
v : Vector ℕ (Nat.succ 0 + 1)
n✝ : ℕ
n_ih✝ : Nat.rec 0 (fun y IH => Vector.head (Vector.tail v) + IH) n✝ = n✝ * Vector.head (Vector.tail v)
⊢ Nat.rec 0 (fun y IH => Vector.head (Vector.tail v) + IH) (Nat.succ n✝) = Nat.succ n✝ * Vector.head (Vector.tail v)

Next tactic:
simp [*, Nat.succ_mul]
theorem mul : @Primrec' 2 fun v => v.head * v.tail.head :=
  (prec (const 0) (tail (add.comp₂ _ (tail head) head))).of_eq fun v => by
    simp; induction v.head <;> simp [*, Nat.succ_mul]; 

Proof state:
case succ
v : Vector ℕ (Nat.succ 0 + 1)
n✝ : ℕ
n_ih✝ : Nat.rec 0 (fun y IH => Vector.head (Vector.tail v) + IH) n✝ = n✝ * Vector.head (Vector.tail v)
⊢ Vector.head (Vector.tail v) + n✝ * Vector.head (Vector.tail v) =
    n✝ * Vector.head (Vector.tail v) + Vector.head (Vector.tail v)

Next tactic:
rw [add_comm]
theorem if_lt {n a b f g} (ha : @Primrec' n a) (hb : @Primrec' n b) (hf : @Primrec' n f)
    (hg : @Primrec' n g) : @Primrec' n fun v => if a v < b v then f v else g v :=
  (prec' (sub.comp₂ _ hb ha) hg (tail <| tail hf)).of_eq fun v => by
    

Proof state:
n : ℕ
a b f g : Vector ℕ n → ℕ
ha : Primrec' a
hb : Primrec' b
hf : Primrec' f
hg : Primrec' g
v : Vector ℕ n
⊢ Nat.rec (g v) (fun y IH => f (Vector.tail (Vector.tail (y ::ᵥ IH ::ᵥ v)))) (b v - a v) =
    if a v < b v then f v else g v

Next tactic:
cases e : b v - a v
theorem if_lt {n a b f g} (ha : @Primrec' n a) (hb : @Primrec' n b) (hf : @Primrec' n f)
    (hg : @Primrec' n g) : @Primrec' n fun v => if a v < b v then f v else g v :=
  (prec' (sub.comp₂ _ hb ha) hg (tail <| tail hf)).of_eq fun v => by
    cases e : b v - a v
    · 

Proof state:
case zero
n : ℕ
a b f g : Vector ℕ n → ℕ
ha : Primrec' a
hb : Primrec' b
hf : Primrec' f
hg : Primrec' g
v : Vector ℕ n
e : b v - a v = Nat.zero
⊢ Nat.rec (g v) (fun y IH => f (Vector.tail (Vector.tail (y ::ᵥ IH ::ᵥ v)))) Nat.zero = if a v < b v then f v else g v

Next tactic:
simp [not_lt.2 (tsub_eq_zero_iff_le.mp e)]
theorem if_lt {n a b f g} (ha : @Primrec' n a) (hb : @Primrec' n b) (hf : @Primrec' n f)
    (hg : @Primrec' n g) : @Primrec' n fun v => if a v < b v then f v else g v :=
  (prec' (sub.comp₂ _ hb ha) hg (tail <| tail hf)).of_eq fun v => by
    cases e : b v - a v
    · simp [not_lt.2 (tsub_eq_zero_iff_le.mp e)]
    · 

Proof state:
case succ
n : ℕ
a b f g : Vector ℕ n → ℕ
ha : Primrec' a
hb : Primrec' b
hf : Primrec' f
hg : Primrec' g
v : Vector ℕ n
n✝ : ℕ
e : b v - a v = Nat.succ n✝
⊢ Nat.rec (g v) (fun y IH => f (Vector.tail (Vector.tail (y ::ᵥ IH ::ᵥ v)))) (Nat.succ n✝) =
    if a v < b v then f v else g v

Next tactic:
simp [Nat.lt_of_sub_eq_succ e]
protected theorem encode : ∀ {n}, @Primrec' n encode
  | 0 => (const 0).of_eq fun v => by 

Proof state:
v : Vector ℕ 0
⊢ 0 = encode v

Next tactic:
rw [v.eq_nil]
protected theorem encode : ∀ {n}, @Primrec' n encode
  | 0 => (const 0).of_eq fun v => by rw [v.eq_nil]; 

Proof state:
v : Vector ℕ 0
⊢ 0 = encode nil

Next tactic:
rfl
theorem sqrt : @Primrec' 1 fun v => v.head.sqrt := by
  

Proof state:
⊢ Primrec' fun v => Nat.sqrt (Vector.head v)

Next tactic:
suffices H : ∀ n : ℕ, n.sqrt = n.rec 0 fun x y => if x.succ < y.succ * y.succ then y else y.succ
theorem sqrt : @Primrec' 1 fun v => v.head.sqrt := by
  suffices H : ∀ n : ℕ, n.sqrt = n.rec 0 fun x y => if x.succ < y.succ * y.succ then y else y.succ
  · 

Proof state:
H : ∀ (n : ℕ), Nat.sqrt n = Nat.rec 0 (fun x y => if Nat.succ x < Nat.succ y * Nat.succ y then y else Nat.succ y) n
⊢ Primrec' fun v => Nat.sqrt (Vector.head v)

Next tactic:
simp [H]
theorem sqrt : @Primrec' 1 fun v => v.head.sqrt := by
  suffices H : ∀ n : ℕ, n.sqrt = n.rec 0 fun x y => if x.succ < y.succ * y.succ then y else y.succ
  · simp [H]
    

Proof state:
H : ∀ (n : ℕ), Nat.sqrt n = Nat.rec 0 (fun x y => if Nat.succ x < Nat.succ y * Nat.succ y then y else Nat.succ y) n
⊢ Primrec' fun v =>
    Nat.rec 0 (fun x y => if Nat.succ x < Nat.succ y * Nat.succ y then y else Nat.succ y) (Vector.head v)

Next tactic:
have :=
      @prec' 1 _ _
        (fun v => by
          have x := v.head; have y := v.tail.head;
            exact if x.succ < y.succ * y.succ then y else y.succ)
        head (const 0) ?_
theorem sqrt : @Primrec' 1 fun v => v.head.sqrt := by
  suffices H : ∀ n : ℕ, n.sqrt = n.rec 0 fun x y => if x.succ < y.succ * y.succ then y else y.succ
  · simp [H]
    have :=
      @prec' 1 _ _
        (fun v => by
          

Proof state:
H : ∀ (n : ℕ), Nat.sqrt n = Nat.rec 0 (fun x y => if Nat.succ x < Nat.succ y * Nat.succ y then y else Nat.succ y) n
v : Vector ℕ (1 + 2)
⊢ ℕ

Next tactic:
have x := v.head
theorem sqrt : @Primrec' 1 fun v => v.head.sqrt := by
  suffices H : ∀ n : ℕ, n.sqrt = n.rec 0 fun x y => if x.succ < y.succ * y.succ then y else y.succ
  · simp [H]
    have :=
      @prec' 1 _ _
        (fun v => by
          have x := v.head; 

Proof state:
H : ∀ (n : ℕ), Nat.sqrt n = Nat.rec 0 (fun x y => if Nat.succ x < Nat.succ y * Nat.succ y then y else Nat.succ y) n
v : Vector ℕ (1 + 2)
x : ℕ
⊢ ℕ

Next tactic:
have y := v.tail.head
theorem sqrt : @Primrec' 1 fun v => v.head.sqrt := by
  suffices H : ∀ n : ℕ, n.sqrt = n.rec 0 fun x y => if x.succ < y.succ * y.succ then y else y.succ
  · simp [H]
    have :=
      @prec' 1 _ _
        (fun v => by
          have x := v.head; have y := v.tail.head;
            

Proof state:
H : ∀ (n : ℕ), Nat.sqrt n = Nat.rec 0 (fun x y => if Nat.succ x < Nat.succ y * Nat.succ y then y else Nat.succ y) n
v : Vector ℕ (1 + 2)
x y : ℕ
⊢ ℕ

Next tactic:
exact if x.succ < y.succ * y.succ then y else y.succ
theorem sqrt : @Primrec' 1 fun v => v.head.sqrt := by
  suffices H : ∀ n : ℕ, n.sqrt = n.rec 0 fun x y => if x.succ < y.succ * y.succ then y else y.succ
  · simp [H]
    have :=
      @prec' 1 _ _
        (fun v => by
          have x := v.head; have y := v.tail.head;
            exact if x.succ < y.succ * y.succ then y else y.succ)
        head (const 0) ?_
    · 

Proof state:
case refine_2
H : ∀ (n : ℕ), Nat.sqrt n = Nat.rec 0 (fun x y => if Nat.succ x < Nat.succ y * Nat.succ y then y else Nat.succ y) n
this :
  Primrec' fun v =>
    Nat.rec 0
      (fun y IH =>
        (fun v =>
            let_fun x := Vector.head v;
            let_fun y := Vector.head (Vector.tail v);
            if Nat.succ x < Nat.succ y * Nat.succ y then y else Nat.succ y)
          (y ::ᵥ IH ::ᵥ v))
      (Vector.head v)
⊢ Primrec' fun v =>
    Nat.rec 0 (fun x y => if Nat.succ x < Nat.succ y * Nat.succ y then y else Nat.succ y) (Vector.head v)

Next tactic:
exact this