(** * Additional notions over maps *)
Definition Disjoint (m m' : t elt) :=
forall k, ~(In k m /\ In k m').
Definition Partition (m m1 m2 : t elt) :=
Disjoint m1 m2 /\
(forall k e, MapsTo k e m <-> MapsTo k e m1 \/ MapsTo k e m2).
(** * Emulation of some functions lacking in the interface *)
Definition filter (f : key -> elt -> bool)(m : t elt) :=
fold (fun k e m => if f k e then add k e m else m) m (empty _).
Definition for_all (f : key -> elt -> bool)(m : t elt) :=
fold (fun k e b => if f k e then b else false) m true.
Definition exists_ (f : key -> elt -> bool)(m : t elt) :=
fold (fun k e b => if f k e then true else b) m false.
Definition partition (f : key -> elt -> bool)(m : t elt) :=
(filter f m, filter (fun k e => negb (f k e)) m).
(** [update] adds to [m1] all the bindings of [m2]. It can be seen as an [union] operator which gives priority to its 2nd argument in case of binding conflit. *)
Definition update (m1 m2 : t elt) := fold (@add _) m2 m1.
(** [restrict] keeps from [m1] only the bindings whose key is in [m2]. It can be seen as an [inter] operator, with priority to its 1st argument in case of binding conflit. *)
Definition restrict (m1 m2 : t elt) := filter (fun k _ => mem k m2) m1.
(** [diff] erases from [m1] all bindings whose key is in [m2]. *)
Definition diff (m1 m2 : t elt) := filter (fun k _ => negb (mem k m2)) m1.
Section Specs.
Variable f : key -> elt -> bool.
Hypothesis Hf : Proper (E.eq==>eq==>eq) f.

(* Specifications: *)
Lemma filter_iff : forall m k e,
MapsTo k e (filter f m) <-> MapsTo k e m /\ f k e = true.
Lemma for_all_iff : forall m,
for_all f m = true <-> (forall k e, MapsTo k e m -> f k e = true).
Lemma exists_iff : forall m,
exists_ f m = true <->
(exists p, MapsTo (fst p) (snd p) m /\ f (fst p) (snd p) = true).