diff --git a/guides/sets.v b/guides/sets.v new file mode 100644 index 0000000000000000000000000000000000000000..33397b405a7e5106b50b8029488484b175167e13 --- /dev/null +++ b/guides/sets.v @@ -0,0 +1,99 @@ +From stdpp Require Import gmap sorting. + +(* [gset K] is the type of sets you probably want to use. It enjoys good +properties w.r.t. computation (most operations are logarithmic or linear) and +equality. It works for any type [K] that is countable (see type class +[Countable]). There are [Countable] instances for all the usual types, [nat], +[list nat], [nat * nat], [gset nat], etc. *) + +Check gset. + +(* All the set operations are overloaded via type classes, but there are +instances for [gset]. The most important operations are: + +- [elem_of], notation [∈] +- [subseteq], notation [⊆] +- [subset], notation [⊂] +- [empty], notation [∅] +- [singleton], notation [ {[ x ]} ] +- [union], notation [∪] +- [intersection], notation [∩] +- [difference], notation [∖] +*) + +(* Let us try to type check some stuff. *) + +Check {[ 10 ]} : gset nat. + +Check {[ [10] ]} : gset (list nat). + +Check {[ {[ 10 ]} ]} : gset (gset nat). + +Check (λ X : gset nat, X ∪ {[ 10 ]}). + +(** And let write some lemmas. The most useful tactic is [set_solver]. *) + +Lemma some_stuff (X Y Z : gset nat) : + X ∪ Y ∩ X ∪ Z ∩ X = (Y ∪ X ∪ Z ∖ ∅ ∪ X) ∩ X. +Proof. set_solver. Qed. + +Lemma some_stuff_poly `{Countable A} (X Y Z : gset nat) : + X ∪ Y ∩ X ∪ Z ∩ X = (Y ∪ X ∪ Z ∖ ∅ ∪ X) ∩ X. +Proof. set_solver. Qed. + +(** If you want to search for lemmas, search for the operations, not [gset] +since all lemmas are overloaded. *) + +Search difference intersection. + +(** Some important notes: + +- The lemmas look a bit dounting because of the additional arguments due to + type classes, but these arguments can mostly be ignored +- There are both lemmas about Leibniz equality [=] and setoid equality [≡]. + The first ones are suffixed [_L]. For [gset] you always want to use [=] (and + thus the [_L] lemmas) because we have [X ≡ Y ↔ X = Y]. This is not the case + for other implementations of sets, like [propset A := A → Prop] or + [listset A := list A], hence [≡] is useful in the general case. *) + +(** Some other examples *) + +Definition evens (X : gset nat) : gset nat := + filter (λ x, (2 | x)) X. +Definition intersection_alt (X Y : gset nat) : gset nat := + filter (.∈ Y) X. +Definition add_one (X : gset nat) : gset nat := + set_map S X. +Definition until_n (n : nat) : gset nat := + set_seq 0 n. + +(** Keep in mind that [filter], [set_map], [set_seq], etc are overloaded via +type classes. So, you need sufficient type information in your definitions and +you won't find much about them when searching for [gset]. *) + +(** When computing with sets, always make sure to cast the result that you want +to display is a simple type like [nat], [list nat], [bool], etc. The result +of a [gset] computation is a big sigma type with lots of noise, so it won't be +pretty (or useful) to look at. *) + +Eval vm_compute in (elements (add_one (evens {[ 10; 11; 14 ]}))). +Eval vm_compute in (elements (evens (until_n 40))). +(** [elements] converts a set to a list. They are not sorted, but you can do +that yourself. *) +Eval vm_compute in (merge_sort (≤) (elements (evens (until_n 40)))). +Eval vm_compute in (fresh ({[ 10; 12 ]} : gset nat)). +Eval vm_compute in (size ({[ 10; 12 ]} : gset nat)). +(** You can use [bool_decide] to turn decidable [Prop]s into [bool]s. *) +Eval vm_compute in bool_decide (10 ∈ evens {[ 10; 11 ]}). +Eval vm_compute in (bool_decide ({[ 10; 14; 17 ]} ⊂ until_n 40)). +Eval vm_compute in (bool_decide (set_Forall (λ x, (2 | x)) (evens (until_n 40)))). + +(** Want to know more: + +- Look up the definitions of the type classes for [union], [intersection], etc., + interfaces [SimpleSet], [Set_], etc. in [theories/base.v]. +- Look up the generic theory of sets in [theories/sets.v]. +- Look up the generic theory of finite sets in [theories/fin_sets.v]. +- Probably don't look into the implementation of [gset] in [theories/gmap.v], + unless you are very interested in encodings as bit strings and radix-2 search + trees. You should treat [gset] as a black box. *)