End Filtering.
Section DisjointUnion.
Variable (K : ordType) (V : Type).
Notation fmap := (finMap K V).
Notation nil := (nil K V).
Definition disj (s1 s2 : fmap) :=
all (predC (fun x => x \in supp s2)) (supp s1).
CoInductive disj_spec (s1 s2 : fmap) : bool -> Type :=
| disj_true of (forall x, x \in supp s1 -> x \notin supp s2) :
disj_spec s1 s2 true
| disj_false x of x \in supp s1 & x \in supp s2 :
disj_spec s1 s2 false.

(* Specifications: *)
Lemma disjP s1 s2 : disj_spec s1 s2 (disj s1 s2).
Lemma disjC s1 s2 : disj s1 s2 = disj s2 s1.
Lemma disj_nil (s : fmap) : disj s nil.
Lemma disj_rem k (s1 s2 : fmap) :
disj s1 s2 -> disj s1 (rem k s2).
Lemma disj_remE k (s1 s2 : fmap) :
k \notin supp s1 -> disj s1 (rem k s2) = disj s1 s2.
Lemma disj_fcat (s s1 s2 : fmap) :
disj s (fcat s1 s2) = disj s s1 && disj s s2.
Lemma fcatC (s1 s2 : fmap) : disj s1 s2 -> fcat s1 s2 = fcat s2 s1.
Lemma fcatA (s1 s2 s3 : fmap) :
disj s2 s3 -> fcat (fcat s1 s2) s3 = fcat s1 (fcat s2 s3).
Lemma fcatAC (s1 s2 s3 : fmap) :
[&& disj s1 s2, disj s2 s3 & disj s1 s3] ->
fcat s1 (fcat s2 s3) = fcat s2 (fcat s1 s3).
Lemma fcatsK (s s1 s2 : fmap) :
disj s1 s && disj s2 s -> fcat s1 s = fcat s2 s -> s1 = s2.
Lemma fcatKs (s s1 s2 : fmap) :
disj s s1 && disj s s2 -> fcat s s1 = fcat s s2 -> s1 = s2.
Lemma disj_kfilt p1 p2 s1 s2 :
disj s1 s2 -> disj (kfilter p1 s1) (kfilter p2 s2).
Lemma in_disj_kfilt p1 p2 s :
{in supp s, forall x, ~~ p1 x || ~~ p2 x} ->
disj (kfilter p1 s) (kfilter p2 s).