Fixpoint dedup (xs : list A) : list A :=
    match xs with
    | [] => []
    | x :: xs => let tail := dedup xs in
                 if in_dec A_eq_dec x xs then
                   tail
                 else
                   x :: tail
    end.

(* Specifications: *)
Lemma dedup_eliminates_duplicates : forall a l l', dedup (a :: l ++ a :: l') = dedup (l ++ a :: l').
Lemma dedup_In : forall (x : A) xs, In x xs -> In x (dedup xs).
Lemma filter_dedup (pred : A -> bool) : forall xs (p : A) ys, pred p = false -> filter pred (dedup (xs ++ ys)) = filter pred (dedup (xs ++ p :: ys)).
Lemma dedup_app : forall (xs ys : list A), (forall x y, In x xs -> In y ys -> x <> y) -> dedup (xs ++ ys) = dedup xs ++ dedup ys.
Lemma in_dedup_was_in : forall xs (x : A), In x (dedup xs) -> In x xs.
Lemma NoDup_dedup : forall (xs : list A), NoDup (dedup xs).
Lemma remove_dedup_comm : forall (x : A) xs, remove A_eq_dec x (dedup xs) = dedup (remove A_eq_dec x xs).
Lemma dedup_partition : forall xs (p : A) ys xs' ys', dedup (xs ++ p :: ys) = xs' ++ p :: ys' -> remove A_eq_dec p (dedup (xs ++ ys)) = xs' ++ ys'.
Lemma dedup_NoDup_id : forall (xs : list A), NoDup xs -> dedup xs = xs.
Lemma dedup_not_in_cons : forall x xs, (~ In x xs) -> x :: dedup xs = dedup (x :: xs).