(** Compute the length of a list, with result in [Z]. *)

Fixpoint list_length_z_aux (A: Type) (l: list A) (acc: Z) {struct l}: Z :=
  match l with
  | nil => acc
  | hd :: tl => list_length_z_aux tl (Z.succ acc)
  end.Remark list_length_z_aux_shift:
  forall (A: Type) (l: list A) n m,
  list_length_z_aux l n = list_length_z_aux l m + (n - m).Definition list_length_z (A: Type) (l: list A) : Z :=
  list_length_z_aux l 0.

(* Specifications: *)
Lemma list_length_z_cons: forall (A: Type) (hd: A) (tl: list A), list_length_z (hd :: tl) = list_length_z tl + 1.
Lemma list_length_z_pos: forall (A: Type) (l: list A), list_length_z l >= 0.
Lemma list_length_z_map: forall (A B: Type) (f: A -> B) (l: list A), list_length_z (map f l) = list_length_z l.
Lemma list_length_z_cons: forall (A: Type) (hd: A) (tl: list A), list_length_z (hd :: tl) = list_length_z tl + 1.
Lemma list_length_z_pos: forall (A: Type) (l: list A), list_length_z l >= 0.
Lemma list_length_z_map: forall (A B: Type) (f: A -> B) (l: list A), list_length_z (map f l) = list_length_z l.