Next Obligation.
exists (fun _ => empty_map); auto; repeat intro.
split; auto; intros [|]; auto; discriminate.
Defined.
Next Obligation.
constructor.
- intros.
extensionality k.
specialize (H k); specialize (H0 k).
destruct (z k).
+ destruct (H b) as [X _]; specialize (X eq_refl).
rewrite <- H0 in X; auto.
+ destruct (z' k); auto.
destruct (H0 b) as [X _]; specialize (X eq_refl).
rewrite <- H in X; auto.
- intros.
rewrite map_join_spec in *.
destruct H, H0; subst.
rewrite map_add_assoc.
eexists; rewrite !map_join_spec; repeat split.
+ eapply compatible_incl; eauto.
rewrite map_add_comm by auto; apply map_incl_add.
+ apply compatible_add_assoc; auto.
- intros ???; rewrite !map_join_spec; intros []; subst.
split; [symmetry | apply map_add_comm]; auto.
- intros.
extensionality k; specialize (H k); specialize (H0 k).
destruct (a k), (b k); auto.
+ apply H0; auto.
+ destruct (H b0) as [_ H']; lapply H'; auto.
+ destruct (H0 b0) as [_ H']; lapply H'; auto.
Defined.
Next Obligation.
auto.
Defined.
Instance fmap_order : PCM_order map_incl.

(* Specifications: *)
Lemma map_upd_list_app : forall l1 l2 m, map_upd_list m (l1 ++ l2) = map_upd_list (map_upd_list m l1) l2.
Lemma map_upd_list_out : forall l m k, m k = None -> ~In k (map fst l) -> map_upd_list m l k = None.
Lemma compatible_k : forall m1 m2 (Hcompat : compatible m1 m2) k v, m2 k = Some v -> map_add m1 m2 k = Some v.
Lemma map_join_incl_compat : forall m1 m2 m' m'' (Hincl : map_incl m1 m2) (Hjoin : join m2 m' m''),
exists m, join m1 m' m /\ map_incl m m''.
Lemma map_add_empty : forall m, map_add m empty_map = m.
Lemma map_upd_incl : forall m1 m2 k v, map_incl m1 m2 ->
m2 k = Some v -> map_incl (map_upd m1 k v) m2.
Lemma map_add_single : forall m k v, map_add (singleton k v) m = map_upd m k v.
Lemma incl_compatible : forall m1 m2, map_incl m1 m2 -> compatible m1 m2.
Lemma map_add_redundant : forall m1 m2, map_incl m1 m2 -> map_add m1 m2 = m2.
Lemma empty_map_incl : forall m, map_incl empty_map m.
Lemma map_upd2_incl : forall m1 m2 k v, map_incl m1 m2 -> map_incl (map_upd m1 k v) (map_upd m2 k v).
Lemma compatible_upd : forall m1 m2 k v, compatible m1 m2 -> m2 k = None ->
compatible (map_upd m1 k v) m2.
Lemma map_add_upd : forall m1 m2 k v, map_upd (map_add m1 m2) k v = map_add (map_upd m1 k v) m2.
Notation maps_add l := (fold_right map_add empty_map l).
Lemma in_maps_add : forall l (k : A) (v : B), maps_add l k = Some v -> exists m, In m l /\ m k = Some v.
Definition all_compatible (l : list (A -> option B)) := forall m1 m2, In m1 l -> In m2 l -> compatible m1 m2.
Lemma all_compatible_cons : forall (m : A -> option B) l, all_compatible (m :: l) -> compatible m (maps_add l) /\ all_compatible l.
Lemma maps_add_in : forall l m (k : A) (v : B) (Hcompat : all_compatible l),
In m l -> m k = Some v -> maps_add l k = Some v.
Lemma fold_right_maps_add : forall l (e : A -> option B), fold_right map_add e l = map_add (maps_add l) e.
Section Maps_Disjoint.