collections.v 47.1 KB
Newer Older
1
(* Copyright (c) 2012-2017, Coq-std++ developers. *)
2
3
4
5
(* This file is distributed under the terms of the BSD license. *)
(** This file collects definitions and theorems on collections. Most
importantly, it implements some tactics to automatically solve goals involving
collections. *)
6
From stdpp Require Export orders list.
7
8
(* FIXME: This file needs a 'Proof Using' hint, but the default we use
   everywhere makes for lots of extra ssumptions. *)
9

10
11
Instance collection_equiv `{ElemOf A C} : Equiv C := λ X Y,
   x, x  X  x  Y.
12
13
Instance collection_subseteq `{ElemOf A C} : SubsetEq C := λ X Y,
   x, x  X  x  Y.
14
15
16
Instance collection_disjoint `{ElemOf A C} : Disjoint C := λ X Y,
   x, x  X  x  Y  False.
Typeclasses Opaque collection_equiv collection_subseteq collection_disjoint.
17

18
19
(** * Setoids *)
Section setoids_simple.
20
  Context `{SimpleCollection A C}.
Robbert Krebbers's avatar
Robbert Krebbers committed
21

22
  Global Instance collection_equivalence : Equivalence (@{C}).
23
  Proof.
24
25
26
27
    split.
    - done.
    - intros X Y ? x. by symmetry.
    - intros X Y Z ?? x; by trans (x  Y).
28
  Qed.
29
  Global Instance singleton_proper : Proper ((=) ==> (@{C})) singleton.
30
  Proof. apply _. Qed.
Robbert Krebbers's avatar
Robbert Krebbers committed
31
  Global Instance elem_of_proper : Proper ((=) ==> () ==> iff) (@{C}) | 5.
32
  Proof. by intros x ? <- X Y. Qed.
