(** [partition] *)

    Fixpoint partition (l:list A) : list A * list A :=
      match l with
      | [] => ([], [])
      | x :: tl => let (g,d) := partition tl in
                   if f x then (x::g,d) else (g,x::d)
      end.

(* Specifications: *)
Theorem partition_cons1 a l l1 l2: partition l = (l1, l2) -> f a = true -> partition (a::l) = (a::l1, l2).
Theorem partition_cons2 a l l1 l2: partition l = (l1, l2) -> f a=false -> partition (a::l) = (l1, a::l2).
Theorem partition_length l l1 l2: partition l = (l1, l2) -> length l = length l1 + length l2.
Theorem partition_inv_nil (l : list A): partition l = ([], []) <-> l = [].
Theorem elements_in_partition l l1 l2: partition l = (l1, l2) -> forall x:A, In x l <-> In x l1 \/ In x l2.
Lemma filter_map_swap A B f g l : filter f (@map A B g l) = @map A B g (filter (fun a => f (g a)) l).
Lemma filter_true l : filter (fun _ : A => true) l = l.
Lemma filter_false l : filter (fun _ : A => false) l = nil.
Lemma filter_ext_in : forall (f g : A -> bool) (l : list A), (forall a, In a l -> f a = g a) -> filter f l = filter g l.
Lemma ext_in_filter : forall (f g : A -> bool) (l : list A), filter f l = filter g l -> (forall a, In a l -> f a = g a).
Lemma filter_ext_in_iff : forall (f g : A -> bool) (l : list A), filter f l = filter g l <-> (forall a, In a l -> f a = g a).
Lemma filter_map : forall (f g : A -> bool) (l : list A), filter f l = filter g l <-> map f l = map g l.
Lemma filter_ext : forall (f g : A -> bool), (forall a, f a = g a) -> forall l, filter f l = filter g l.
Lemma partition_as_filter f (l : list A) : partition f l = (filter f l, filter (fun x => negb (f x)) l).