Section Maps.
Context {A B : Type} {A_eq : EqDec A}.
Implicit Types (k : A) (v : B) (m : A -> option B).
Definition map_upd m k v k' := if eq_dec k' k then Some v else m k'.
Fixpoint map_upd_list m l :=
match l with
| [] => m
| (k, v) :: rest => map_upd_list (map_upd m k v) rest
end.
Definition map_add m1 m2 k := match m1 k with Some v' => Some v' | None => m2 k end.
Definition empty_map k : option B := None.
Global Instance Inhabitant_map : Inhabitant (A -> option B) := empty_map.
Definition singleton k v k1 := if eq_dec k1 k then Some v else None.
Definition map_incl m1 m2 := forall k v, m1 k = Some v -> m2 k = Some v.
Global Instance map_incl_refl : Reflexive map_incl.
Global Instance map_incl_antisym : Antisymmetric _ _ map_incl.
Global Instance map_incl_trans : Transitive map_incl.
Definition compatible m1 m2 := forall k v1 v2, m1 k = Some v1 -> m2 k = Some v2 -> v1 = v2.
Global Instance compatible_refl : Reflexive compatible.
Global Instance compatible_comm : Symmetric compatible.
Global Instance map_join : Join (A -> option B) :=
fun a b c => forall k v, c k = Some v <-> a k = Some v \/ b k = Some v.
Global Program Instance map_PCM : Ghost := { valid a := True; Join_G := map_join }.
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.
Notation maps_add l := (fold_right map_add empty_map l).
Definition all_compatible (l : list (A -> option B)) := forall m1 m2, In m1 l -> In m2 l -> compatible m1 m2.

Lemma fold_right_maps_add : forall l (e : A -> option B), fold_right map_add e l = map_add (maps_add l) e.