(** [flat_map] *)

    Fixpoint flat_map (l:list A) : list B :=
      match l with
        | [] => []
        | x :: l => f x ++ flat_map l
      end.

(* Specifications: *)
Lemma flat_map_concat_map l : flat_map l = concat (map f l).
Lemma flat_map_app l1 l2 : flat_map (l1 ++ l2) = flat_map l1 ++ flat_map l2.
Lemma in_flat_map l y : In y (flat_map l) <-> exists x, In x l /\ In y (f x).
Lemma concat_map : forall A B (f : A -> B) l, map f (concat l) = concat (map (map f) l).
Lemma remove_concat A (eq_dec : forall x y : A, {x = y}+{x <> y}) : forall l x, remove eq_dec x (concat l) = flat_map (remove eq_dec x) l.
Lemma map_id : forall (A :Type) (l : list A), map (fun x => x) l = l.
Lemma map_map : forall (A B C:Type)(f:A->B)(g:B->C) l, map g (map f l) = map (fun x => g (f x)) l.
Lemma map_ext_in : forall (A B : Type)(f g:A->B) l, (forall a, In a l -> f a = g a) -> map f l = map g l.
Lemma ext_in_map : forall (A B : Type)(f g:A->B) l, map f l = map g l -> forall a, In a l -> f a = g a.
Lemma map_ext_in_iff : forall (A B : Type)(f g:A->B) l, map f l = map g l <-> forall a, In a l -> f a = g a.
Lemma map_ext : forall (A B : Type)(f g:A->B), (forall a, f a = g a) -> forall l, map f l = map g l.