Section Maps_Disjoint.
(* This map instance requires that maps be disjoint, providing e.g. uniqueness of timestamps for histories. *)
Definition disjoint m1 m2 := forall k v1, m1 k = Some v1 -> m2 k = None.
Global Instance disjoint_comm : Symmetric disjoint.
Instance map_disj_join : Join (A -> option B) :=
fun a b c => forall k, match a k, b k with Some v, None | None, Some v => c k = Some v | None, None => c k = None | _, _ => False end.
Global Program Instance map_disj_PCM : Ghost := { valid a := True; Join_G := map_disj_join }.
Next Obligation.
exists (fun _ => empty_map); auto; repeat intro.
simpl.
destruct (t k); auto.
Defined.
Next Obligation.
constructor.
- intros.
extensionality k.
specialize (H k); specialize (H0 k).
destruct (x k), (y k); try congruence; contradiction.
- intros.
rewrite map_disj_join_spec in *.
destruct H, H0; subst.
rewrite map_add_assoc.
eexists; rewrite !map_disj_join_spec; repeat split.
+ eapply disjoint_incl; eauto.
rewrite map_add_comm by (apply disjoint_compatible; auto); apply map_incl_add.
+ apply disjoint_add; auto.
eapply disjoint_incl; eauto.
apply map_incl_add.
- intros ???; rewrite !map_disj_join_spec; intros []; subst.
split; [symmetry | apply map_add_comm, disjoint_compatible]; auto.
- intros.
extensionality k; specialize (H k); specialize (H0 k).
destruct (a k), (b k); auto.
+ destruct (a' k); [contradiction | auto].
+ destruct (a' k); [contradiction | auto].
+ destruct (b' k); [contradiction | auto].
Defined.
Next Obligation.
auto.
Defined.

Lemma disj_join_sub : forall m1 m2, map_incl m1 m2 -> exists m3, join m1 m3 m2.