End UM.
End UM.
(* a class of union_map types *)
Module UMC.
Section MixinDef.
Variables (K : ordType) (V : Type) (p : pred K).
Structure mixin_of (T : Type) := Mixin {
defined_op : T -> bool;
empty_op : T;
undef_op : T;
upd_op : K -> V -> T -> T;
dom_op : T -> seq K;
dom_eq_op : T -> T -> bool;
free_op : K -> T -> T;
find_op : K -> T -> option V;
union_op : T -> T -> T;
um_filter_op : pred K -> T -> T;
empb_op : T -> bool;
undefb_op : T -> bool;
pts_op : K -> V -> T;
from_op : T -> UM.base V p;
to_op : UM.base V p -> T;
_ : forall b, from_op (to_op b) = b;
_ : forall f, to_op (from_op f) = f;
_ : forall f, defined_op f = UM.valid (from_op f);
_ : undef_op = to_op (UM.Undef V p);
_ : empty_op = to_op (UM.empty V p);
_ : forall k v f, upd_op k v f = to_op (UM.upd k v (from_op f));
_ : forall f, dom_op f = UM.dom (from_op f);
_ : forall f1 f2, dom_eq_op f1 f2 = UM.dom_eq (from_op f1) (from_op f2);
_ : forall k f, free_op k f = to_op (UM.free k (from_op f));
_ : forall k f, find_op k f = UM.find k (from_op f);
_ : forall f1 f2,
union_op f1 f2 = to_op (UM.union (from_op f1) (from_op f2));
_ : forall q f, um_filter_op q f = to_op (UM.um_filter q (from_op f));
_ : forall f, empb_op f = UM.empb (from_op f);
_ : forall f, undefb_op f = UM.undefb (from_op f);
_ : forall k v, pts_op k v = to_op (UM.pts p k v)}.
End MixinDef.
Section ClassDef.
Variables (K : ordType) (V : Type).
(* I used to package K and V into the class. I did that to get cond function over keys to work without supplying the type parameter. I.e., with K and V out, I have to write cond U k, where U : union_map_class K V. But the complication wasn't worth it. One has to frequently reorder arguments to various operations in a "less-ad-hoc" style, to get the types to be inferred properly. While fun, it's just an unnecessary hassle, since cond is not used that much. The condition p can be kept in the structure, however, since no types depend on it. *)
Structure class_of (T : Type) := Class {
p : pred K;
mixin : mixin_of V p T}.
Structure type : Type := Pack {sort : Type; _ : class_of sort}.
Local Coercion sort : type >-> Sortclass.
Variables (T : Type) (cT : type).
Definition class := let: Pack _ c as cT' := cT return class_of cT' in c.
Definition clone c of phant_id class c := @Pack T c.
Definition pack p (m : @mixin_of K V p T) :=
@Pack T (@Class T p m).
(* Definition cond : pred K := @p _ class. *)
Definition cond := [pred x : K | @p _ class x].
Definition from := from_op (mixin class).
Definition to := to_op (mixin class).
Definition defined := defined_op (mixin class).
Definition um_undef := undef_op (mixin class).
Definition empty := empty_op (mixin class).
Definition upd : K -> V -> cT -> cT := upd_op (mixin class).
Definition dom : cT -> seq K := dom_op (mixin class).
Definition dom_eq := dom_eq_op (mixin class).
Definition free : K -> cT -> cT := free_op (mixin class).
Definition find : K -> cT -> option V := find_op (mixin class).
Definition union := union_op (mixin class).
Definition um_filter : pred K -> cT -> cT := um_filter_op (mixin class).
Definition empb := empb_op (mixin class).
Definition undefb := undefb_op (mixin class).
Definition pts : K -> V -> cT := pts_op (mixin class).
End ClassDef.
Arguments um_undef [K V cT].
Arguments empty [K V cT].
Arguments pts [K V cT] _ _.
Prenex Implicits to um_undef empty pts.
Section Lemmas.
Variables (K : ordType) (V : Type) (U : type K V).
Local Coercion sort : type >-> Sortclass.
Implicit Type f : U.

Lemma joinA f1 f2 f3 : f1 \+ (f2 \+ f3) = (f1 \+ f2) \+ f3.