-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathListSetExtras.v
701 lines (636 loc) · 19.4 KB
/
ListSetExtras.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
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
92
93
94
95
96
97
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
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
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
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
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
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
From VLSM.Lib Require Import Itauto.
From stdpp Require Import prelude.
From VLSM.Lib Require Import Preamble ListExtras StdppExtras StdppListSet.
(** * Utility: List Set Definitions and Results *)
Definition set_eq {A} (s1 s2 : set A) : Prop :=
s1 ⊆ s2 /\ s2 ⊆ s1.
(**
By declaring [set_eq] an [Equivalence] relation, we enable rewriting with
it using the rewrite tactic. See the Coq reference manual for details:
https://coq.inria.fr/refman/addendum/generalized-rewriting.html
(section "Declaring rewrite relations", subsection "First class setoids and morphisms").
*)
#[export] Instance Equivalence_set_eq {A : Type} : Equivalence (@set_eq A).
Proof. by firstorder. Qed.
#[export] Instance set_eq_dec `{EqDecision A} : RelDecision (@set_eq A).
Proof.
by intros s1 s2; typeclasses eauto.
Qed.
Lemma set_eq_extract_forall
{A : Type}
(l1 l2 : set A)
: set_eq l1 l2 <-> forall a, (a ∈ l1 <-> a ∈ l2).
Proof.
by unfold set_eq; firstorder.
Qed.
Lemma set_eq_fin_set `{FinSet A Cm} (s1 s2 : Cm) :
s1 ≡ s2 <-> set_eq (elements s1) (elements s2).
Proof.
by rewrite set_eq_extract_forall, set_equiv; setoid_rewrite elem_of_elements.
Qed.
Lemma set_eq_proj1 {A} : forall (s1 s2 : set A),
set_eq s1 s2 ->
s1 ⊆ s2.
Proof.
by intros s1 s2 [].
Qed.
Lemma set_eq_proj2 {A} : forall (s1 s2 : set A),
set_eq s1 s2 ->
s2 ⊆ s1.
Proof.
by intros s1 s2 [].
Qed.
Lemma set_eq_empty_iff
{A}
: forall (l : list A),
set_eq l [] <-> l = [].
Proof.
split; intros; [| by subst].
destruct l as [| hd tl]; [done |].
destruct H.
specialize (H hd (elem_of_list_here hd tl)).
by inversion H.
Qed.
Lemma set_eq_cons {A} : forall (a : A) (s1 s2 : set A),
set_eq s1 s2 ->
set_eq (a :: s1) (a :: s2).
Proof.
intros a s1 s2 Heq.
rewrite !set_eq_extract_forall in *.
setoid_rewrite elem_of_cons.
by firstorder.
Qed.
Lemma set_eq_Forall
{A : Type}
(s1 s2 : set A)
(H12 : set_eq s1 s2)
(P : A -> Prop)
: Forall P s1 <-> Forall P s2.
Proof.
by rewrite !Forall_forall; firstorder.
Qed.
Lemma set_union_comm `{EqDecision A} : forall (s1 s2 : list A),
set_eq (set_union s1 s2) (set_union s2 s1).
Proof.
by intros s1 s2; split; intro x; rewrite !set_union_iff; itauto.
Qed.
Lemma set_union_empty `{EqDecision A} : forall (s1 s2 : list A),
set_union s1 s2 = [] ->
s1 = [] /\ s2 = [].
Proof.
intros.
destruct s2; [done |].
by cbn in H; apply set_add_not_empty in H.
Qed.
Lemma set_union_nodup_left `{EqDecision A} (l l' : set A)
: NoDup l -> NoDup (set_union l l').
Proof.
intro Hl.
induction l' as [| x' l' IH]; [done |].
by apply set_add_nodup.
Qed.
Lemma set_union_subseteq_left `{EqDecision A} : forall (s1 s2 : list A),
s1 ⊆ set_union s1 s2.
Proof.
by intros; intros x H; apply set_union_intro; left.
Qed.
Lemma set_union_subseteq_right `{EqDecision A} : forall (s1 s2 : list A),
s2 ⊆ set_union s1 s2.
Proof.
by intros; intros x H; apply set_union_intro; right.
Qed.
Lemma set_union_subseteq_iff `{EqDecision A} : forall (s1 s2 s : list A),
set_union s1 s2 ⊆ s <-> s1 ⊆ s /\ s2 ⊆ s.
Proof.
intros.
unfold subseteq, list_subseteq.
setoid_rewrite set_union_iff.
by firstorder.
Qed.
Lemma set_union_iterated_nodup `{EqDecision A}
(ss : list (list A))
(H : forall s, s ∈ ss -> NoDup s) :
NoDup (fold_right set_union [] ss).
Proof.
induction ss; cbn.
- by apply NoDup_nil.
- apply set_union_nodup.
+ by apply H; left.
+ by apply IHss; intros; apply H; right.
Qed.
Lemma set_union_in_iterated
`{EqDecision A}
(ss : list (set A))
(a : A)
: a ∈ fold_right set_union [] ss <-> Exists (fun s => a ∈ s) ss.
Proof.
rewrite Exists_exists.
induction ss; split; simpl.
- by intro H; inversion H.
- by intros (x & Hin & _); inversion Hin.
- intro Hin; apply set_union_iff in Hin as [Hina0 | Hinss].
+ by exists a0; rewrite elem_of_cons; split; [left |].
+ apply IHss in Hinss as (x & Hinss & Hinx).
by setoid_rewrite elem_of_cons; eauto.
- rewrite set_union_iff.
intros (x & Hx & Ha).
apply elem_of_cons in Hx as [-> |].
+ by left.
+ by right; apply IHss; exists x.
Qed.
Lemma set_union_iterated_subseteq
`{EqDecision A}
(ss ss' : list (set A))
(Hincl : ss ⊆ ss') :
fold_right set_union [] ss ⊆
fold_right set_union [] ss'.
Proof.
intros a H.
apply set_union_in_iterated in H.
apply set_union_in_iterated.
rewrite Exists_exists in *.
destruct H as [x [Hx Ha]].
exists x.
by split; [apply Hincl |].
Qed.
Lemma set_union_empty_left `{EqDecision A} : forall (s : list A),
NoDup s -> set_eq (set_union [] s) s.
Proof.
intros. split; intros x Hin.
- by apply set_union_elim in Hin as []; [inversion H0 |].
- by apply set_union_intro; right.
Qed.
Lemma map_list_subseteq {A B} : forall (f : B -> A) (s s' : list B),
s ⊆ s' -> map f s ⊆ map f s'.
Proof.
intro f; induction s; intros; simpl.
- by apply list_subseteq_nil.
- assert (Hs : s ⊆ s') by (intros b Hs; apply H; right; done).
specialize (IHs s' Hs).
intros b Hs'.
apply elem_of_cons in Hs' as [-> |]; [| by apply IHs].
by apply elem_of_list_fmap_1, H; left.
Qed.
Lemma map_set_eq {A B} (f : B -> A) : forall s s',
set_eq s s' ->
set_eq (map f s) (map f s').
Proof.
by split; apply map_list_subseteq; apply H.
Qed.
Lemma set_map_nodup {A B} `{EqDecision A} (f : B -> A) : forall (s : set B),
NoDup (set_map f s).
Proof.
induction s; simpl; try constructor.
by apply set_add_nodup.
Qed.
Lemma set_map_elem_of {A B} `{EqDecision A} (f : B -> A) : forall x s,
x ∈ s ->
f x ∈ set_map f s.
Proof.
induction s; intros; inversion H; subst; clear H; simpl.
- by apply set_add_intro2.
- by apply set_add_intro1, IHs.
Qed.
Lemma set_map_exists {A B} `{EqDecision A} (f : B -> A) : forall y s,
y ∈ set_map f s <->
exists x, x ∈ s /\ f x = y.
Proof.
induction s; split; intros; cbn in *.
- by inversion H.
- by destruct H as (x & Hx & Hf); inversion Hx.
- apply set_add_iff in H as [Heq | Hin]; subst.
+ by exists a; split; [left |].
+ apply IHs in Hin as (x & Hin & Heq); subst.
by exists x; split; [right |].
- destruct H as [x [Hx Hf]]; subst; simpl; apply set_add_iff.
apply elem_of_cons in Hx as [-> |].
+ by left.
+ by right; apply IHs; exists x.
Qed.
Lemma set_map_subseteq {A B} `{EqDecision A} (f : B -> A) : forall s s',
s ⊆ s' ->
set_map f s ⊆ set_map f s'.
Proof.
induction s; cbn; intros s' Hsub msg Hin; [by inversion Hin |].
apply set_add_elim in Hin as [-> |].
- by apply set_map_elem_of, Hsub; left.
- apply IHs; [| done].
by intros x Hin'; apply Hsub; right.
Qed.
Lemma set_map_eq {A B} `{EqDecision A} (f : B -> A) : forall s s',
set_eq s s' ->
set_eq (set_map f s) (set_map f s').
Proof.
by split; destruct H; apply set_map_subseteq.
Qed.
Lemma set_map_singleton {A B} `{EqDecision A} (f : B -> A) : forall s a,
set_map f s = [a] ->
forall b, b ∈ s -> f b = a.
Proof.
intros s a H b H0.
apply (set_map_elem_of f) in H0.
rewrite H in H0.
by apply elem_of_cons in H0 as []; [| inversion H0].
Qed.
Lemma filter_set_add `{EqDecision X} P
`{forall (x : X), Decision (P x)} :
forall (l : list X) x, ~ P x ->
filter P l = filter P (set_add x l).
Proof.
induction l as [| hd tl IHl]; intros x H_false; cbn.
- by rewrite decide_False.
- destruct (decide (x = hd)); cbn; [done |].
by destruct (decide (P hd)); rewrite <- IHl.
Qed.
Lemma set_add_ignore `{EqDecision X} :
forall (l : list X) (x : X),
x ∈ l ->
set_add x l = l.
Proof.
induction l as [| hd tl IHl]; inversion 1; subst; cbn.
- by rewrite decide_True.
- by case_decide; [| rewrite IHl].
Qed.
Lemma set_add_new `{EqDecision A} :
forall (x : A) l, x ∉ l -> set_add x l = l++[x].
Proof.
induction l; cbn; [done |]; intros H_not_in.
rewrite decide_False; cycle 1.
- by intros ->; apply H_not_in; left.
- by rewrite elem_of_cons in H_not_in; rewrite IHl; itauto.
Qed.
Lemma set_remove_not_elem_of `{EqDecision A} : forall x (s : list A),
x ∉ s ->
set_remove x s = s.
Proof.
induction s; cbn; intros; [done |].
rewrite decide_False; cycle 1.
- by intros ->; contradict H; left.
- rewrite IHs; [done |].
by rewrite elem_of_cons in H; itauto.
Qed.
Lemma set_remove_elim `{EqDecision A} : forall x (s : list A),
NoDup s -> x ∉ set_remove x s.
Proof.
by intros x s HND Hnelem; apply set_remove_iff in Hnelem; itauto.
Qed.
Lemma set_remove_first `{EqDecision A} : forall x y (s : list A),
x = y -> set_remove x (y :: s) = s.
Proof.
by intros x y s ->; cbn; rewrite decide_True.
Qed.
Lemma set_remove_nodup_1 `{EqDecision A} : forall x (s : list A),
NoDup (set_remove x s) ->
x ∉ set_remove x s ->
NoDup s.
Proof.
induction s; intros; [by constructor |].
simpl in H0; destruct (decide (x = a)); subst.
- by cbn in H; rewrite decide_True in H; constructor.
- rewrite elem_of_cons in H0.
simpl in H; rewrite decide_False in H by done; inversion H; subst; clear H.
constructor; [| by firstorder].
by intro Ha; apply (set_remove_3 _ x) in Ha; auto.
Qed.
Lemma set_remove_elem_of_iff `{EqDecision A} : forall x y (s : list A),
NoDup s ->
y ∈ s ->
x ∈ s <-> x = y \/ x ∈ set_remove y s.
Proof.
intros. split; intros.
- destruct (decide (x = y)).
+ by left.
+ by right; apply set_remove_3.
- destruct H1 as [Heq | Hin].
+ by subst.
+ by apply set_remove_1 in Hin.
Qed.
Lemma set_add_length
`{EqDecision A}
(x : A)
(s : set A)
(Hx : x ∉ s)
: S (length s) = length (set_add x s).
Proof.
revert x Hx.
induction s; cbn; intros; [done |].
destruct (decide (x = a)); [by subst; elim Hx; left |].
cbn; f_equal.
by apply IHs; intro Hs; apply Hx; right.
Qed.
Lemma set_remove_length
`{EqDecision A}
(x : A)
(s : set A)
(Hx : x ∈ s)
: length s = S (length (set_remove x s)).
Proof.
generalize dependent x. induction s; intros; inversion Hx; subst.
- by rewrite set_remove_first.
- by cbn; destruct (decide (x = a)); [| cbn; rewrite <- IHs].
Qed.
Lemma set_eq_remove `{EqDecision A} : forall x (s1 s2 : list A),
NoDup s1 ->
NoDup s2 ->
set_eq s1 s2 ->
set_eq (set_remove x s1) (set_remove x s2).
Proof.
intros x s1 s2 HND1 HND2 [].
by split; intros a Hin; rewrite set_remove_iff in *; itauto.
Qed.
Lemma subseteq_remove_union `{EqDecision A} : forall x (s1 s2 : list A),
NoDup s1 ->
NoDup s2 ->
set_remove x (set_union s1 s2) ⊆
set_union s1 (set_remove x s2).
Proof.
intros. intros y Hin. apply set_remove_iff in Hin.
- apply set_union_intro. destruct Hin. apply set_union_elim in H1.
by rewrite set_remove_iff; itauto.
- by apply set_union_nodup.
Qed.
Lemma set_eq_remove_union_elem_of `{EqDecision A} : forall x (s1 s2 : list A),
NoDup s1 ->
NoDup s2 ->
x ∈ s1 ->
set_eq (set_union s1 (set_remove x s2)) (set_union s1 s2).
Proof.
split; intros msg Hin; apply set_union_iff; apply set_union_iff in Hin
; destruct Hin; try by left.
- by apply set_remove_iff in H2; itauto.
- destruct (decide (msg = x)); subst.
+ by left.
+ by right; apply set_remove_iff.
Qed.
Lemma set_eq_remove_union_not_elem_of `{EqDecision A} : forall x (s1 s2 : list A),
NoDup s1 ->
NoDup s2 ->
x ∉ s1 ->
set_eq (set_union s1 (set_remove x s2)) (set_remove x (set_union s1 s2)).
Proof.
intros.
assert (HnodupUs1s2 := H0).
apply (set_union_nodup _ _ H) in HnodupUs1s2.
split; intros msg Hin.
- apply set_remove_iff; [done |].
apply set_union_iff in Hin as []; split.
+ by apply set_union_iff; left.
+ by intro; subst; apply H1.
+ apply set_remove_iff in H2 as []; [| done].
by apply set_union_iff; right.
+ intro; subst.
by apply set_remove_iff in H2; itauto.
- apply set_union_iff.
apply set_remove_iff in Hin as []; [| done].
apply set_union_iff in H2 as []; [by left |].
by right; apply set_remove_iff.
Qed.
Lemma diff_app_nodup `{EqDecision A} : forall (s1 s2 : list A),
NoDup s1 ->
NoDup s2 ->
NoDup (set_diff s1 s2 ++ s2).
Proof.
intros.
apply NoDup_app; split_and!; [| | done].
- by apply set_diff_nodup.
- by intros a; apply (set_diff_elim2 a s1).
Qed.
Lemma add_remove_inverse `{EqDecision X} :
forall (lv : list X) (v : X),
v ∉ lv ->
set_remove v (set_add v lv) = lv.
Proof.
induction lv as [| hd tl IHlv]; cbn; intros.
- by rewrite decide_True.
- rewrite elem_of_cons in H.
destruct (decide (v = hd)) eqn: Heq; subst; cbn; [by itauto |].
by rewrite Heq, IHlv; itauto.
Qed.
Lemma set_union_iterated_empty `{EqDecision A} :
forall ss : list (set A),
(forall s : list A, s ∈ ss -> s = []) -> fold_right set_union [] ss = [].
Proof.
induction ss; [done |]; cbn; intros H.
rewrite IHss; cycle 1.
- by intros s Hel; apply H; right.
- by cbn; apply H; left.
Qed.
(**
For each element <<X>> of <<l1>>, exactly one occurrence of <<X>> is removed
from <<l2>>. If no such occurrence exists, nothing happens.
*)
Definition set_remove_list `{EqDecision A} (l1 l2 : list A) : list A :=
fold_right set_remove l2 l1.
Example set_remove_list1 : set_remove_list [3; 1; 3] [1; 1; 2; 3; 3; 3; 3] = [1; 2; 3; 3].
Proof. done. Qed.
Example set_remove_list2 : set_remove_list [4] [1; 2; 3] = [1; 2; 3].
Proof. done. Qed.
Lemma set_remove_list_1
`{EqDecision A}
(a : A)
(l1 l2 : list A)
(Hin : a ∈ set_remove_list l1 l2) :
a ∈ l2.
Proof.
unfold set_remove_list in Hin.
induction l1.
- by simpl in Hin; itauto.
- by simpl in Hin; apply set_remove_1, IHl1 in Hin.
Qed.
Lemma set_prod_nodup `(s1 : set A) `(s2 : set B) :
NoDup s1 ->
NoDup s2 ->
NoDup (set_prod s1 s2).
Proof.
intros Hs1 H22; induction Hs1; cbn; [by constructor |].
apply NoDup_app; split_and!; [| | done].
- by apply NoDup_fmap; [congruence |].
- intros [a b].
rewrite elem_of_list_fmap, elem_of_list_prod.
by intros [_ [[= -> _] _]] [].
Qed.
(**
An alternative to [set_diff].
Unlike [set_diff], the result may contain
duplicates if the first argument list <<l>> does.
This definition exists to make proving
[len_set_diff_decrease] more convenient,
because [length] of [filter] can be simplified
step by step while doing induction over <<l>>.
*)
Definition set_diff_filter `{EqDecision A} (l r : list A) :=
filter (.∉ r) l.
(**
The characteristic membership property, parallel to
[set_diff_iff].
*)
Lemma set_diff_filter_iff `{EqDecision A} (a : A) l r :
a ∈ set_diff_filter l r <-> a ∈ l /\ a ∉ r.
Proof.
induction l; simpl.
- by cbn; split; intros; [inversion H | itauto].
- unfold set_diff_filter in *.
rewrite filter_cons.
destruct (decide (a0 ∉ r)).
+ rewrite 2 elem_of_cons, IHl.
by split; itauto congruence.
+ rewrite elem_of_cons.
by split; itauto congruence.
Qed.
Lemma set_diff_filter_nodup `{EqDecision A} (l r : list A) :
NoDup l -> NoDup (set_diff_filter l r).
Proof.
by intros H; apply NoDup_filter.
Qed.
(**
Prove that subtracting a superset cannot produce
a smaller result.
This lemma is used to prove [len_set_diff_decrease].
*)
Lemma len_set_diff_incl_le `{EqDecision A} (l a b : list A)
(H_subseteq : forall x, x ∈ b -> x ∈ a) :
length (set_diff_filter l a) <= length (set_diff_filter l b).
Proof.
induction l; [done |].
unfold set_diff_filter.
rewrite 2 filter_cons.
destruct (decide (a0 ∉ a)); destruct (decide (a0 ∉ b)).
- by simpl; unfold set_diff_filter in IHl; lia.
- by itauto.
- by simpl; apply le_S, IHl.
- by apply IHl.
Qed.
(**
Prove that strictly increasing the set to be subtracted,
by adding an element actually found in <<l>> will decrease
the size of the result.
*)
Lemma len_set_diff_decrease `{EqDecision A} (new : A) (l a b : list A)
(H_subseteq : forall x, x ∈ b -> x ∈ a)
(H_new_is_new : new ∈ a /\ new ∉ b)
(H_new_is_relevant : new ∈ l) :
length (set_diff_filter l a) < length (set_diff_filter l b).
Proof.
induction l; [by inversion H_new_is_relevant |];
apply elem_of_cons in H_new_is_relevant; destruct H_new_is_relevant.
- subst a0.
unfold set_diff_filter.
rewrite 2 filter_cons.
destruct (decide (new ∉ a)); [by itauto |].
destruct (decide (new ∉ b)); [| by contradict n0; itauto].
simpl.
by apply le_n_S, len_set_diff_incl_le.
- specialize (IHl H); clear H.
unfold set_diff_filter.
rewrite 2 filter_cons.
destruct (decide (a0 ∉ a)); destruct (decide (a0 ∉ b)).
+ simpl.
rewrite <- Nat.succ_lt_mono.
by apply IHl.
+ contradict n.
apply H_subseteq.
by destruct (decide (a0 ∈ b)).
+ simpl.
apply Nat.lt_lt_succ_r.
by apply IHl.
+ by apply IHl.
Qed.
Lemma len_set_diff_map_set_add `{EqDecision B} (new : B) `{EqDecision A} (f : B -> A)
(a : list B) (l : list A)
(H_new_is_new : f new ∉ map f a)
(H_new_is_relevant : f new ∈ l) :
length (set_diff_filter l (map f (set_add new a))) <
length (set_diff_filter l (map f a)).
Proof.
apply len_set_diff_decrease with (f new); [.. | done].
- intro x. rewrite 2 elem_of_list_fmap.
intros [x0 [Hx0 Hin]]. exists x0.
by rewrite set_add_iff; itauto.
- split; [| done].
apply elem_of_list_fmap_1.
by apply set_add_iff; left.
Qed.
#[export] Instance set_eq_elem_of (A : Type) :
Proper (@eq A ==> @set_eq A ==> iff) elem_of_list.
Proof.
by intros x y -> l1 l2 H; split; apply H.
Qed.
#[export] Instance set_elem_of_subseteq (A : Type) :
Proper (@eq A ==> @list_subseteq A ==> impl) elem_of_list.
Proof. by intros x y -> l1 l2 H; firstorder. Qed.
Lemma set_union_iterated_preserves_prop
`{EqDecision A}
(ss : list (set A))
(P : A -> Prop)
(Hp : forall (s : set A), forall (a : A), (s ∈ ss /\ a ∈ s) -> P a) :
forall (a : A), a ∈ fold_right set_union [] ss -> P a.
Proof.
intros.
apply set_union_in_iterated in H. rewrite Exists_exists in H.
destruct H as [s [Hins Hina]].
apply Hp with (s := s).
by itauto.
Qed.
Lemma filter_set_eq {X} P Q
`{forall (x : X), Decision (P x)} `{forall (x : X), Decision (Q x)}
(l : list X)
(resf := filter P l)
(resg := filter Q l) :
set_eq resf resg -> resf = resg.
Proof.
intros.
unfold resf, resg in *.
apply filter_ext_elem_of. intros.
unfold set_eq in H1.
destruct H1 as [H1 H1'].
specialize (H1 a). specialize (H1' a).
split; intros.
- by eapply elem_of_list_filter, H1, elem_of_list_filter.
- by eapply elem_of_list_filter, H1', elem_of_list_filter.
Qed.
Lemma subseteq_appr : forall A (l m n : list A), l ⊆ n -> l ⊆ m ++ n.
Proof.
intros A l m n x y yinl.
apply x in yinl.
by apply elem_of_app; right.
Qed.
Lemma elem_of_union_fold
`{EqDecision A}
(haystack : list (list A))
(a : A) :
a ∈ fold_right set_union [] haystack
<->
exists (needle : list A), a ∈ needle /\ needle ∈ haystack.
Proof.
split.
- generalize dependent a.
generalize dependent haystack.
induction haystack.
+ by intros; cbn in H; inversion H.
+ intros.
unfold fold_right in H.
rewrite set_union_iff in H.
destruct H.
* by setoid_rewrite elem_of_cons; eauto.
* destruct (IHhaystack a0 H) as (needle & Hin1 & Hin2).
by setoid_rewrite elem_of_cons; eauto.
- generalize dependent a.
generalize dependent haystack.
induction haystack.
+ by cbn; intros a (x & Ha & Hx); inversion Hx.
+ intros a0 (needle & Hin & Hin2).
apply elem_of_cons in Hin2 as [<- |]; cbn.
* by apply set_union_iff; auto.
* apply set_union_iff; right.
apply IHhaystack.
by exists needle.
Qed.
Lemma subseteq_Forall (A : Type) (P : A -> Prop) (l1 l2 : list A) :
l2 ⊆ l1 -> Forall P l1 -> Forall P l2.
Proof.
intros Hsub Hfor.
apply Forall_forall.
rewrite Forall_forall in Hfor.
intros.
by apply Hfor, Hsub.
Qed.