(******************************************)
  (** ** Counting occurrences of an element *)
  (******************************************)

  Fixpoint count_occ (l : list A) (x : A) : nat :=
    match l with
      | [] => 0
      | y :: tl =>
        let n := count_occ tl x in
        if eq_dec y x then S n else n
    end.

(* Specifications: *)
Theorem count_occ_In l x : In x l <-> count_occ l x > 0.
Theorem count_occ_not_In l x : ~ In x l <-> count_occ l x = 0.
Lemma count_occ_nil x : count_occ [] x = 0.
Theorem count_occ_inv_nil l : (forall x:A, count_occ l x = 0) <-> l = [].
Lemma count_occ_cons_eq l x y : x = y -> count_occ (x::l) y = S (count_occ l y).
Lemma count_occ_cons_neq l x y : x <> y -> count_occ (x::l) y = count_occ l y.
Lemma count_occ_app l1 l2 x : count_occ (l1 ++ l2) x = count_occ l1 x + count_occ l2 x.
Lemma count_occ_elt_eq l1 l2 x y : x = y -> count_occ (l1 ++ x :: l2) y = S (count_occ (l1 ++ l2) y).
Lemma count_occ_elt_neq l1 l2 x y : x <> y -> count_occ (l1 ++ x :: l2) y = count_occ (l1 ++ l2) y.
Lemma count_occ_bound x l : count_occ l x <= length l.