(** Extract the n-th element of a list, as [List.nth_error] does, but the index [n] is of type [Z]. *)
Fixpoint list_nth_z (A: Type) (l: list A) (n: Z) {struct l}: option A :=
match l with
| nil => None
| hd :: tl => if zeq n 0 then Some hd else list_nth_z tl (Z.pred n)
end.

(* Specifications: *)
Lemma list_nth_z_in:
forall (A: Type) (l: list A) n x,
list_nth_z l n = Some x -> In x l.
Lemma list_nth_z_map:
forall (A B: Type) (f: A -> B) (l: list A) n,
list_nth_z (List.map f l) n = option_map f (list_nth_z l n).
Lemma list_nth_z_range:
forall (A: Type) (l: list A) n x,
list_nth_z l n = Some x -> 0 <= n < list_length_z l.
Lemma list_nth_z_in:
forall (A: Type) (l: list A) n x,
list_nth_z l n = Some x -> In x l.
Lemma list_nth_z_map:
forall (A B: Type) (f: A -> B) (l: list A) n,
list_nth_z (List.map f l) n = option_map f (list_nth_z l n).
Lemma list_nth_z_range:
forall (A: Type) (l: list A) n x,
list_nth_z l n = Some x -> 0 <= n < list_length_z l.