End RestrictionOps.
Arguments filterf : simpl never.
Arguments restrictf : simpl never.
Notation "x .[& A ]" := (restrictf x A) : fmap_scope.
Notation "x .[\ A ]" := (x.[& domf x `\` A]) : fmap_scope.
Notation "x .[~ k ]" := (x.[\ [fset k]]) : fmap_scope.
Section Cat.
Variables (K : choiceType) (V : Type).
Implicit Types (f g : {fmap K -> V}).
Definition catf (f g : {fmap K -> V}) :=
[fmap k : (domf f `\` domf g) `|` domf g=>
match fsetULVR (valP k) with
| inl kfDg => f.[fsubsetP (fsubsetDl _ _) _ kfDg]
| inr kg => g.[kg]
end].
Local Notation "f + g" := (catf f g) : fset_scope.

(* Specifications: *)
Lemma domf_cat f g : domf (f + g) = domf f `|` domf g.
Lemma mem_catf f g k : k \in domf (f + g) = (k \in f) || (k \in g).
Lemma catfE f g : f + g = f.[\ domf g] + g.
Lemma getf_catr f g k (kfg : k \in domf (f + g))
(kg : k \in domf g) : (f + g).[kfg] = g.[kg].
Lemma catf_setl f g k (v : V) :
f.[k <- v] + g = if k \in g then f + g else (f + g).[k <- v].
Lemma catf_setr f g k (v : V) : f + g.[k <- v] = (f + g).[k <- v].
Lemma restrictf_cat f g A : (f + g).[& A] = f.[& A] + g.[& A].
Lemma restrictf_cat_domr f g : (f + g).[& domf g] = g.
Lemma remf_cat f g A : (f + g).[\ A] = f.[\ A] + g.[\ A].
Lemma catf_restrictl A f g : f.[& A] + g = (f + g).[& A `|` domf g].
Lemma catf_reml A f g : f.[\ A] + g = (f + g).[\ A `\` domf g].
Lemma catf_rem1l k f g :
f.[~ k] + g = if k \in g then f + g else (f + g).[~ k].
Lemma setf_catr f g k (v : V) : (f + g).[k <- v] = f + g.[k <- v].
Lemma catfC f g : f + g = g + f.[\ domf g].
Lemma disjoint_catfC f g : [disjoint domf f & domf g] -> f + g = g + f.
Lemma disjoint_catfIs h f g :
[disjoint domf f & domf h] -> [disjoint domf g & domf h] ->
f + h = g + h -> f = g.
Lemma disjoint_catfsI h f g :
[disjoint domf f & domf h] -> [disjoint domf g & domf h] ->
h + f = h + g -> f = g.