fin_maps.v 17.5 KB
 Robbert Krebbers committed Aug 29, 2012 1 2 3 4 5 6 ``````(* Copyright (c) 2012, Robbert Krebbers. *) (* This file is distributed under the terms of the BSD license. *) (** Finite maps associate data to keys. This file defines an interface for finite maps and collects some theory on it. Most importantly, it proves useful induction principles for finite maps and implements the tactic [simplify_map] to simplify goals involving finite maps. *) `````` Robbert Krebbers committed Jun 11, 2012 7 8 ``````Require Export prelude. `````` Robbert Krebbers committed Aug 29, 2012 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ``````(** * Axiomatization of finite maps *) (** We require Leibniz equality to be extensional on finite maps. This of course limits the class of finite map implementations, but since we are mainly interested in finite maps with numbers or paths as indexes, we do not consider this a serious limitation. The main application of finite maps is to implement the memory, where extensionality of Leibniz equality becomes very important for a convenient use in assertions of our axiomatic semantics. *) (** Finiteness is axiomatized by requiring each map to have a finite domain. Since we may have multiple implementations of finite sets, the [dom] function is parametrized by an implementation of finite sets over the map's key type. *) (** Finite map implementations are required to implement the [merge] function which enables us to give a generic implementation of [union_with], [intersection_with], and [difference_with]. *) Class FinMap K M `{∀ A, Empty (M A)} `{Lookup K M} `{FMap M} `````` Robbert Krebbers committed Jun 11, 2012 23 `````` `{PartialAlter K M} `{∀ A, Dom K (M A)} `{Merge M} := { `````` Robbert Krebbers committed Aug 21, 2012 24 25 26 27 28 29 30 31 32 33 34 35 `````` finmap_eq {A} (m1 m2 : M A) : (∀ i, m1 !! i = m2 !! i) → m1 = m2; lookup_empty {A} i : (∅ : M A) !! i = None; lookup_partial_alter {A} f (m : M A) i : partial_alter f i m !! i = f (m !! i); lookup_partial_alter_ne {A} f (m : M A) i j : i ≠ j → partial_alter f i m !! j = m !! j; lookup_fmap {A B} (f : A → B) (m : M A) i : (f <\$> m) !! i = f <\$> m !! i; elem_of_dom C {A} `{Collection K C} (m : M A) i : i ∈ dom C m ↔ is_Some (m !! i); `````` Robbert Krebbers committed Aug 29, 2012 36 `````` merge_spec {A} f `{!PropHolds (f None None = None)} `````` Robbert Krebbers committed Jun 11, 2012 37 38 39 `````` (m1 m2 : M A) i : merge f m1 m2 !! i = f (m1 !! i) (m2 !! i) }. `````` Robbert Krebbers committed Aug 29, 2012 40 41 42 43 44 ``````(** * Derived operations *) (** All of the following functions are defined in a generic way for arbitrary finite map implementations. These generic implementations do not cause a significant enough performance loss to make including them in the finite map axiomatization worthwhile. *) `````` Robbert Krebbers committed Aug 21, 2012 45 46 47 48 49 50 ``````Instance finmap_alter `{PartialAlter K M} : Alter K M := λ A f, partial_alter (fmap f). Instance finmap_insert `{PartialAlter K M} : Insert K M := λ A k x, partial_alter (λ _, Some x) k. Instance finmap_delete `{PartialAlter K M} {A} : Delete K (M A) := partial_alter (λ _, None). `````` Robbert Krebbers committed Aug 29, 2012 51 ``````Instance finmap_singleton `{PartialAlter K M} {A} `````` Robbert Krebbers committed Aug 21, 2012 52 `````` `{Empty (M A)} : Singleton (K * A) (M A) := λ p, <[fst p:=snd p]>∅. `````` Robbert Krebbers committed Jun 11, 2012 53 `````` `````` Robbert Krebbers committed Aug 29, 2012 54 55 ``````Definition list_to_map `{Insert K M} {A} `{Empty (M A)} (l : list (K * A)) : M A := insert_list l ∅. `````` Robbert Krebbers committed Jun 11, 2012 56 `````` `````` Robbert Krebbers committed Aug 21, 2012 57 58 59 60 61 62 ``````Instance finmap_union `{Merge M} : UnionWith M := λ A f, merge (union_with f). Instance finmap_intersection `{Merge M} : IntersectionWith M := λ A f, merge (intersection_with f). Instance finmap_difference `{Merge M} : DifferenceWith M := λ A f, merge (difference_with f). `````` Robbert Krebbers committed Jun 11, 2012 63 `````` `````` Robbert Krebbers committed Aug 29, 2012 64 ``````(** * General theorems *) `````` Robbert Krebbers committed Jun 11, 2012 65 ``````Section finmap. `````` Robbert Krebbers committed Aug 21, 2012 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 ``````Context `{FinMap K M} `{∀ i j : K, Decision (i = j)} {A : Type}. Global Instance finmap_subseteq: SubsetEq (M A) := λ m n, ∀ i x, m !! i = Some x → n !! i = Some x. Global Instance: BoundedPreOrder (M A). Proof. split. firstorder. intros m i x. rewrite lookup_empty. discriminate. Qed. Lemma lookup_subseteq_Some (m1 m2 : M A) i x : m1 ⊆ m2 → m1 !! i = Some x → m2 !! i = Some x. Proof. auto. Qed. Lemma lookup_subseteq_None (m1 m2 : M A) i : m1 ⊆ m2 → m2 !! i = None → m1 !! i = None. Proof. rewrite !eq_None_not_Some. firstorder. Qed. Lemma lookup_ne (m : M A) i j : m !! i ≠ m !! j → i ≠ j. Proof. congruence. Qed. Lemma not_elem_of_dom C `{Collection K C} (m : M A) i : i ∉ dom C m ↔ m !! i = None. Proof. now rewrite (elem_of_dom C), eq_None_not_Some. Qed. Lemma finmap_empty (m : M A) : (∀ i, m !! i = None) → m = ∅. Proof. intros Hm. apply finmap_eq. intros. now rewrite Hm, lookup_empty. Qed. Lemma dom_empty C `{Collection K C} : dom C (∅ : M A) ≡ ∅. Proof. split; intro. * rewrite (elem_of_dom C), lookup_empty. simplify_is_Some. `````` Robbert Krebbers committed Aug 29, 2012 92 `````` * solve_elem_of. `````` Robbert Krebbers committed Aug 21, 2012 93 94 95 96 ``````Qed. Lemma dom_empty_inv C `{Collection K C} (m : M A) : dom C m ≡ ∅ → m = ∅. Proof. intros E. apply finmap_empty. intros. apply (not_elem_of_dom C). `````` Robbert Krebbers committed Aug 29, 2012 97 `````` rewrite E. solve_elem_of. `````` Robbert Krebbers committed Aug 21, 2012 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 ``````Qed. Lemma lookup_empty_not i : ¬is_Some ((∅ : M A) !! i). Proof. rewrite lookup_empty. simplify_is_Some. Qed. Lemma lookup_empty_Some i (x : A) : ¬∅ !! i = Some x. Proof. rewrite lookup_empty. discriminate. Qed. Lemma partial_alter_compose (m : M A) i f g : partial_alter (f ∘ g) i m = partial_alter f i (partial_alter g i m). Proof. intros. apply finmap_eq. intros ii. case (decide (i = ii)). * intros. subst. now rewrite !lookup_partial_alter. * intros. now rewrite !lookup_partial_alter_ne. Qed. Lemma partial_alter_comm (m : M A) i j f g : i ≠ j → partial_alter f i (partial_alter g j m) = partial_alter g j (partial_alter f i m). Proof. intros. apply finmap_eq. intros jj. destruct (decide (jj = j)). * subst. now rewrite lookup_partial_alter_ne, !lookup_partial_alter, lookup_partial_alter_ne. * destruct (decide (jj = i)). + subst. now rewrite lookup_partial_alter, !lookup_partial_alter_ne, lookup_partial_alter by congruence. + now rewrite !lookup_partial_alter_ne by congruence. Qed. Lemma partial_alter_self_alt (m : M A) i x : x = m !! i → partial_alter (λ _, x) i m = m. Proof. intros. apply finmap_eq. intros ii. destruct (decide (i = ii)). * subst. now rewrite lookup_partial_alter. * now rewrite lookup_partial_alter_ne. Qed. Lemma partial_alter_self (m : M A) i : partial_alter (λ _, m !! i) i m = m. Proof. now apply partial_alter_self_alt. Qed. Lemma lookup_insert (m : M A) i x : <[i:=x]>m !! i = Some x. Proof. unfold insert. apply lookup_partial_alter. Qed. Lemma lookup_insert_rev (m : M A) i x y : <[i:= x ]>m !! i = Some y → x = y. Proof. rewrite lookup_insert. congruence. Qed. Lemma lookup_insert_ne (m : M A) i j x : i ≠ j → <[i:=x]>m !! j = m !! j. Proof. unfold insert. apply lookup_partial_alter_ne. Qed. Lemma insert_comm (m : M A) i j x y : i ≠ j → <[i:=x]>(<[j:=y]>m) = <[j:=y]>(<[i:=x]>m). Proof. apply partial_alter_comm. Qed. Lemma lookup_insert_Some (m : M A) i j x y : <[i:=x]>m !! j = Some y ↔ (i = j ∧ x = y) ∨ (i ≠ j ∧ m !! j = Some y). Proof. split. * destruct (decide (i = j)); subst; rewrite ?lookup_insert, ?lookup_insert_ne; intuition congruence. * intros [[??]|[??]]. + subst. apply lookup_insert. + now rewrite lookup_insert_ne. Qed. Lemma lookup_insert_None (m : M A) i j x : <[i:=x]>m !! j = None ↔ m !! j = None ∧ i ≠ j. Proof. split. * destruct (decide (i = j)); subst; rewrite ?lookup_insert, ?lookup_insert_ne; intuition congruence. * intros [??]. now rewrite lookup_insert_ne. Qed. Lemma lookup_singleton_Some i j (x y : A) : {[(i, x)]} !! j = Some y ↔ i = j ∧ x = y. Proof. unfold singleton, finmap_singleton. rewrite lookup_insert_Some, lookup_empty. simpl. intuition congruence. Qed. Lemma lookup_singleton_None i j (x : A) : {[(i, x)]} !! j = None ↔ i ≠ j. Proof. unfold singleton, finmap_singleton. rewrite lookup_insert_None, lookup_empty. simpl. tauto. Qed. Lemma lookup_singleton i (x : A) : {[(i, x)]} !! i = Some x. Proof. rewrite lookup_singleton_Some. tauto. Qed. Lemma lookup_singleton_ne i j (x : A) : i ≠ j → {[(i, x)]} !! j = None. Proof. now rewrite lookup_singleton_None. Qed. Lemma lookup_delete (m : M A) i : delete i m !! i = None. Proof. apply lookup_partial_alter. Qed. Lemma lookup_delete_ne (m : M A) i j : i ≠ j → delete i m !! j = m !! j. Proof. apply lookup_partial_alter_ne. Qed. Lemma lookup_delete_Some (m : M A) i j y : delete i m !! j = Some y ↔ i ≠ j ∧ m !! j = Some y. Proof. split. * destruct (decide (i = j)); subst; rewrite ?lookup_delete, ?lookup_delete_ne; intuition congruence. * intros [??]. now rewrite lookup_delete_ne. Qed. Lemma lookup_delete_None (m : M A) i j : delete i m !! j = None ↔ i = j ∨ m !! j = None. Proof. destruct (decide (i = j)). * subst. rewrite lookup_delete. tauto. * rewrite lookup_delete_ne; tauto. Qed. Lemma delete_empty i : delete i (∅ : M A) = ∅. Proof. rewrite <-(partial_alter_self ∅) at 2. now rewrite lookup_empty. Qed. Lemma delete_singleton i (x : A) : delete i {[(i, x)]} = ∅. Proof. setoid_rewrite <-partial_alter_compose. apply delete_empty. Qed. Lemma delete_comm (m : M A) i j : delete i (delete j m) = delete j (delete i m). Proof. destruct (decide (i = j)). now subst. now apply partial_alter_comm. Qed. Lemma delete_insert_comm (m : M A) i j x : i ≠ j → delete i (<[j:=x]>m) = <[j:=x]>(delete i m). Proof. intro. now apply partial_alter_comm. Qed. Lemma delete_notin (m : M A) i : m !! i = None → delete i m = m. Proof. intros. apply finmap_eq. intros j. destruct (decide (i = j)). * subst. now rewrite lookup_delete. * now apply lookup_delete_ne. Qed. Lemma delete_partial_alter (m : M A) i f : m !! i = None → delete i (partial_alter f i m) = m. Proof. `````` Robbert Krebbers committed Aug 29, 2012 226 `````` intros. unfold delete, finmap_delete. rewrite <-partial_alter_compose. `````` Robbert Krebbers committed Aug 21, 2012 227 228 `````` rapply partial_alter_self_alt. congruence. Qed. `````` Robbert Krebbers committed Aug 29, 2012 229 ``````Lemma delete_partial_alter_dom C `{Collection K C} (m : M A) i f : `````` Robbert Krebbers committed Aug 21, 2012 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 `````` i ∉ dom C m → delete i (partial_alter f i m) = m. Proof. rewrite (not_elem_of_dom C). apply delete_partial_alter. Qed. Lemma delete_insert (m : M A) i x : m !! i = None → delete i (<[i:=x]>m) = m. Proof. apply delete_partial_alter. Qed. Lemma delete_insert_dom C `{Collection K C} (m : M A) i x : i ∉ dom C m → delete i (<[i:=x]>m) = m. Proof. rewrite (not_elem_of_dom C). apply delete_partial_alter. Qed. Lemma insert_delete (m : M A) i x : m !! i = Some x → <[i:=x]>(delete i m) = m. Proof. intros Hmi. unfold delete, finmap_delete, insert, finmap_insert. rewrite <-partial_alter_compose. unfold compose. rewrite <-Hmi. now apply partial_alter_self_alt. Qed. Lemma elem_of_dom_delete C `{Collection K C} (m : M A) i j : i ∈ dom C (delete j m) ↔ i ≠ j ∧ i ∈ dom C m. Proof. rewrite !(elem_of_dom C). unfold is_Some. setoid_rewrite lookup_delete_Some. firstorder auto. Qed. Lemma not_elem_of_dom_delete C `{Collection K C} (m : M A) i : i ∉ dom C (delete i m). Proof. apply (not_elem_of_dom C), lookup_delete. Qed. `````` Robbert Krebbers committed Jun 11, 2012 253 `````` `````` Robbert Krebbers committed Aug 29, 2012 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 ``````(** * Induction principles *) (** We use the induction principle on finite collections to prove the following induction principle on finite maps. *) Lemma finmap_ind_alt C (P : M A → Prop) `{FinCollection K C} : P ∅ → (∀ i x m, i ∉ dom C m → P m → P (<[i:=x]>m)) → ∀ m, P m. Proof. intros Hemp Hinsert m. apply (collection_ind (λ X, ∀ m, dom C m ≡ X → P m)) with (dom C m). * solve_proper. * clear m. intros m Hm. rewrite finmap_empty. + easy. + intros. rewrite <-(not_elem_of_dom C), Hm. now solve_elem_of. * clear m. intros i X Hi IH m Hdom. assert (is_Some (m !! i)) as [x Hx]. { apply (elem_of_dom C). rewrite Hdom. clear Hdom. now solve_elem_of. } rewrite <-(insert_delete m i x) by easy. apply Hinsert. { now apply (not_elem_of_dom_delete C). } apply IH. apply elem_of_equiv. intros. rewrite (elem_of_dom_delete C). esolve_elem_of. * easy. Qed. (** We use the [listset] implementation to prove an induction principle that does not mention the map's domain. *) Lemma finmap_ind (P : M A → Prop) : P ∅ → (∀ i x m, m !! i = None → P m → P (<[i:=x]>m)) → ∀ m, P m. Proof. setoid_rewrite <-(not_elem_of_dom (listset _)). apply (finmap_ind_alt (listset _) P). Qed. (** * Deleting and inserting multiple elements *) `````` Robbert Krebbers committed Aug 21, 2012 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 ``````Lemma lookup_delete_list (m : M A) is j : In j is → delete_list is m !! j = None. Proof. induction is as [|i is]; simpl; [easy |]. intros [?|?]. * subst. now rewrite lookup_delete. * destruct (decide (i = j)). + subst. now rewrite lookup_delete. + rewrite lookup_delete_ne; auto. Qed. Lemma lookup_delete_list_notin (m : M A) is j : ¬In j is → delete_list is m !! j = m !! j. Proof. induction is; simpl; [easy |]. intros. rewrite lookup_delete_ne; tauto. Qed. Lemma delete_list_notin (m : M A) is : Forall (λ i, m !! i = None) is → delete_list is m = m. Proof. induction 1; simpl; [easy |]. rewrite delete_notin; congruence. Qed. Lemma delete_list_insert_comm (m : M A) is j x : ¬In j is → delete_list is (<[j:=x]>m) = <[j:=x]>(delete_list is m). Proof. induction is; simpl; [easy |]. intros. rewrite IHis, delete_insert_comm; tauto. Qed. `````` Robbert Krebbers committed Aug 29, 2012 325 326 ``````Lemma lookup_insert_list (m : M A) l1 l2 i x : (∀y, ¬In (i,y) l1) → insert_list (l1 ++ (i,x) :: l2) m !! i = Some x. `````` Robbert Krebbers committed Aug 21, 2012 327 ``````Proof. `````` Robbert Krebbers committed Aug 29, 2012 328 329 330 331 332 333 334 335 336 `````` induction l1 as [|[j y] l1 IH]; simpl. * intros. now rewrite lookup_insert. * intros Hy. rewrite lookup_insert_ne; naive_solver. Qed. Lemma lookup_insert_list_not_in (m : M A) l i : (∀y, ¬In (i,y) l) → insert_list l m !! i = m !! i. Proof. induction l as [|[j y] l IH]; simpl. `````` Robbert Krebbers committed Aug 21, 2012 337 `````` * easy. `````` Robbert Krebbers committed Aug 29, 2012 338 `````` * intros Hy. rewrite lookup_insert_ne; naive_solver. `````` Robbert Krebbers committed Aug 21, 2012 339 340 ``````Qed. `````` Robbert Krebbers committed Aug 29, 2012 341 ``````(** * Properties of the merge operation *) `````` Robbert Krebbers committed Aug 21, 2012 342 343 344 345 ``````Section merge. Context (f : option A → option A → option A). Global Instance: LeftId (=) None f → LeftId (=) ∅ (merge f). `````` Robbert Krebbers committed Jun 11, 2012 346 `````` Proof. `````` Robbert Krebbers committed Aug 21, 2012 347 348 `````` intros ??. apply finmap_eq. intros. now rewrite !(merge_spec f), lookup_empty, (left_id None f). `````` Robbert Krebbers committed Jun 11, 2012 349 `````` Qed. `````` Robbert Krebbers committed Aug 21, 2012 350 `````` Global Instance: RightId (=) None f → RightId (=) ∅ (merge f). `````` Robbert Krebbers committed Jun 11, 2012 351 `````` Proof. `````` Robbert Krebbers committed Aug 21, 2012 352 353 `````` intros ??. apply finmap_eq. intros. now rewrite !(merge_spec f), lookup_empty, (right_id None f). `````` Robbert Krebbers committed Jun 11, 2012 354 `````` Qed. `````` Robbert Krebbers committed Aug 21, 2012 355 356 357 358 359 360 361 `````` Global Instance: Idempotent (=) f → Idempotent (=) (merge f). Proof. intros ??. apply finmap_eq. intros. now rewrite !(merge_spec f). Qed. Context `{!PropHolds (f None None = None)}. Lemma merge_spec_alt m1 m2 m : (∀ i, m !! i = f (m1 !! i) (m2 !! i)) ↔ merge f m1 m2 = m. `````` Robbert Krebbers committed Jun 11, 2012 362 `````` Proof. `````` Robbert Krebbers committed Aug 21, 2012 363 364 365 `````` split; [| intro; subst; apply (merge_spec _) ]. intros Hlookup. apply finmap_eq. intros. rewrite Hlookup. apply (merge_spec _). `````` Robbert Krebbers committed Jun 11, 2012 366 `````` Qed. `````` Robbert Krebbers committed Aug 21, 2012 367 368 369 370 371 372 373 374 375 `````` Lemma merge_comm m1 m2 : (∀ i, f (m1 !! i) (m2 !! i) = f (m2 !! i) (m1 !! i)) → merge f m1 m2 = merge f m2 m1. Proof. intros. apply finmap_eq. intros. now rewrite !(merge_spec f). Qed. Global Instance: Commutative (=) f → Commutative (=) (merge f). Proof. intros ???. apply merge_comm. intros. now apply (commutative f). Qed. Lemma merge_assoc m1 m2 m3 : `````` Robbert Krebbers committed Aug 29, 2012 376 377 `````` (∀ i, f (m1 !! i) (f (m2 !! i) (m3 !! i)) = f (f (m1 !! i) (m2 !! i)) (m3 !! i)) → `````` Robbert Krebbers committed Aug 21, 2012 378 379 380 381 382 383 `````` merge f m1 (merge f m2 m3) = merge f (merge f m1 m2) m3. Proof. intros. apply finmap_eq. intros. now rewrite !(merge_spec f). Qed. Global Instance: Associative (=) f → Associative (=) (merge f). Proof. intros ????. apply merge_assoc. intros. now apply (associative f). Qed. End merge. `````` Robbert Krebbers committed Aug 29, 2012 384 ``````(** * Properties of the union and intersection operation *) `````` Robbert Krebbers committed Aug 21, 2012 385 386 387 388 ``````Section union_intersection. Context (f : A → A → A). Lemma finmap_union_merge m1 m2 i x y : `````` Robbert Krebbers committed Aug 29, 2012 389 390 391 `````` m1 !! i = Some x → m2 !! i = Some y → union_with f m1 m2 !! i = Some (f x y). `````` Robbert Krebbers committed Jun 14, 2012 392 `````` Proof. `````` Robbert Krebbers committed Aug 21, 2012 393 394 `````` intros Hx Hy. unfold union_with, finmap_union. now rewrite (merge_spec _), Hx, Hy. `````` Robbert Krebbers committed Aug 29, 2012 395 `````` Qed. `````` Robbert Krebbers committed Aug 21, 2012 396 397 `````` Lemma finmap_union_l m1 m2 i x : m1 !! i = Some x → m2 !! i = None → union_with f m1 m2 !! i = Some x. `````` Robbert Krebbers committed Jun 14, 2012 398 `````` Proof. `````` Robbert Krebbers committed Aug 21, 2012 399 400 `````` intros Hx Hy. unfold union_with, finmap_union. now rewrite (merge_spec _), Hx, Hy. `````` Robbert Krebbers committed Jun 14, 2012 401 `````` Qed. `````` Robbert Krebbers committed Aug 21, 2012 402 403 `````` Lemma finmap_union_r m1 m2 i y : m1 !! i = None → m2 !! i = Some y → union_with f m1 m2 !! i = Some y. `````` Robbert Krebbers committed Jun 11, 2012 404 `````` Proof. `````` Robbert Krebbers committed Aug 21, 2012 405 406 `````` intros Hx Hy. unfold union_with, finmap_union. now rewrite (merge_spec _), Hx, Hy. `````` Robbert Krebbers committed Jun 11, 2012 407 `````` Qed. `````` Robbert Krebbers committed Aug 21, 2012 408 409 `````` Lemma finmap_union_None m1 m2 i : union_with f m1 m2 !! i = None ↔ m1 !! i = None ∧ m2 !! i = None. `````` Robbert Krebbers committed Jun 11, 2012 410 `````` Proof. `````` Robbert Krebbers committed Aug 21, 2012 411 412 `````` unfold union_with, finmap_union. rewrite (merge_spec _). destruct (m1 !! i), (m2 !! i); compute; intuition congruence. `````` Robbert Krebbers committed Jun 11, 2012 413 414 `````` Qed. `````` Robbert Krebbers committed Aug 21, 2012 415 416 417 418 419 420 421 422 423 `````` Global Instance: LeftId (=) ∅ (union_with f : M A → M A → M A) := _. Global Instance: RightId (=) ∅ (union_with f : M A → M A → M A) := _. Global Instance: Commutative (=) f → Commutative (=) (union_with f : M A → M A → M A) := _. Global Instance: Associative (=) f → Associative (=) (union_with f : M A → M A → M A) := _. Global Instance: Idempotent (=) f → Idempotent (=) (union_with f : M A → M A → M A) := _. End union_intersection. `````` Robbert Krebbers committed Jun 11, 2012 424 ``````End finmap. `````` Robbert Krebbers committed Aug 21, 2012 425 `````` `````` Robbert Krebbers committed Aug 29, 2012 426 427 428 429 ``````(** * The finite map tactic *) (** The tactic [simplify_map by tac] simplifies finite map expressions occuring in the conclusion and assumptions. It uses [tac] to discharge generated inequalities. *) `````` Robbert Krebbers committed Aug 21, 2012 430 431 ``````Tactic Notation "simplify_map" "by" tactic(T) := repeat match goal with `````` Robbert Krebbers committed Aug 29, 2012 432 `````` | _ => progress simplify_equality `````` Robbert Krebbers committed Aug 21, 2012 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 `````` | H : context[ ∅ !! _ ] |- _ => rewrite lookup_empty in H | H : context[ (<[_:=_]>_) !! _ ] |- _ => rewrite lookup_insert in H | H : context[ (<[_:=_]>_) !! _ ] |- _ => rewrite lookup_insert_ne in H by T | H : context[ (delete _ _) !! _ ] |- _ => rewrite lookup_delete in H | H : context[ (delete _ _) !! _ ] |- _ => rewrite lookup_delete_ne in H by T | H : context[ {[ _ ]} !! _ ] |- _ => rewrite lookup_singleton in H | H : context[ {[ _ ]} !! _ ] |- _ => rewrite lookup_singleton_ne in H by T | |- context[ ∅ !! _ ] => rewrite lookup_empty | |- context[ (<[_:=_]>_) !! _ ] => rewrite lookup_insert | |- context[ (<[_:=_]>_) !! _ ] => rewrite lookup_insert_ne by T | |- context[ (delete _ _) !! _ ] => rewrite lookup_delete | |- context[ (delete _ _) !! _ ] => rewrite lookup_delete_ne by T | |- context[ {[ _ ]} !! _ ] => rewrite lookup_singleton | |- context[ {[ _ ]} !! _ ] => rewrite lookup_singleton_ne by T end. Tactic Notation "simplify_map" := simplify_map by auto.``````