Section PRIMITIVE_RECURSION. (* Reference: "https://github.com/princeton-vl/CoqGym/blob/master/coq_projects/goedel/primRec.v" *)
#[local] Open Scope program_scope.
Let arity : Set := nat.
Fixpoint naryFun (n : arity) : Set :=
match n with
| O => nat
| S n' => nat -> naryFun n'
end.
Fixpoint naryRel (n : arity) : Type :=
match n with
| O => Prop
| S n' => nat -> naryRel n'
end.
Fixpoint eval_vec {n : arity} (xs : Vector.t nat n) : naryFun n -> nat :=
match xs with
| VNil => id
| VCons n' x xs' => fun f => eval_vec xs' (f x)
end.
Fixpoint eval_const {n : arity} (m : nat) : naryFun n :=
match n with
| O => m
| S n' => const (eval_const m)
end.
Fixpoint eval_proj {n : arity} (i : Fin.t n) : naryFun n :=
match i with
| FZ => eval_const
| FS i' => const (eval_proj i')
end.

Lemma eval_proj_spec (n : arity) (i : Fin.t n) (xs : Vector.t nat n)
: eval_vec xs (eval_proj i) = xs !! i.