Robbert Krebbers's avatar
Robbert Krebbers committed
33
  Global Instance disjoint_proper: Proper (() ==> () ==> iff) (##@{C}).
34
  Proof.
35
    intros X1 X2 HX Y1 Y2 HY; apply forall_proper; intros x. by rewrite HX, HY.
36
  Qed.
37
  Global Instance union_proper : Proper (() ==> () ==> (@{C})) union.
38
  Proof. intros X1 X2 HX Y1 Y2 HY x. rewrite !elem_of_union. f_equiv; auto. Qed.
39
  Global Instance union_list_proper: Proper (() ==> (@{C})) union_list.
40
  Proof. by induction 1; simpl; try apply union_proper. Qed.
41
  Global Instance subseteq_proper : Proper ((@{C}) ==> (@{C}) ==> iff) ().
42
43
44
45
46
47
48
  Proof.
    intros X1 X2 HX Y1 Y2 HY. apply forall_proper; intros x. by rewrite HX, HY.
  Qed.
End setoids_simple.

Section setoids.
  Context `{Collection A C}.
49

50
51
  (** * Setoids *)
  Global Instance intersection_proper :
52
    Proper (() ==> () ==> (@{C})) intersection.
53
  Proof.
54
    intros X1 X2 HX Y1 Y2 HY x. by rewrite !elem_of_intersection, HX, HY.
55
  Qed.
56
  Global Instance difference_proper :
57
     Proper (() ==> () ==> (@{C})) difference.
58
  Proof.
59
    intros X1 X2 HX Y1 Y2 HY x. by rewrite !elem_of_difference, HX, HY.
60
  Qed.
61
End setoids.
Robbert Krebbers's avatar
Robbert Krebbers committed
62

63
64
65
66
67
Section setoids_monad.
  Context `{CollectionMonad M}.

  Global Instance collection_fmap_proper {A B} :
    Proper (pointwise_relation _ (=) ==> () ==> ()) (@fmap M _ A B).
68
  Proof.
69
70
    intros f1 f2 Hf X1 X2 HX x. rewrite !elem_of_fmap. f_equiv; intros z.
    by rewrite HX, Hf.
71
  Qed.
72
  Global Instance collection_bind_proper {A B} :
73
    Proper (pointwise_relation _ () ==> () ==> ()) (@mbind M _ A B).
74
75
  Proof.
    intros f1 f2 Hf X1 X2 HX x. rewrite !elem_of_bind. f_equiv; intros z.
76
    by rewrite HX, (Hf z).
77
78
79
80
81
82
83
  Qed.
  Global Instance collection_join_proper {A} :
    Proper (() ==> ()) (@mjoin M _ A).
  Proof.
    intros X1 X2 HX x. rewrite !elem_of_join. f_equiv; intros z. by rewrite HX.
  Qed.
End setoids_monad.
84

85
86
87
88
89
(** * Tactics *)
(** The tactic [set_unfold] transforms all occurrences of [(∪)], [(∩)], [(∖)],
[(<$>)], [∅], [{[_]}], [(≡)], and [(⊆)] into logically equivalent propositions
involving just [∈]. For example, [A → x ∈ X ∪ ∅] becomes [A → x ∈ X ∨ False].

90
91
92
This transformation is implemented using type classes instead of setoid
rewriting to ensure that we traverse each term at most once and to be able to
deal with occurences of the set operations under binders. *)
93
Class SetUnfold (P Q : Prop) := { set_unfold : P  Q }.
94
Arguments set_unfold _ _ {_} : assert.
95
96
97
98
99
Hint Mode SetUnfold + - : typeclass_instances.

Class SetUnfoldSimpl (P Q : Prop) := { set_unfold_simpl : SetUnfold P Q }.
Hint Extern 0 (SetUnfoldSimpl _ _) => csimpl; constructor : typeclass_instances.

100
Instance set_unfold_default P : SetUnfold P P | 1000. done. Qed.
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
Definition set_unfold_1 `{SetUnfold P Q} : P  Q := proj1 (set_unfold P Q).
Definition set_unfold_2 `{SetUnfold P Q} : Q  P := proj2 (set_unfold P Q).

Lemma set_unfold_impl P Q P' Q' :
  SetUnfold P P'  SetUnfold Q Q'  SetUnfold (P  Q) (P'  Q').
Proof. constructor. by rewrite (set_unfold P P'), (set_unfold Q Q'). Qed.
Lemma set_unfold_and P Q P' Q' :
  SetUnfold P P'  SetUnfold Q Q'  SetUnfold (P  Q) (P'  Q').
Proof. constructor. by rewrite (set_unfold P P'), (set_unfold Q Q'). Qed.
Lemma set_unfold_or P Q P' Q' :
  SetUnfold P P'  SetUnfold Q Q'  SetUnfold (P  Q) (P'  Q').
Proof. constructor. by rewrite (set_unfold P P'), (set_unfold Q Q'). Qed.
Lemma set_unfold_iff P Q P' Q' :
  SetUnfold P P'  SetUnfold Q Q'  SetUnfold (P  Q) (P'  Q').
Proof. constructor. by rewrite (set_unfold P P'), (set_unfold Q Q'). Qed.
Lemma set_unfold_not P P' : SetUnfold P P'  SetUnfold (¬P) (¬P').
Proof. constructor. by rewrite (set_unfold P P'). Qed.
Lemma set_unfold_forall {A} (P P' : A  Prop) :
  ( x, SetUnfold (P x) (P' x))  SetUnfold ( x, P x) ( x, P' x).
Proof. constructor. naive_solver. Qed.
Lemma set_unfold_exist {A} (P P' : A  Prop) :
  ( x, SetUnfold (P x) (P' x))  SetUnfold ( x, P x) ( x, P' x).
Proof. constructor. naive_solver. Qed.

(* Avoid too eager application of the above instances (and thus too eager
unfolding of type class transparent definitions). *)
Hint Extern 0 (SetUnfold (_  _) _) =>
  class_apply set_unfold_impl : typeclass_instances.
Hint Extern 0 (SetUnfold (_  _) _) =>
  class_apply set_unfold_and : typeclass_instances.
Hint Extern 0 (SetUnfold (_  _) _) =>
  class_apply set_unfold_or : typeclass_instances.
Hint Extern 0 (SetUnfold (_  _) _) =>
  class_apply set_unfold_iff : typeclass_instances.
Hint Extern 0 (SetUnfold (¬ _) _) =>
  class_apply set_unfold_not : typeclass_instances.
Hint Extern 1 (SetUnfold ( _, _) _) =>
  class_apply set_unfold_forall : typeclass_instances.
Hint Extern 0 (SetUnfold ( _, _) _) =>
  class_apply set_unfold_exist : typeclass_instances.

Section set_unfold_simple.
  Context `{SimpleCollection A C}.
  Implicit Types x y : A.
  Implicit Types X Y : C.

147
  Global Instance set_unfold_empty x : SetUnfold (x  ( : C)) False.
148
  Proof. constructor. split. apply not_elem_of_empty. done. Qed.
149
  Global Instance set_unfold_singleton x y : SetUnfold (x  ({[ y ]} : C)) (x = y).
150
151
152
153
154
155
156
157
158
159
160
161
  Proof. constructor; apply elem_of_singleton. Qed.
  Global Instance set_unfold_union x X Y P Q :
    SetUnfold (x  X) P  SetUnfold (x  Y) Q  SetUnfold (x  X  Y) (P  Q).
  Proof.
    intros ??; constructor.
    by rewrite elem_of_union, (set_unfold (x  X) P), (set_unfold (x  Y) Q).
  Qed.
  Global Instance set_unfold_equiv_same X : SetUnfold (X  X) True | 1.
  Proof. done. Qed.
  Global Instance set_unfold_equiv_empty_l X (P : A  Prop) :
    ( x, SetUnfold (x  X) (P x))  SetUnfold (  X) ( x, ¬P x) | 5.
  Proof.
162
    intros ?; constructor. unfold equiv, collection_equiv.
163
    pose proof (not_elem_of_empty (C:=C)); naive_solver.
164
  Qed.
165
  Global Instance set_unfold_equiv_empty_r (P : A  Prop) X :
166
    ( x, SetUnfold (x  X) (P x))  SetUnfold (X  ) ( x, ¬P x) | 5.
167
168
  Proof.
    intros ?; constructor. unfold equiv, collection_equiv.
169
    pose proof (not_elem_of_empty (C:=C)); naive_solver.
170
  Qed.
171
  Global Instance set_unfold_equiv (P Q : A  Prop) X :
172
173
    ( x, SetUnfold (x  X) (P x))  ( x, SetUnfold (x  Y) (Q x)) 
    SetUnfold (X  Y) ( x, P x  Q x) | 10.
174
  Proof. constructor. apply forall_proper; naive_solver. Qed.
175
  Global Instance set_unfold_subseteq (P Q : A  Prop) X Y :
176
177
    ( x, SetUnfold (x  X) (P x))  ( x, SetUnfold (x  Y) (Q x)) 
    SetUnfold (X  Y) ( x, P x  Q x).
178
  Proof. constructor. apply forall_proper; naive_solver. Qed.
179
  Global Instance set_unfold_subset (P Q : A  Prop) X :
180
    ( x, SetUnfold (x  X) (P x))  ( x, SetUnfold (x  Y) (Q x)) 
181
    SetUnfold (X  Y) (( x, P x  Q x)  ¬∀ x, Q x  P x).
182
  Proof.
183
184
    constructor. unfold strict.
    repeat f_equiv; apply forall_proper; naive_solver.
185
  Qed.
186
  Global Instance set_unfold_disjoint (P Q : A  Prop) X Y :
Robbert Krebbers's avatar
Robbert Krebbers committed
187
    ( x, SetUnfold (x  X) (P x))  ( x, SetUnfold (x  Y) (Q x)) 
188
    SetUnfold (X ## Y) ( x, P x  Q x  False).
189
  Proof. constructor. unfold disjoint, collection_disjoint. naive_solver. Qed.
190
191
192
193
194
195

  Context `{!LeibnizEquiv C}.
  Global Instance set_unfold_equiv_same_L X : SetUnfold (X = X) True | 1.
  Proof. done. Qed.
  Global Instance set_unfold_equiv_empty_l_L X (P : A  Prop) :
    ( x, SetUnfold (x  X) (P x))  SetUnfold ( = X) ( x, ¬P x) | 5.
196
  Proof. constructor. unfold_leibniz. by apply set_unfold_equiv_empty_l. Qed.
197
  Global Instance set_unfold_equiv_empty_r_L (P : A  Prop) X :
198
    ( x, SetUnfold (x  X) (P x))  SetUnfold (X = ) ( x, ¬P x) | 5.
199
  Proof. constructor. unfold_leibniz. by apply set_unfold_equiv_empty_r. Qed.
200
  Global Instance set_unfold_equiv_L (P Q : A  Prop) X Y :
201
202
    ( x, SetUnfold (x  X) (P x))  ( x, SetUnfold (x  Y) (Q x)) 
    SetUnfold (X = Y) ( x, P x  Q x) | 10.
203
  Proof. constructor. unfold_leibniz. by apply set_unfold_equiv. Qed.
204
205
206
207
208
209
210
211
212
213
End set_unfold_simple.

Section set_unfold.
  Context `{Collection A C}.
  Implicit Types x y : A.
  Implicit Types X Y : C.

  Global Instance set_unfold_intersection x X Y P Q :
    SetUnfold (x  X) P  SetUnfold (x  Y) Q  SetUnfold (x  X  Y) (P  Q).
  Proof.
214
215
    intros ??; constructor. rewrite elem_of_intersection.
    by rewrite (set_unfold (x  X) P), (set_unfold (x  Y) Q).
216
217
218
219
  Qed.
  Global Instance set_unfold_difference x X Y P Q :
    SetUnfold (x  X) P  SetUnfold (x  Y) Q  SetUnfold (x  X  Y) (P  ¬Q).
  Proof.
220
221
    intros ??; constructor. rewrite elem_of_difference.
    by rewrite (set_unfold (x  X) P), (set_unfold (x  Y) Q).
222
223
224
225
  Qed.
End set_unfold.

Section set_unfold_monad.
226
  Context `{CollectionMonad M}.
227

228
229
  Global Instance set_unfold_ret {A} (x y : A) :
    SetUnfold (x  mret (M:=M) y) (x = y).
230
  Proof. constructor; apply elem_of_ret. Qed.
231
  Global Instance set_unfold_bind {A B} (f : A  M B) X (P Q : A  Prop) :
232
233
234
    ( y, SetUnfold (y  X) (P y))  ( y, SetUnfold (x  f y) (Q y)) 
    SetUnfold (x  X = f) ( y, Q y  P y).
  Proof. constructor. rewrite elem_of_bind; naive_solver. Qed.
235
  Global Instance set_unfold_fmap {A B} (f : A  B) (X : M A) (P : A  Prop) :
236
237
238
    ( y, SetUnfold (y  X) (P y)) 
    SetUnfold (x  f <$> X) ( y, x = f y  P y).
  Proof. constructor. rewrite elem_of_fmap; naive_solver. Qed.
239
  Global Instance set_unfold_join {A} (X : M (M A)) (P : M A  Prop) :
240
241
242
243
    ( Y, SetUnfold (Y  X) (P Y))  SetUnfold (x  mjoin X) ( Y, x  Y  P Y).
  Proof. constructor. rewrite elem_of_join; naive_solver. Qed.
End set_unfold_monad.

Robbert Krebbers's avatar
Robbert Krebbers committed
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
Section set_unfold_list.
  Context {A : Type}.
  Implicit Types x : A.
  Implicit Types l : list A.

  Global Instance set_unfold_nil x : SetUnfold (x  []) False.
  Proof. constructor; apply elem_of_nil. Qed.
  Global Instance set_unfold_cons x y l P :
    SetUnfold (x  l) P  SetUnfold (x  y :: l) (x = y  P).
  Proof. constructor. by rewrite elem_of_cons, (set_unfold (x  l) P). Qed.
  Global Instance set_unfold_app x l k P Q :
    SetUnfold (x  l) P  SetUnfold (x  k) Q  SetUnfold (x  l ++ k) (P  Q).
  Proof.
    intros ??; constructor.
    by rewrite elem_of_app, (set_unfold (x  l) P), (set_unfold (x  k) Q).
  Qed.
  Global Instance set_unfold_included l k (P Q : A  Prop) :
    ( x, SetUnfold (x  l) (P x))  ( x, SetUnfold (x  k) (Q x)) 
    SetUnfold (l  k) ( x, P x  Q x).
  Proof.
    constructor; unfold subseteq, list_subseteq.
    apply forall_proper; naive_solver.
  Qed.
End set_unfold_list.

269
270
271
Ltac set_unfold :=
  let rec unfold_hyps :=
    try match goal with
272
273
274
275
276
277
278
    | H : ?P |- _ =>
       lazymatch type of P with
       | Prop =>
         apply set_unfold_1 in H; revert H;
         first [unfold_hyps; intros H | intros H; fail 1]
       | _ => fail
       end
279
280
281
    end in
  apply set_unfold_2; unfold_hyps; csimpl in *.

282
283
(** Since [firstorder] already fails or loops on very small goals generated by
[set_solver], we use the [naive_solver] tactic as a substitute. *)
284
Tactic Notation "set_solver" "by" tactic3(tac) :=
285
  try fast_done;
286
287
288
289
290
291
292
293
294
295
296
297
298
  intros; setoid_subst;
  set_unfold;
  intros; setoid_subst;
  try match goal with |- _  _ => apply dec_stable end;
  naive_solver tac.
Tactic Notation "set_solver" "-" hyp_list(Hs) "by" tactic3(tac) :=
  clear Hs; set_solver by tac.
Tactic Notation "set_solver" "+" hyp_list(Hs) "by" tactic3(tac) :=
  clear -Hs; set_solver by tac.
Tactic Notation "set_solver" := set_solver by idtac.
Tactic Notation "set_solver" "-" hyp_list(Hs) := clear Hs; set_solver.
Tactic Notation "set_solver" "+" hyp_list(Hs) := clear -Hs; set_solver.

299
300
301
302
Hint Extern 1000 (_  _) => set_solver : set_solver.
Hint Extern 1000 (_  _) => set_solver : set_solver.
Hint Extern 1000 (_  _) => set_solver : set_solver.

303

304
305
(** * Collections with [∪], [∅] and [{[_]}] *)
Section simple_collection.
306
  Context `{SimpleCollection A C}.
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
  Implicit Types x y : A.
  Implicit Types X Y : C.
  Implicit Types Xs Ys : list C.

  (** Equality *)
  Lemma elem_of_equiv X Y : X  Y   x, x  X  x  Y.
  Proof. set_solver. Qed.
  Lemma collection_equiv_spec X Y : X  Y  X  Y  Y  X.
  Proof. set_solver. Qed.

  (** Subset relation *)
  Global Instance collection_subseteq_antisymm: AntiSymm () (() : relation C).
  Proof. intros ??. set_solver. Qed.

  Global Instance collection_subseteq_preorder: PreOrder (() : relation C).
  Proof. split. by intros ??. intros ???; set_solver. Qed.

  Lemma subseteq_union X Y : X  Y  X  Y  Y.
  Proof. set_solver. Qed.
  Lemma subseteq_union_1 X Y : X  Y  X  Y  Y.
  Proof. by rewrite subseteq_union. Qed.
  Lemma subseteq_union_2 X Y : X  Y  Y  X  Y.
  Proof. by rewrite subseteq_union. Qed.

  Lemma union_subseteq_l X Y : X  X  Y.
  Proof. set_solver. Qed.
  Lemma union_subseteq_r X Y : Y  X  Y.
  Proof. set_solver. Qed.
  Lemma union_least X Y Z : X  Z  Y  Z  X  Y  Z.
  Proof. set_solver. Qed.

  Lemma elem_of_subseteq X Y : X  Y   x, x  X  x  Y.
  Proof. done. Qed.
  Lemma elem_of_subset X Y : X  Y  ( x, x  X  x  Y)  ¬( x, x  Y  x  X).
  Proof. set_solver. Qed.

  (** Union *)
344
345
  Lemma union_subseteq X Y Z : X  Y  Z  X  Z  Y  Z.
  Proof. set_solver. Qed.
346
347
348
349
350
351
  Lemma not_elem_of_union x X Y : x  X  Y  x  X  x  Y.
  Proof. set_solver. Qed.
  Lemma elem_of_union_l x X Y : x  X  x  X  Y.
  Proof. set_solver. Qed.
  Lemma elem_of_union_r x X Y : x  Y  x  X  Y.
  Proof. set_solver. Qed.
Robbert Krebbers's avatar
Robbert Krebbers committed
352
  Lemma union_mono_l X Y1 Y2 : Y1  Y2  X  Y1  X  Y2.
353
  Proof. set_solver. Qed.
Robbert Krebbers's avatar
Robbert Krebbers committed
354
  Lemma union_mono_r X1 X2 Y : X1  X2  X1  Y  X2  Y.
355
  Proof. set_solver. Qed.
Robbert Krebbers's avatar
Robbert Krebbers committed
356
  Lemma union_mono X1 X2 Y1 Y2 : X1  X2  Y1  Y2  X1  Y1  X2  Y2.
357
358
  Proof. set_solver. Qed.

359
  Global Instance union_idemp : IdemP (@{C}) ().
360
  Proof. intros X. set_solver. Qed.
361
  Global Instance union_empty_l : LeftId (@{C})  ().
362
  Proof. intros X. set_solver. Qed.
363
  Global Instance union_empty_r : RightId (@{C})  ().
364
  Proof. intros X. set_solver. Qed.
365
  Global Instance union_comm : Comm (@{C}) ().
366
  Proof. intros X Y. set_solver. Qed.
367
  Global Instance union_assoc : Assoc (@{C}) ().
368
369
370
371
372
  Proof. intros X Y Z. set_solver. Qed.

  Lemma empty_union X Y : X  Y    X    Y  .
  Proof. set_solver. Qed.

373
  Lemma union_cancel_l X Y Z : Z ## X  Z ## Y  Z  X  Z  Y  X  Y.
Robbert Krebbers's avatar
Robbert Krebbers committed
374
  Proof. set_solver. Qed.
375
  Lemma union_cancel_r X Y Z : X ## Z  Y ## Z  X  Z  Y  Z  X  Y.
Robbert Krebbers's avatar
Robbert Krebbers committed
376
377
  Proof. set_solver. Qed.

378
  (** Empty *)
Robbert Krebbers's avatar
Robbert Krebbers committed
379
380
  Lemma empty_subseteq X :   X.
  Proof. set_solver. Qed.
381
382
  Lemma elem_of_equiv_empty X : X     x, x  X.
  Proof. set_solver. Qed.
383
  Lemma elem_of_empty x : x  ( : C)  False.
384
385
386
387
388
389
390
391
392
393
394
  Proof. set_solver. Qed.
  Lemma equiv_empty X : X    X  .
  Proof. set_solver. Qed.
  Lemma union_positive_l X Y : X  Y    X  .
  Proof. set_solver. Qed.
  Lemma union_positive_l_alt X Y : X    X  Y  .
  Proof. set_solver. Qed.
  Lemma non_empty_inhabited x X : x  X  X  .
  Proof. set_solver. Qed.

  (** Singleton *)
395
  Lemma elem_of_singleton_1 x y : x  ({[y]} : C)  x = y.
396
  Proof. by rewrite elem_of_singleton. Qed.
397
  Lemma elem_of_singleton_2 x y : x = y  x  ({[y]} : C).
398
399
400
401
402
  Proof. by rewrite elem_of_singleton. Qed.
  Lemma elem_of_subseteq_singleton x X : x  X  {[ x ]}  X.
  Proof. set_solver. Qed.
  Lemma non_empty_singleton x : ({[ x ]} : C)  .
  Proof. set_solver. Qed.
403
  Lemma not_elem_of_singleton x y : x  ({[ y ]} : C)  x  y.
404
405
406
  Proof. by rewrite elem_of_singleton. Qed.

  (** Disjointness *)
407
  Lemma elem_of_disjoint X Y : X ## Y   x, x  X  x  Y  False.
408
409
  Proof. done. Qed.

Robbert Krebbers's avatar
Robbert Krebbers committed
410
  Global Instance disjoint_sym : Symmetric (##@{C}).
411
  Proof. intros X Y. set_solver. Qed.
412
  Lemma disjoint_empty_l Y :  ## Y.
413
  Proof. set_solver. Qed.
414
  Lemma disjoint_empty_r X : X ## .
415
  Proof. set_solver. Qed.
416
  Lemma disjoint_singleton_l x Y : {[ x ]} ## Y  x  Y.
417
  Proof. set_solver. Qed.
418
  Lemma disjoint_singleton_r y X : X ## {[ y ]}  y  X.
419
  Proof. set_solver. Qed.
420
  Lemma disjoint_union_l X1 X2 Y : X1  X2 ## Y  X1 ## Y  X2 ## Y.
421
  Proof. set_solver. Qed.
422
  Lemma disjoint_union_r X Y1 Y2 : X ## Y1  Y2  X ## Y1  X ## Y2.
423
424
425
426
  Proof. set_solver. Qed.

  (** Big unions *)
  Lemma elem_of_union_list Xs x : x   Xs   X, X  Xs  x  X.
427
428
  Proof.
    split.
429
430
    - induction Xs; simpl; intros HXs; [by apply elem_of_empty in HXs|].
      setoid_rewrite elem_of_cons. apply elem_of_union in HXs. naive_solver.
Ralf Jung's avatar
Ralf Jung committed
431
    - intros [X [Hx]]. induction Hx; simpl; [by apply elem_of_union_l |].
432
      intros. apply elem_of_union_r; auto.
433
  Qed.
434

435
436
437
438
439
440
441
  Lemma union_list_nil :  @nil C = .
  Proof. done. Qed.
  Lemma union_list_cons X Xs :  (X :: Xs) = X   Xs.
  Proof. done. Qed.
  Lemma union_list_singleton X :  [X]  X.
  Proof. simpl. by rewrite (right_id  _). Qed.
  Lemma union_list_app Xs1 Xs2 :  (Xs1 ++ Xs2)   Xs1   Xs2.
442
  Proof.
443
444
    induction Xs1 as [|X Xs1 IH]; simpl; [by rewrite (left_id  _)|].
    by rewrite IH, (assoc _).
445
  Qed.
446
  Lemma union_list_reverse Xs :  (reverse Xs)   Xs.
447
  Proof.
448
449
450
    induction Xs as [|X Xs IH]; simpl; [done |].
    by rewrite reverse_cons, union_list_app,
      union_list_singleton, (comm _), IH.
451
  Qed.
Robbert Krebbers's avatar
Robbert Krebbers committed
452
453
  Lemma union_list_mono Xs Ys : Xs * Ys   Xs   Ys.
  Proof. induction 1; simpl; auto using union_mono. Qed.
454
  Lemma empty_union_list Xs :  Xs    Forall ( ) Xs.
455
  Proof.
456
457
458
    split.
    - induction Xs; simpl; rewrite ?empty_union; intuition.
    - induction 1 as [|?? E1 ? E2]; simpl. done. by apply empty_union.
459
  Qed.
460

461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
  Section leibniz.
    Context `{!LeibnizEquiv C}.

    Lemma elem_of_equiv_L X Y : X = Y   x, x  X  x  Y.
    Proof. unfold_leibniz. apply elem_of_equiv. Qed.
    Lemma collection_equiv_spec_L X Y : X = Y  X  Y  Y  X.
    Proof. unfold_leibniz. apply collection_equiv_spec. Qed.

    (** Subset relation *)
    Global Instance collection_subseteq_partialorder :
      PartialOrder (() : relation C).
    Proof. split. apply _. intros ??. unfold_leibniz. apply (anti_symm _). Qed.

    Lemma subseteq_union_L X Y : X  Y  X  Y = Y.
    Proof. unfold_leibniz. apply subseteq_union. Qed.
    Lemma subseteq_union_1_L X Y : X  Y  X  Y = Y.
    Proof. unfold_leibniz. apply subseteq_union_1. Qed.
    Lemma subseteq_union_2_L X Y : X  Y = Y  X  Y.
    Proof. unfold_leibniz. apply subseteq_union_2. Qed.

    (** Union *)
482
    Global Instance union_idemp_L : IdemP (=@{C}) ().
483
    Proof. intros ?. unfold_leibniz. apply (idemp _). Qed.
484
    Global Instance union_empty_l_L : LeftId (=@{C})  ().
485
    Proof. intros ?. unfold_leibniz. apply (left_id _ _). Qed.
486
    Global Instance union_empty_r_L : RightId (=@{C})  ().
487
    Proof. intros ?. unfold_leibniz. apply (right_id _ _). Qed.
488
    Global Instance union_comm_L : Comm (=@{C}) ().
489
    Proof. intros ??. unfold_leibniz. apply (comm _). Qed.
490
    Global Instance union_assoc_L : Assoc (=@{C}) ().
491
492
493
494
495
    Proof. intros ???. unfold_leibniz. apply (assoc _). Qed.

    Lemma empty_union_L X Y : X  Y =   X =   Y = .
    Proof. unfold_leibniz. apply empty_union. Qed.

496
    Lemma union_cancel_l_L X Y Z : Z ## X  Z ## Y  Z  X = Z  Y  X = Y.
Robbert Krebbers's avatar
Robbert Krebbers committed
497
    Proof. unfold_leibniz. apply union_cancel_l. Qed.
498
    Lemma union_cancel_r_L X Y Z : X ## Z  Y ## Z  X  Z = Y  Z  X = Y.
Robbert Krebbers's avatar
Robbert Krebbers committed
499
500
    Proof. unfold_leibniz. apply union_cancel_r. Qed.

501
502
503
504
505
506
507
508
509
510
511
512
513
    (** Empty *)
    Lemma elem_of_equiv_empty_L X : X =    x, x  X.
    Proof. unfold_leibniz. apply elem_of_equiv_empty. Qed.
    Lemma equiv_empty_L X : X    X = .
    Proof. unfold_leibniz. apply equiv_empty. Qed.
    Lemma union_positive_l_L X Y : X  Y =   X = .
    Proof. unfold_leibniz. apply union_positive_l. Qed.
    Lemma union_positive_l_alt_L X Y : X    X  Y  .
    Proof. unfold_leibniz. apply union_positive_l_alt. Qed.
    Lemma non_empty_inhabited_L x X : x  X  X  .
    Proof. unfold_leibniz. apply non_empty_inhabited. Qed.

    (** Singleton *)
514
    Lemma non_empty_singleton_L x : {[ x ]}  ( : C).
515
516
517
518
519
520
521
522
523
524
525
526
527
528
    Proof. unfold_leibniz. apply non_empty_singleton. Qed.

    (** Big unions *)
    Lemma union_list_singleton_L X :  [X] = X.
    Proof. unfold_leibniz. apply union_list_singleton. Qed.
    Lemma union_list_app_L Xs1 Xs2 :  (Xs1 ++ Xs2) =  Xs1   Xs2.
    Proof. unfold_leibniz. apply union_list_app. Qed.
    Lemma union_list_reverse_L Xs :  (reverse Xs) =  Xs.
    Proof. unfold_leibniz. apply union_list_reverse. Qed.
    Lemma empty_union_list_L Xs :  Xs =   Forall (= ) Xs.
    Proof. unfold_leibniz. by rewrite empty_union_list. Qed. 
  End leibniz.

  Section dec.
529
    Context `{!RelDecision (@{C})}.
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
    Lemma collection_subseteq_inv X Y : X  Y  X  Y  X  Y.
    Proof. destruct (decide (X  Y)); [by right|left;set_solver]. Qed.
    Lemma collection_not_subset_inv X Y : X  Y  X  Y  X  Y.
    Proof. destruct (decide (X  Y)); [by right|left;set_solver]. Qed.

    Lemma non_empty_union X Y : X  Y    X    Y  .
    Proof. rewrite empty_union. destruct (decide (X  )); intuition. Qed.
    Lemma non_empty_union_list Xs :  Xs    Exists ( ) Xs.
    Proof. rewrite empty_union_list. apply (not_Forall_Exists _). Qed.

    Context `{!LeibnizEquiv C}.
    Lemma collection_subseteq_inv_L X Y : X  Y  X  Y  X = Y.
    Proof. unfold_leibniz. apply collection_subseteq_inv. Qed.
    Lemma collection_not_subset_inv_L X Y : X  Y  X  Y  X = Y.
    Proof. unfold_leibniz. apply collection_not_subset_inv. Qed.
    Lemma non_empty_union_L X Y : X  Y    X    Y  .
    Proof. unfold_leibniz. apply non_empty_union. Qed.
    Lemma non_empty_union_list_L Xs :  Xs    Exists ( ) Xs.
    Proof. unfold_leibniz. apply non_empty_union_list. Qed.
  End dec.
End simple_collection.


(** * Collections with [∪], [∩], [∖], [∅] and [{[_]}] *)
Robbert Krebbers's avatar
Robbert Krebbers committed
554
555
Section collection.
  Context `{Collection A C}.
556
  Implicit Types x y : A.
557
  Implicit Types X Y : C.
Robbert Krebbers's avatar
Robbert Krebbers committed
558

559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
  (** Intersection *)
  Lemma subseteq_intersection X Y : X  Y  X  Y  X.
  Proof. set_solver. Qed. 
  Lemma subseteq_intersection_1 X Y : X  Y  X  Y  X.
  Proof. apply subseteq_intersection. Qed.
  Lemma subseteq_intersection_2 X Y : X  Y  X  X  Y.
  Proof. apply subseteq_intersection. Qed.

  Lemma intersection_subseteq_l X Y : X  Y  X.
  Proof. set_solver. Qed.
  Lemma intersection_subseteq_r X Y : X  Y  Y.
  Proof. set_solver. Qed.
  Lemma intersection_greatest X Y Z : Z  X  Z  Y  Z  X  Y.
  Proof. set_solver. Qed.

Robbert Krebbers's avatar
Robbert Krebbers committed
574
  Lemma intersection_mono_l X Y1 Y2 : Y1  Y2  X  Y1  X  Y2.
575
  Proof. set_solver. Qed.
Robbert Krebbers's avatar
Robbert Krebbers committed
576
  Lemma intersection_mono_r X1 X2 Y : X1  X2  X1  Y  X2  Y.
577
  Proof. set_solver. Qed.
Robbert Krebbers's avatar
Robbert Krebbers committed
578
  Lemma intersection_mono X1 X2 Y1 Y2 :
579
    X1  X2  Y1  Y2  X1  Y1  X2  Y2.
580
  Proof. set_solver. Qed.
581

582
  Global Instance intersection_idemp : IdemP (@{C}) ().
583
  Proof. intros X; set_solver. Qed.
584
  Global Instance intersection_comm : Comm (@{C}) ().
585
  Proof. intros X Y; set_solver. Qed.
586
  Global Instance intersection_assoc : Assoc (@{C}) ().
587
  Proof. intros X Y Z; set_solver. Qed.
588
  Global Instance intersection_empty_l : LeftAbsorb (@{C})  ().
589
  Proof. intros X; set_solver. Qed.
590
  Global Instance intersection_empty_r: RightAbsorb (@{C})  ().
591
592
  Proof. intros X; set_solver. Qed.

593
  Lemma intersection_singletons x : ({[x]} : C)  {[x]}  {[x]}.
594
  Proof. set_solver. Qed.
595
596
597
598
599
600
601
602
603
604
605

  Lemma union_intersection_l X Y Z : X  (Y  Z)  (X  Y)  (X  Z).
  Proof. set_solver. Qed.
  Lemma union_intersection_r X Y Z : (X  Y)  Z  (X  Z)  (Y  Z).
  Proof. set_solver. Qed.
  Lemma intersection_union_l X Y Z : X  (Y  Z)  (X  Y)  (X  Z).
  Proof. set_solver. Qed.
  Lemma intersection_union_r X Y Z : (X  Y)  Z  (X  Z)  (Y  Z).
  Proof. set_solver. Qed.

  (** Difference *)
Robbert Krebbers's avatar
Robbert Krebbers committed
606
  Lemma difference_twice X Y : (X  Y)  Y  X  Y.
607
  Proof. set_solver. Qed.
608
  Lemma subseteq_empty_difference X Y : X  Y  X  Y  .
609
  Proof. set_solver. Qed.
Robbert Krebbers's avatar
Robbert Krebbers committed
610
  Lemma difference_diag X : X  X  .
611
  Proof. set_solver. Qed.
612
613
  Lemma difference_empty X : X    X.
  Proof. set_solver. Qed.
Robbert Krebbers's avatar
Robbert Krebbers committed
614
  Lemma difference_union_distr_l X Y Z : (X  Y)  Z  X  Z  Y  Z.
615
  Proof. set_solver. Qed.
Robbert Krebbers's avatar
Robbert Krebbers committed
616
  Lemma difference_union_distr_r X Y Z : Z  (X  Y)  (Z  X)  (Z  Y).
617
  Proof. set_solver. Qed.
Robbert Krebbers's avatar
Robbert Krebbers committed
618
  Lemma difference_intersection_distr_l X Y Z : (X  Y)  Z  X  Z  Y  Z.
619
  Proof. set_solver. Qed.
620
  Lemma difference_disjoint X Y : X ## Y  X  Y  X.
621
  Proof. set_solver. Qed.
622
623
624
  Lemma subset_difference_elem_of {x: A} {s: C} (inx: x  s): s  {[ x ]}  s.
  Proof. set_solver. Qed.

Robbert Krebbers's avatar
Robbert Krebbers committed
625

Robbert Krebbers's avatar
Robbert Krebbers committed
626
  Lemma difference_mono X1 X2 Y1 Y2 :
Robbert Krebbers's avatar
Robbert Krebbers committed
627
628
    X1  X2  Y2  Y1  X1  Y1  X2  Y2.
  Proof. set_solver. Qed.
Robbert Krebbers's avatar
Robbert Krebbers committed
629
  Lemma difference_mono_l X Y1 Y2 : Y2  Y1  X  Y1  X  Y2.
Robbert Krebbers's avatar
Robbert Krebbers committed
630
  Proof. set_solver. Qed.
Robbert Krebbers's avatar
Robbert Krebbers committed
631
  Lemma difference_mono_r X1 X2 Y : X1  X2  X1  Y  X2  Y.
Robbert Krebbers's avatar
Robbert Krebbers committed
632
633
  Proof. set_solver. Qed.

634
  (** Disjointness *)
635
  Lemma disjoint_intersection X Y : X ## Y  X  Y  .
636
637
  Proof. set_solver. Qed.

638
639
  Section leibniz.
    Context `{!LeibnizEquiv C}.
640
641
642
643
644
645
646
647
648

    (** Intersection *)
    Lemma subseteq_intersection_L X Y : X  Y  X  Y = X.
    Proof. unfold_leibniz. apply subseteq_intersection. Qed.
    Lemma subseteq_intersection_1_L X Y : X  Y  X  Y = X.
    Proof. unfold_leibniz. apply subseteq_intersection_1. Qed.
    Lemma subseteq_intersection_2_L X Y : X  Y = X  X  Y.
    Proof. unfold_leibniz. apply subseteq_intersection_2. Qed.

649
    Global Instance intersection_idemp_L : IdemP (=@{C}) ().
650
    Proof. intros ?. unfold_leibniz. apply (idemp _). Qed.
651
    Global Instance intersection_comm_L : Comm (=@{C}) ().
652
    Proof. intros ??. unfold_leibniz. apply (comm _). Qed.
653
    Global Instance intersection_assoc_L : Assoc (=@{C}) ().
654
    Proof. intros ???. unfold_leibniz. apply (assoc _). Qed.
655
    Global Instance intersection_empty_l_L: LeftAbsorb (=@{C})  ().
656
    Proof. intros ?. unfold_leibniz. apply (left_absorb _ _). Qed.
657
    Global Instance intersection_empty_r_L: RightAbsorb (=@{C})  ().
658
659
    Proof. intros ?. unfold_leibniz. apply (right_absorb _ _). Qed.

660
    Lemma intersection_singletons_L x : {[x]}  {[x]} = ({[x]} : C).
661
    Proof. unfold_leibniz. apply intersection_singletons. Qed.
662
663
664
665
666

    Lemma union_intersection_l_L X Y Z : X  (Y  Z) = (X  Y)  (X  Z).
    Proof. unfold_leibniz; apply union_intersection_l. Qed.
    Lemma union_intersection_r_L X Y Z : (X  Y)  Z = (X  Z)  (Y  Z).
    Proof. unfold_leibniz; apply union_intersection_r. Qed.
Robbert Krebbers's avatar
Robbert Krebbers committed
667
    Lemma intersection_union_l_L X Y Z : X  (Y  Z) = (X  Y)  (X  Z).
668
    Proof. unfold_leibniz; apply intersection_union_l. Qed.
Robbert Krebbers's avatar
Robbert Krebbers committed
669
    Lemma intersection_union_r_L X Y Z : (X  Y)  Z = (X  Z)  (Y  Z).
670
671
672
    Proof. unfold_leibniz; apply intersection_union_r. Qed.

    (** Difference *)
673
674
    Lemma difference_twice_L X Y : (X  Y)  Y = X  Y.
    Proof. unfold_leibniz. apply difference_twice. Qed.
675
676
    Lemma subseteq_empty_difference_L X Y : X  Y  X  Y = .
    Proof. unfold_leibniz. apply subseteq_empty_difference. Qed.
677
678
    Lemma difference_diag_L X : X  X = .
    Proof. unfold_leibniz. apply difference_diag. Qed.
679
680
    Lemma difference_empty_L X : X   = X.
    Proof. unfold_leibniz. apply difference_empty. Qed.
681
682
    Lemma difference_union_distr_l_L X Y Z : (X  Y)  Z = X  Z  Y  Z.
    Proof. unfold_leibniz. apply difference_union_distr_l. Qed.
Robbert Krebbers's avatar
Robbert Krebbers committed
683
684
    Lemma difference_union_distr_r_L X Y Z : Z  (X  Y) = (Z  X)  (Z  Y).
    Proof. unfold_leibniz. apply difference_union_distr_r. Qed.
685
686
687
    Lemma difference_intersection_distr_l_L X Y Z :
      (X  Y)  Z = X  Z  Y  Z.
    Proof. unfold_leibniz. apply difference_intersection_distr_l. Qed.
688
    Lemma difference_disjoint_L X Y : X ## Y  X  Y = X.
689
    Proof. unfold_leibniz. apply difference_disjoint. Qed.
690
691

    (** Disjointness *)
692
    Lemma disjoint_intersection_L X Y : X ## Y  X  Y = .
693
    Proof. unfold_leibniz. apply disjoint_intersection. Qed.
694
695
696
  End leibniz.

  Section dec.
Robbert Krebbers's avatar
Robbert Krebbers committed
697
    Context `{!RelDecision (@{C})}.
698
    Lemma not_elem_of_intersection x X Y : x  X  Y  x  X  x  Y.
699
    Proof. rewrite elem_of_intersection. destruct (decide (x  X)); tauto. Qed.
700
    Lemma not_elem_of_difference x X Y : x  X  Y  x  X  x  Y.
701
    Proof. rewrite elem_of_difference. destruct (decide (x  Y)); tauto. Qed.
702
703
    Lemma union_difference X Y : X  Y  Y  X  Y  X.
    Proof.
704
      intros ? x; split; rewrite !elem_of_union, elem_of_difference; [|intuition].
705
      destruct (decide (x  X)); intuition.
706
    Qed.
707
708
709
710
711
    Lemma difference_union X Y : X  Y  Y  X  Y.
    Proof.
      intros x. rewrite !elem_of_union; rewrite elem_of_difference.
      split; [ | destruct (decide (x  Y)) ]; intuition.
    Qed.
712
    Lemma subseteq_disjoint_union X Y : X  Y   Z, Y  X  Z  X ## Z.
713
714
715
716
    Proof.
      split; [|set_solver].
      exists (Y  X); split; [auto using union_difference|set_solver].
    Qed.
717
    Lemma non_empty_difference X Y : X  Y  Y  X  .
718
    Proof. intros [HXY1 HXY2] Hdiff. destruct HXY2. set_solver. Qed.
719
    Lemma empty_difference_subseteq X Y : X  Y    X  Y.
720
    Proof. set_solver. Qed.
721
722
723
724
    Lemma singleton_union_difference X Y x :
      {[x]}  (X  Y)  ({[x]}  X)  (Y  {[x]}).
    Proof.
      intro y; split; intros Hy; [ set_solver | ].
725
      destruct (decide (y  ({[x]} : C))); set_solver.
726
    Qed.
727

728
729
730
    Context `{!LeibnizEquiv C}.
    Lemma union_difference_L X Y : X  Y  Y = X  Y  X.
    Proof. unfold_leibniz. apply union_difference. Qed.
731
732
    Lemma difference_union_L X Y : X  Y  Y = X  Y.
    Proof. unfold_leibniz. apply difference_union. Qed.
733
734
    Lemma non_empty_difference_L X Y : X  Y  Y  X  .
    Proof. unfold_leibniz. apply non_empty_difference. Qed.
735
736
    Lemma empty_difference_subseteq_L X Y : X  Y =   X  Y.
    Proof. unfold_leibniz. apply empty_difference_subseteq. Qed.
737
    Lemma subseteq_disjoint_union_L X Y : X  Y   Z, Y = X  Z  X ## Z.
738
    Proof. unfold_leibniz. apply subseteq_disjoint_union. Qed.
739
740
741
    Lemma singleton_union_difference_L X Y x :
      {[x]}  (X  Y) = ({[x]}  X)  (Y  {[x]}).
    Proof. unfold_leibniz. apply singleton_union_difference. Qed.
742
743
744
  End dec.
End collection.

745
746
747
748
749
750
751
752
753

(** * Conversion of option and list *)
Definition of_option `{Singleton A C, Empty C} (mx : option A) : C :=
  match mx with None =>  | Some x => {[ x ]} end.
Fixpoint of_list `{Singleton A C, Empty C, Union C} (l : list A) : C :=
  match l with [] =>  | x :: l => {[ x ]}  of_list l end.

Section of_option_list.
  Context `{SimpleCollection A C}.
Robbert Krebbers's avatar
Robbert Krebbers committed
754
755
  Implicit Types l : list A.

756
  Lemma elem_of_of_option (x : A) mx: x  of_option (C:=C) mx  mx = Some x.
757
  Proof. destruct mx; set_solver. Qed.
758
  Lemma not_elem_of_of_option (x : A) mx: x  of_option (C:=C) mx  mx  Some x.
Robbert Krebbers's avatar
Robbert Krebbers committed
759
760
  Proof. by rewrite elem_of_of_option. Qed.

761
  Lemma elem_of_of_list (x : A) l : x  of_list (C:=C) l  x  l.
762
763
764
765
766
767
  Proof.
    split.
    - induction l; simpl; [by rewrite elem_of_empty|].
      rewrite elem_of_union,elem_of_singleton; intros [->|?]; constructor; auto.
    - induction 1; simpl; rewrite elem_of_union, elem_of_singleton; auto.
  Qed.
768
  Lemma not_elem_of_of_list (x : A) l : x  of_list (C:=C) l  x  l.
Robbert Krebbers's avatar
Robbert Krebbers committed
769
770
  Proof. by rewrite elem_of_of_list. Qed.

771
  Global Instance set_unfold_of_option (mx : option A) x :