You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
semantics-2023/theories/lib/maps.v

285 lines
12 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

From stdpp Require Import gmap.
From stdpp Require Export relations orders.
From semantics.lib Require Export sets.
(** * Finite maps *)
(** This file provides lemmas on finite maps (functions with a finite domain) [gmap].
The stdpp library provides a definitions and lemmas on finite maps [gmap], but states lemmas axiomatically in terms of the [FinMap] typeclass, which may make them hard to read for novice users of stdpp.
We therefore instantiate the most important lemmas specifically for [gmap] to make the statements easier to comprehend.
The most important operations are:
- the empty map ∅ contains no elements
- the singleton map {[ i := v ]} defines a singleton map that maps key i to value v
- the insert operation <[ i := v ]> m inserts the association i ↦ v to the map m, overriding any mappings for i in m
- the delete operatin delete i m deletes the mapping for key i from m
- the lookup operation m !! i lookups a key i, and yields the optional value associated with i
- the fmap operation f <$> m maps a function f over all values stored in the map
- the subset relation m1 ⊆ m2 states that all associations of map m1 are also included in map m2
- the dom operation dom m yields a finite set ([gset]) of the domain of the map
stdpp's maps satisfy extensional Leibniz equality -- that is, two maps X and Y are equal (X = Y) iff they represent the same finite function.
*)
Section map.
(* keys need to be countable, i.e., have an injection into positive integers *)
Context {K} {A B : Type} `{Countable K}.
Implicit Types (m : gmap K A).
Definition gmap := gmap.
#[global]
Arguments gmap _ {_ _}.
Lemma lookup_empty i : ( : gmap K A) !! i = None.
Proof. apply lookup_empty. Qed.
Lemma lookup_fmap (f : A B) (m : gmap K A) i : (f <$> m) !! i = f <$> m !! i.
Proof. apply lookup_fmap. Qed.
Lemma map_fmap_mono (f : A B) m1 m2 : m1 m2 f <$> m1 f <$> m2.
Proof. apply map_fmap_mono. Qed.
Lemma fmap_insert (f : A B) m i x : f <$> <[i := x]> m = <[i := f x]> (f <$> m).
Proof. apply fmap_insert. Qed.
Lemma fmap_empty (f : A B) : f <$> ( : gmap K A) = .
Proof. apply fmap_empty. Qed.
Lemma map_fmap_compose {C} (f : A B) (g : B C) m : g f <$> m = g <$> (f <$> m).
Proof. apply map_fmap_compose. Qed.
Lemma map_fmap_ext (f1 f2 : A B) m :
( i x, m !! i = Some x f1 x = f2 x)
f1 <$> m = f2 <$> m.
Proof. apply map_fmap_ext. Qed.
Lemma map_eq_iff m1 m2 : m1 = m2 i, m1 !! i = m2 !! i.
Proof. apply map_eq_iff. Qed.
Lemma map_subseteq_spec m1 m2 :
m1 m2 i x, m1 !! i = Some x m2 !! i = Some x.
Proof. apply map_subseteq_spec. Qed.
Lemma lookup_weaken m1 m2 i x :
m1 !! i = Some x m1 m2 m2 !! i = Some x.
Proof. apply lookup_weaken. Qed.
Lemma lookup_weaken_is_Some m1 m2 i :
is_Some (m1 !! i) m1 m2 is_Some (m2 !! i).
Proof. apply lookup_weaken_is_Some. Qed.
Lemma lookup_weaken_None m1 m2 i :
m2 !! i = None m1 m2 m1 !! i = None.
Proof. apply lookup_weaken_None. Qed.
Lemma lookup_weaken_inv m1 m2 i x y :
m1 !! i = Some x m1 m2 m2 !! i = Some y x = y.
Proof. apply lookup_weaken_inv. Qed.
Lemma lookup_ne m i j : m !! i m !! j i j.
Proof. apply lookup_ne. Qed.
Lemma map_empty m : m = i, m !! i = None.
Proof. apply map_empty. Qed.
Lemma lookup_empty_is_Some i : ¬is_Some (( : gmap K A) !! i).
Proof. apply lookup_empty_is_Some. Qed.
Lemma lookup_empty_Some i (x : A) : ¬( : gmap K A) !! i = Some x.
Proof. apply lookup_empty_Some. Qed.
Lemma map_empty_subseteq m : m.
Proof. apply map_empty_subseteq. Qed.
Lemma lookup_delete m i : delete i m !! i = None.
Proof. apply lookup_delete. Qed.
Lemma lookup_delete_ne m i j : i j delete i m !! j = m !! j.
Proof. apply lookup_delete_ne. Qed.
Lemma lookup_delete_Some m i j y :
delete i m !! j = Some y i j m !! j = Some y.
Proof. apply lookup_delete_Some. Qed.
Lemma lookup_delete_is_Some m i j :
is_Some (delete i m !! j) i j is_Some (m !! j).
Proof. apply lookup_delete_is_Some. Qed.
Lemma lookup_delete_None m i j :
delete i m !! j = None i = j m !! j = None.
Proof. apply lookup_delete_None. Qed.
Lemma delete_empty i : delete i = ( : gmap K A).
Proof. apply delete_empty. Qed.
Lemma delete_commute m i j :
delete i (delete j m) = delete j (delete i m).
Proof. apply delete_commute. Qed.
Lemma delete_insert_ne m i j x :
i j delete i (<[j:=x]>m) = <[j:=x]>(delete i m).
Proof. apply delete_insert_ne. Qed.
Lemma delete_notin m i : m !! i = None delete i m = m.
Proof. apply delete_notin. Qed.
Lemma delete_idemp m i :
delete i (delete i m) = delete i m.
Proof. apply delete_idemp. Qed.
Lemma delete_insert m i x :
m !! i = None delete i (<[i:=x]>m) = m.
Proof. apply delete_insert. Qed.
Lemma delete_insert_delete m i x :
delete i (<[i:=x]>m) = delete i m.
Proof. apply delete_insert_delete. Qed.
Lemma delete_subseteq m i : delete i m m.
Proof. apply delete_subseteq. Qed.
Lemma delete_mono m1 m2 i : m1 m2 delete i m1 delete i m2.
Proof. apply delete_mono. Qed.
(** ** Properties of the [insert] operation *)
Lemma lookup_insert m i x : <[i:=x]>m !! i = Some x.
Proof. apply lookup_insert. Qed.
Lemma lookup_insert_rev m i x y : <[i:=x]>m !! i = Some y x = y.
Proof. apply lookup_insert_rev. Qed.
Lemma lookup_insert_ne m i j x : i j <[i:=x]>m !! j = m !! j.
Proof. apply lookup_insert_ne. Qed.
Lemma insert_insert m i x y : <[i:=x]>(<[i:=y]>m) = <[i:=x]>m.
Proof. apply insert_insert. Qed.
Lemma insert_commute m i j x y :
i j <[i:=x]>(<[j:=y]>m) = <[j:=y]>(<[i:=x]>m).
Proof. apply insert_commute. Qed.
Lemma lookup_insert_Some m i j x y :
<[i:=x]>m !! j = Some y (i = j x = y) (i j m !! j = Some y).
Proof. apply lookup_insert_Some. Qed.
Lemma lookup_insert_is_Some m i j x :
is_Some (<[i:=x]>m !! j) i = j i j is_Some (m !! j).
Proof. apply lookup_insert_is_Some. Qed.
Lemma lookup_insert_None m i j x :
<[i:=x]>m !! j = None m !! j = None i j.
Proof. apply lookup_insert_None. Qed.
Lemma insert_id m i x : m !! i = Some x <[i:=x]>m = m.
Proof. apply insert_id. Qed.
Lemma insert_non_empty m i x : <[i:=x]>m .
Proof. apply insert_non_empty. Qed.
Lemma insert_delete_insert m i x : <[i:=x]>(delete i m) = <[i:=x]> m.
Proof. apply insert_delete_insert. Qed.
Lemma insert_delete m i x :
m !! i = Some x <[i:=x]> (delete i m) = m.
Proof. apply insert_delete. Qed.
Lemma insert_subseteq m i x : m !! i = None m <[i:=x]>m.
Proof. apply insert_subseteq. Qed.
Lemma insert_mono m1 m2 i x : m1 m2 <[i:=x]> m1 <[i:=x]>m2.
Proof. apply insert_mono. Qed.
Lemma insert_subseteq_r m1 m2 i x :
m1 !! i = None m1 m2 m1 <[i:=x]>m2.
Proof. apply insert_subseteq_r. Qed.
Lemma insert_subseteq_l m1 m2 i x :
m2 !! i = Some x m1 m2 <[i:=x]> m1 m2.
Proof. apply insert_subseteq_l. Qed.
Lemma insert_delete_subseteq m1 m2 i x :
m1 !! i = None <[i:=x]> m1 m2 m1 delete i m2.
Proof. apply insert_delete_subseteq. Qed.
Lemma delete_insert_subseteq m1 m2 i x :
m1 !! i = Some x delete i m1 m2 m1 <[i:=x]> m2.
Proof. apply delete_insert_subseteq. Qed.
Lemma map_delete_subseteq (k : K) m :
delete k m m.
Proof.
apply map_subseteq_spec.
intros i x. rewrite lookup_delete_Some. intros [ ]; done.
Qed.
Lemma insert_union_singleton_l (k : K) m x :
<[ k := x ]> m = {[ k := x ]} m.
Proof. apply insert_union_singleton_l. Qed.
Lemma insert_union_singleton_r (k : K) m x :
m !! k = None <[ k := x ]> m = m {[ k := x ]}.
Proof. apply insert_union_singleton_r. Qed.
Lemma lookup_union_Some_l m1 m2 (k : K) x :
m1 !! k = Some x (m1 m2) !! k = Some x.
Proof. apply lookup_union_Some_l. Qed.
Lemma lookup_union_r m1 m2 (k : K) :
m1 !! k = None (m1 m2) !! k = m2 !! k.
Proof. apply lookup_union_r. Qed.
(** map disjoint *)
Definition map_disjoint := @map_disjoint K (gmap K) _ A.
Lemma map_disjoint_spec m1 m2 :
m1 ## m2 i x y, m1 !! i = Some x m2 !! i = Some y False.
Proof. apply map_disjoint_spec. Qed.
Lemma map_disjoint_alt m1 m2 :
m1 ## m2 i, m1 !! i = None m2 !! i = None.
Proof. apply map_disjoint_alt. Qed.
Lemma map_not_disjoint m1 m2 :
¬m1 ## m2 i x1 x2, m1 !! i = Some x1 m2 !! i = Some x2.
Proof. apply map_not_disjoint. Qed.
Global Instance map_disjoint_sym : Symmetric (map_disjoint).
Proof. apply map_disjoint_sym. Qed.
Lemma map_disjoint_empty_l m : ## m.
Proof. apply map_disjoint_empty_l. Qed.
Lemma map_disjoint_empty_r m : m ## .
Proof. apply map_disjoint_empty_r. Qed.
(** Domain *)
Definition dom := @base.dom (gmap K A) (gset K) _.
Lemma elem_of_dom m i : i dom m is_Some (m !! i).
Proof. apply elem_of_dom. Qed.
Lemma elem_of_dom_2 m i x : m !! i = Some x i dom m.
Proof. apply elem_of_dom_2. Qed.
Lemma not_elem_of_dom m i : i dom m m !! i = None.
Proof. apply not_elem_of_dom. Qed.
Lemma subseteq_dom m1 m2 : m1 m2 dom m1 dom m2.
Proof. apply subseteq_dom. Qed.
Lemma dom_empty : dom = .
Proof. apply dom_empty_L. Qed.
Lemma dom_empty_iff m : dom m = m = .
Proof. apply dom_empty_iff_L. Qed.
Lemma dom_insert m i x : dom (<[i:=x]>m) = {[ i ]} dom m.
Proof. apply dom_insert_L. Qed.
Lemma dom_insert_lookup m i x :
is_Some (m !! i) dom (<[i:=x]>m) = dom m.
Proof. apply dom_insert_lookup_L. Qed.
Lemma dom_insert_subseteq m i x : dom m dom (<[i:=x]>m).
Proof. apply dom_insert_subseteq. Qed.
Lemma dom_singleton (i : K) (x : A) : dom ({[i := x]} : gmap K A) = {[ i ]}.
Proof. apply dom_singleton_L. Qed.
Lemma dom_delete m i : dom (delete i m) = dom m {[ i ]}.
Proof. apply dom_delete_L. Qed.
Lemma dom_fmap f m : dom (f <$> m) = dom m.
Proof. apply dom_fmap_L. Qed.
(** difference *)
(* TODO: upstream? *)
Lemma map_difference_mono m1 m2 m3 :
m1 m2
m1 m3 m2 m3.
Proof.
intros ?. apply map_subseteq_spec.
intros i x. rewrite !lookup_difference_Some.
intros [? ?]; split; [ | done]. by eapply map_subseteq_spec.
Qed.
(* Upstream? *)
Lemma map_difference_union' m1 m2 m3 :
m1 ## m2
(m1 m2) m3 = (m1 m3) (m2 m3).
Proof.
intros Hdisj. apply map_eq.
intros i. destruct (((m1 m2) m3) !! i) as [ s | ] eqn:Hlook.
- apply lookup_difference_Some in Hlook as [Hlook1 Hlook2].
apply lookup_union_Some in Hlook1; [ | done].
symmetry. apply lookup_union_Some.
{ eapply map_disjoint_weaken; [ done | | ]; apply map_subseteq_difference_l; done. }
destruct Hlook1 as [ Hlook1 | Hlook1]; [left | right]; apply lookup_difference_Some; done.
- symmetry. apply lookup_difference_None in Hlook as [ Hlook | Hlook].
+ apply lookup_union_None in Hlook as [ ? ?].
apply lookup_union_None; split; apply lookup_difference_None; eauto.
+ apply lookup_union_None; split; apply lookup_difference_None; eauto.
Qed.
(* TODO: upstream the first inclusion as a lemma? *)
Lemma map_disjoint_difference m1 m2 :
m1 ## m2
m1 = m1 m2.
Proof.
intros Hdisj. apply (partial_order_anti_symm (R := ())).
- apply map_subseteq_spec.
intros i x Hlook. apply lookup_difference_Some. split; [done | ].
by eapply map_disjoint_Some_l.
- by apply map_subseteq_difference_l.
Qed.
End map.
Infix "##ₘ" := map_disjoint (at level 70) : stdpp_scope.
Global Hint Extern 0 (_ ## _) => symmetry; eassumption : core.