Commit 2f9f3d3f authored by Robbert Krebbers's avatar Robbert Krebbers

Introduce `RelDecision` for decidable relations and define `EqDecision` using it.

This allows for more control over `Hint Mode`.
parent 929d64cc
Pipeline #4486 passed with stages
in 4 minutes
...@@ -150,13 +150,30 @@ Hint Extern 0 (_ ≡ _) => symmetry; assumption. ...@@ -150,13 +150,30 @@ Hint Extern 0 (_ ≡ _) => symmetry; assumption.
(** * Type classes *) (** * Type classes *)
(** ** Decidable propositions *) (** ** Decidable propositions *)
(** This type class by (Spitters/van der Weegen, 2011) collects decidable (** This type class by (Spitters/van der Weegen, 2011) collects decidable
propositions. For example to declare a parameter expressing decidable equality propositions. *)
on a type [A] we write [`{∀ x y : A, Decision (x = y)}] and use it by writing
[decide (x = y)]. *)
Class Decision (P : Prop) := decide : {P} + {¬P}. Class Decision (P : Prop) := decide : {P} + {¬P}.
Hint Mode Decision ! : typeclass_instances. Hint Mode Decision ! : typeclass_instances.
Arguments decide _ {_} : assert. Arguments decide _ {_} : simpl never, assert.
Notation EqDecision A := ( x y : A, Decision (x = y)).
(** Although [RelDecision R] is just [∀ x y, Decision (R x y)], we make this
an explicit class instead of a notation for two reasons:
- It allows us to control [Hint Mode] more precisely. In particular, if it were
defined as a notation, the above [Hint Mode] for [Decision] would not prevent
diverging instance search when looking for [RelDecision (@eq ?A)], which would
result in it looking for [Decision (@eq ?A x y)], i.e. an instance where the
head position of [Decision] is not en evar.
- We use it to avoid inefficient computation due to eager evaluation of
propositions by [vm_compute]. This inefficiency arises for example if
[(x = y) := (f x = f y)]. Since [decide (x = y)] evaluates to
[decide (f x = f y)], this would then lead to evaluation of [f x] and [f y].
Using the [RelDecision], the [f] is hidden under a lambda, which prevents
unnecessary evaluation. *)
Class RelDecision {A B} (R : A B Prop) :=
decide_rel x y :> Decision (R x y).
Hint Mode RelDecision ! ! ! : typeclass_instances.
Arguments decide_rel {_ _} _ {_} _ _ : simpl never, assert.
Notation EqDecision A := (RelDecision (@eq A)).
(** ** Inhabited types *) (** ** Inhabited types *)
(** This type class collects types that are inhabited. *) (** This type class collects types that are inhabited. *)
......
...@@ -29,7 +29,8 @@ Proof. ...@@ -29,7 +29,8 @@ Proof.
- intros X Y x; unfold elem_of, bset_elem_of; simpl. - intros X Y x; unfold elem_of, bset_elem_of; simpl.
destruct (bset_car X x), (bset_car Y x); simpl; tauto. destruct (bset_car X x), (bset_car Y x); simpl; tauto.
Qed. Qed.
Instance bset_elem_of_dec {A} x (X : bset A) : Decision (x X) := _. Instance bset_elem_of_dec {A} : RelDecision (@elem_of _ (bset A) _).
Proof. refine (λ x X, cast_if (decide (bset_car X x))); done. Defined.
Typeclasses Opaque bset_elem_of. Typeclasses Opaque bset_elem_of.
Global Opaque bset_empty bset_singleton bset_union Global Opaque bset_empty bset_singleton bset_union
......
...@@ -190,17 +190,18 @@ Proof. ...@@ -190,17 +190,18 @@ Proof.
intros p; apply eq_bool_prop_intro, (HXY p). intros p; apply eq_bool_prop_intro, (HXY p).
Qed. Qed.
Instance coPset_elem_of_dec (p : positive) (X : coPset) : Decision (p X) := _. Instance coPset_elem_of_dec : RelDecision (@elem_of _ coPset _).
Instance coPset_equiv_dec (X Y : coPset) : Decision (X Y). Proof. solve_decision. Defined.
Proof. refine (cast_if (decide (X = Y))); abstract (by fold_leibniz). Defined. Instance coPset_equiv_dec : RelDecision (@equiv coPset _).
Instance mapset_disjoint_dec (X Y : coPset) : Decision (X Y). Proof. refine (λ X Y, cast_if (decide (X = Y))); abstract (by fold_leibniz). Defined.
Instance mapset_disjoint_dec : RelDecision (@disjoint coPset _).
Proof. Proof.
refine (cast_if (decide (X Y = ))); refine (λ X Y, cast_if (decide (X Y = )));
abstract (by rewrite disjoint_intersection_L). abstract (by rewrite disjoint_intersection_L).
Defined. Defined.
Instance mapset_subseteq_dec (X Y : coPset) : Decision (X Y). Instance mapset_subseteq_dec : RelDecision (@subseteq coPset _).
Proof. Proof.
refine (cast_if (decide (X Y = Y))); abstract (by rewrite subseteq_union_L). refine (λ X Y, cast_if (decide (X Y = Y))); abstract (by rewrite subseteq_union_L).
Defined. Defined.
(** * Top *) (** * Top *)
......
...@@ -527,7 +527,7 @@ Section simple_collection. ...@@ -527,7 +527,7 @@ Section simple_collection.
End leibniz. End leibniz.
Section dec. Section dec.
Context `{ (X Y : C), Decision (X Y)}. Context `{!RelDecision (@equiv C _)}.
Lemma collection_subseteq_inv X Y : X Y X Y X Y. Lemma collection_subseteq_inv X Y : X Y X Y X Y.
Proof. destruct (decide (X Y)); [by right|left;set_solver]. Qed. Proof. destruct (decide (X Y)); [by right|left;set_solver]. Qed.
Lemma collection_not_subset_inv X Y : X Y X Y X Y. Lemma collection_not_subset_inv X Y : X Y X Y X Y.
...@@ -692,7 +692,7 @@ Section collection. ...@@ -692,7 +692,7 @@ Section collection.
End leibniz. End leibniz.
Section dec. Section dec.
Context `{ (x : A) (X : C), Decision (x X)}. Context `{!RelDecision (@elem_of A C _)}.
Lemma not_elem_of_intersection x X Y : x X Y x X x Y. Lemma not_elem_of_intersection x X Y : x X Y x X x Y.
Proof. rewrite elem_of_intersection. destruct (decide (x X)); tauto. Qed. Proof. rewrite elem_of_intersection. destruct (decide (x X)); tauto. Qed.
Lemma not_elem_of_difference x X Y : x X Y x X x Y. Lemma not_elem_of_difference x X Y : x X Y x X x Y.
......
...@@ -10,6 +10,7 @@ Class Countable A `{EqDecision A} := { ...@@ -10,6 +10,7 @@ Class Countable A `{EqDecision A} := {
decode : positive option A; decode : positive option A;
decode_encode x : decode (encode x) = Some x decode_encode x : decode (encode x) = Some x
}. }.
Hint Mode Countable ! - : typeclass_instances.
Arguments encode : simpl never. Arguments encode : simpl never.
Arguments decode : simpl never. Arguments decode : simpl never.
...@@ -36,8 +37,8 @@ Section choice. ...@@ -36,8 +37,8 @@ Section choice.
Context `{Countable A} (P : A Prop). Context `{Countable A} (P : A Prop).
Inductive choose_step: relation positive := Inductive choose_step: relation positive :=
| choose_step_None {p} : decode p = None choose_step (Psucc p) p | choose_step_None {p} : decode (A:=A) p = None choose_step (Psucc p) p
| choose_step_Some {p x} : | choose_step_Some {p} {x : A} :
decode p = Some x ¬P x choose_step (Psucc p) p. decode p = Some x ¬P x choose_step (Psucc p) p.
Lemma choose_step_acc : ( x, P x) Acc choose_step 1%positive. Lemma choose_step_acc : ( x, P x) Acc choose_step 1%positive.
Proof. Proof.
...@@ -320,7 +321,7 @@ Arguments GenNode {_} _ _ : assert. ...@@ -320,7 +321,7 @@ Arguments GenNode {_} _ _ : assert.
Instance gen_tree_dec `{EqDecision T} : EqDecision (gen_tree T). Instance gen_tree_dec `{EqDecision T} : EqDecision (gen_tree T).
Proof. Proof.
refine ( refine (
fix go t1 t2 := fix go t1 t2 := let _ : EqDecision _ := @go in
match t1, t2 with match t1, t2 with
| GenLeaf x1, GenLeaf x2 => cast_if (decide (x1 = x2)) | GenLeaf x1, GenLeaf x2 => cast_if (decide (x1 = x2))
| GenNode n1 ts1, GenNode n2 ts2 => | GenNode n1 ts1, GenNode n2 ts2 =>
......
...@@ -6,8 +6,6 @@ type class. *) ...@@ -6,8 +6,6 @@ type class. *)
From stdpp Require Export proof_irrel. From stdpp Require Export proof_irrel.
Set Default Proof Using "Type*". Set Default Proof Using "Type*".
Hint Extern 200 (Decision _) => progress (lazy beta) : typeclass_instances.
Lemma dec_stable `{Decision P} : ¬¬P P. Lemma dec_stable `{Decision P} : ¬¬P P.
Proof. firstorder. Qed. Proof. firstorder. Qed.
...@@ -16,17 +14,6 @@ Proof. destruct b. left; constructor. right. intros []. Qed. ...@@ -16,17 +14,6 @@ Proof. destruct b. left; constructor. right. intros []. Qed.
Instance: Inj (=) () Is_true. Instance: Inj (=) () Is_true.
Proof. intros [] []; simpl; intuition. Qed. Proof. intros [] []; simpl; intuition. Qed.
(** We introduce [decide_rel] to avoid inefficienct computation due to eager
evaluation of propositions by [vm_compute]. This inefficiency occurs if
[(x = y) := (f x = f y)] as [decide (x = y)] evaluates to [decide (f x = f y)]
which then might lead to evaluation of [f x] and [f y]. Using [decide_rel]
we hide [f] under a lambda abstraction to avoid this unnecessary evaluation. *)
Definition decide_rel {A B} (R : A B Prop) {dec : x y, Decision (R x y)}
(x : A) (y : B) : Decision (R x y) := dec x y.
Lemma decide_rel_correct {A B} (R : A B Prop) `{ x y, Decision (R x y)}
(x : A) (y : B) : decide_rel R x y = decide (R x y).
Proof. reflexivity. Qed.
Lemma decide_True {A} `{Decision P} (x y : A) : Lemma decide_True {A} `{Decision P} (x y : A) :
P (if decide P then x else y) = x. P (if decide P then x else y) = x.
Proof. destruct (decide P); tauto. Qed. Proof. destruct (decide P); tauto. Qed.
...@@ -75,9 +62,10 @@ Ltac solve_trivial_decision := ...@@ -75,9 +62,10 @@ Ltac solve_trivial_decision :=
| |- Decision (?P) => apply _ | |- Decision (?P) => apply _
| |- sumbool ?P (¬?P) => change (Decision P); apply _ | |- sumbool ?P (¬?P) => change (Decision P); apply _
end. end.
Ltac solve_decision := intros; first Ltac solve_decision :=
[ solve_trivial_decision unfold EqDecision; intros; first
| unfold Decision; decide equality; solve_trivial_decision ]. [ solve_trivial_decision
| unfold Decision; decide equality; solve_trivial_decision ].
(** The following combinators are useful to create Decision proofs in (** The following combinators are useful to create Decision proofs in
combination with the [refine] tactic. *) combination with the [refine] tactic. *)
......
...@@ -23,9 +23,9 @@ Implicit Types X Y : C. ...@@ -23,9 +23,9 @@ Implicit Types X Y : C.
Lemma fin_collection_finite X : set_finite X. Lemma fin_collection_finite X : set_finite X.
Proof. by exists (elements X); intros; rewrite elem_of_elements. Qed. Proof. by exists (elements X); intros; rewrite elem_of_elements. Qed.
Instance elem_of_dec_slow (x : A) (X : C) : Decision (x X) | 100. Instance elem_of_dec_slow : RelDecision (@elem_of A C _) | 100.
Proof. Proof.
refine (cast_if (decide_rel () x (elements X))); refine (λ x X, cast_if (decide_rel () x (elements X)));
by rewrite <-(elem_of_elements _). by rewrite <-(elem_of_elements _).
Defined. Defined.
......
...@@ -1238,10 +1238,9 @@ Proof. ...@@ -1238,10 +1238,9 @@ Proof.
destruct (m1 !! i), (m2 !! i); simplify_eq/=; auto; destruct (m1 !! i), (m2 !! i); simplify_eq/=; auto;
by eapply bool_decide_unpack, Hm. by eapply bool_decide_unpack, Hm.
Qed. Qed.
Global Instance map_relation_dec `{ x y, Decision (R x y), x, Decision (P x), Global Instance map_relation_dec : RelDecision (map_relation (M:=M) R P Q).
y, Decision (Q y)} (m1 : M A) (m2 : M B) : Decision (map_relation R P Q m1 m2).
Proof. Proof.
refine (cast_if (decide (map_Forall (λ _, Is_true) (merge f m1 m2)))); refine (λ m1 m2, cast_if (decide (map_Forall (λ _, Is_true) (merge f m1 m2))));
abstract by rewrite map_relation_alt. abstract by rewrite map_relation_alt.
Defined. Defined.
(** Due to the finiteness of finite maps, we can extract a witness if the (** Due to the finiteness of finite maps, we can extract a witness if the
......
...@@ -8,6 +8,7 @@ Class Finite A `{EqDecision A} := { ...@@ -8,6 +8,7 @@ Class Finite A `{EqDecision A} := {
NoDup_enum : NoDup enum; NoDup_enum : NoDup enum;
elem_of_enum x : x enum elem_of_enum x : x enum
}. }.
Hint Mode Finite ! - : typeclass_instances.
Arguments enum : clear implicits. Arguments enum : clear implicits.
Arguments enum _ {_ _} : assert. Arguments enum _ {_ _} : assert.
Arguments NoDup_enum : clear implicits. Arguments NoDup_enum : clear implicits.
......
...@@ -7,18 +7,14 @@ Record gmultiset A `{Countable A} := GMultiSet { gmultiset_car : gmap A nat }. ...@@ -7,18 +7,14 @@ Record gmultiset A `{Countable A} := GMultiSet { gmultiset_car : gmap A nat }.
Arguments GMultiSet {_ _ _} _ : assert. Arguments GMultiSet {_ _ _} _ : assert.
Arguments gmultiset_car {_ _ _} _ : assert. Arguments gmultiset_car {_ _ _} _ : assert.
Lemma gmultiset_eq_dec `{Countable A} : EqDecision (gmultiset A). Instance gmultiset_eq_dec `{Countable A} : EqDecision (gmultiset A).
Proof. solve_decision. Defined. Proof. solve_decision. Defined.
Hint Extern 1 (Decision (@eq (gmultiset _) _ _)) =>
eapply @gmultiset_eq_dec : typeclass_instances.
Program Definition gmultiset_countable `{Countable A} : Program Instance gmultiset_countable `{Countable A} :
Countable (gmultiset A) := {| Countable (gmultiset A) := {|
encode X := encode (gmultiset_car X); decode p := GMultiSet <$> decode p encode X := encode (gmultiset_car X); decode p := GMultiSet <$> decode p
|}. |}.
Next Obligation. intros A ?? [X]; simpl. by rewrite decode_encode. Qed. Next Obligation. intros A ?? [X]; simpl. by rewrite decode_encode. Qed.
Hint Extern 1 (Countable (gmultiset _)) =>
eapply @gmultiset_countable : typeclass_instances.
Section definitions. Section definitions.
Context `{Countable A}. Context `{Countable A}.
...@@ -102,8 +98,8 @@ Proof. ...@@ -102,8 +98,8 @@ Proof.
by split; auto with lia. by split; auto with lia.
- intros X Y x. rewrite !elem_of_multiplicity, multiplicity_union. omega. - intros X Y x. rewrite !elem_of_multiplicity, multiplicity_union. omega.
Qed. Qed.
Global Instance gmultiset_elem_of_dec x X : Decision (x X). Global Instance gmultiset_elem_of_dec : RelDecision (@elem_of _ (gmultiset A) _).
Proof. unfold elem_of, gmultiset_elem_of. apply _. Defined. Proof. refine (λ x X, cast_if (decide (0 < multiplicity x X))); done. Defined.
(* Algebraic laws *) (* Algebraic laws *)
Global Instance gmultiset_comm : Comm (@eq (gmultiset A)) (). Global Instance gmultiset_comm : Comm (@eq (gmultiset A)) ().
...@@ -144,8 +140,9 @@ Qed. ...@@ -144,8 +140,9 @@ Qed.
Lemma gmultiset_elements_empty_inv X : elements X = [] X = . Lemma gmultiset_elements_empty_inv X : elements X = [] X = .
Proof. Proof.
destruct X as [X]; unfold elements, gmultiset_elements; simpl. destruct X as [X]; unfold elements, gmultiset_elements; simpl.
intros; apply (f_equal GMultiSet). destruct (map_to_list X) intros; apply (f_equal GMultiSet). destruct (map_to_list X) as [|[]] eqn:?.
as [|[]] eqn:?; naive_solver eauto using map_to_list_empty_inv. - by apply map_to_list_empty_inv.
- naive_solver.
Qed. Qed.
Lemma gmultiset_elements_empty' X : elements X = [] X = . Lemma gmultiset_elements_empty' X : elements X = [] X = .
Proof. Proof.
...@@ -249,9 +246,9 @@ Proof. ...@@ -249,9 +246,9 @@ Proof.
apply forall_proper; intros x. unfold multiplicity. apply forall_proper; intros x. unfold multiplicity.
destruct (gmultiset_car X !! x), (gmultiset_car Y !! x); naive_solver omega. destruct (gmultiset_car X !! x), (gmultiset_car Y !! x); naive_solver omega.
Qed. Qed.
Global Instance gmultiset_subseteq_dec X Y : Decision (X Y). Global Instance gmultiset_subseteq_dec : RelDecision (@subseteq (gmultiset A) _).
Proof. Proof.
refine (cast_if (decide (map_relation () refine (λ X Y, cast_if (decide (map_relation ()
(λ _, False) (λ _, True) (gmultiset_car X) (gmultiset_car Y)))); (λ _, False) (λ _, True) (gmultiset_car X) (gmultiset_car Y))));
by rewrite gmultiset_subseteq_alt. by rewrite gmultiset_subseteq_alt.
Defined. Defined.
......
...@@ -311,13 +311,13 @@ Instance list_subseteq {A} : SubsetEq (list A) := λ l1 l2, ∀ x, x ∈ l1 → ...@@ -311,13 +311,13 @@ Instance list_subseteq {A} : SubsetEq (list A) := λ l1 l2, ∀ x, x ∈ l1 →
Section list_set. Section list_set.
Context `{dec : EqDecision A}. Context `{dec : EqDecision A}.
Global Instance elem_of_list_dec (x : A) : l : list A, Decision (x l). Global Instance elem_of_list_dec : RelDecision (@elem_of A (list A) _).
Proof. Proof.
refine ( refine (
fix go l := fix go x l :=
match l return Decision (x l) with match l return Decision (x l) with
| [] => right _ | [] => right _
| y :: l => cast_if_or (decide (x = y)) (go l) | y :: l => cast_if_or (decide (x = y)) (go x l)
end); clear go dec; subst; try (by constructor); abstract by inversion 1. end); clear go dec; subst; try (by constructor); abstract by inversion 1.
Defined. Defined.
Fixpoint remove_dups (l : list A) : list A := Fixpoint remove_dups (l : list A) : list A :=
...@@ -1505,9 +1505,9 @@ Proof. ...@@ -1505,9 +1505,9 @@ Proof.
- intros ?. by eexists []. - intros ?. by eexists [].
- intros ???[k1->] [k2->]. exists (k2 ++ k1). by rewrite (assoc_L (++)). - intros ???[k1->] [k2->]. exists (k2 ++ k1). by rewrite (assoc_L (++)).
Qed. Qed.
Global Instance prefix_dec `{!EqDecision A} : l1 l2, Global Instance prefix_dec `{!EqDecision A} : RelDecision prefix :=
Decision (l1 `prefix_of` l2) := fix go l1 l2 := fix go l1 l2 :=
match l1, l2 return { l1 `prefix_of` l2 } + { ¬l1 `prefix_of` l2 } with match l1, l2 with
| [], _ => left (prefix_nil _) | [], _ => left (prefix_nil _)
| _, [] => right (prefix_nil_not _ _) | _, [] => right (prefix_nil_not _ _)
| x :: l1, y :: l2 => | x :: l1, y :: l2 =>
...@@ -1639,10 +1639,9 @@ Lemma suffix_length l1 l2 : l1 `suffix_of` l2 → length l1 ≤ length l2. ...@@ -1639,10 +1639,9 @@ Lemma suffix_length l1 l2 : l1 `suffix_of` l2 → length l1 ≤ length l2.
Proof. intros [? ->]. rewrite app_length. lia. Qed. Proof. intros [? ->]. rewrite app_length. lia. Qed.
Lemma suffix_cons_not x l : ¬x :: l `suffix_of` l. Lemma suffix_cons_not x l : ¬x :: l `suffix_of` l.
Proof. intros [??]. discriminate_list. Qed. Proof. intros [??]. discriminate_list. Qed.
Global Instance suffix_dec `{!EqDecision A} l1 l2 : Global Instance suffix_dec `{!EqDecision A} : RelDecision (@suffix A).
Decision (l1 `suffix_of` l2).
Proof. Proof.
refine (cast_if (decide_rel prefix (reverse l1) (reverse l2))); refine (λ l1 l2, cast_if (decide_rel prefix (reverse l1) (reverse l2)));
abstract (by rewrite suffix_prefix_reverse). abstract (by rewrite suffix_prefix_reverse).
Defined. Defined.
...@@ -2087,14 +2086,14 @@ Section submseteq_dec. ...@@ -2087,14 +2086,14 @@ Section submseteq_dec.
destruct (list_remove x l2) as [k'|] eqn:?; intros; simplify_eq. destruct (list_remove x l2) as [k'|] eqn:?; intros; simplify_eq.
rewrite submseteq_cons_l. eauto using list_remove_Some. rewrite submseteq_cons_l. eauto using list_remove_Some.
Qed. Qed.
Global Instance submseteq_dec l1 l2 : Decision (l1 + l2). Global Instance submseteq_dec : RelDecision (submseteq : relation (list A)).
Proof. Proof.
refine (cast_if (decide (is_Some (list_remove_list l1 l2)))); refine (λ l1 l2, cast_if (decide (is_Some (list_remove_list l1 l2))));
abstract (rewrite list_remove_list_submseteq; tauto). abstract (rewrite list_remove_list_submseteq; tauto).
Defined. Defined.
Global Instance Permutation_dec l1 l2 : Decision (l1 l2). Global Instance Permutation_dec : RelDecision (Permutation : relation (list A)).
Proof. Proof.
refine (cast_if_and refine (λ l1 l2, cast_if_and
(decide (length l1 = length l2)) (decide (l1 + l2))); (decide (length l1 = length l2)) (decide (l1 + l2)));
abstract (rewrite Permutation_alt; tauto). abstract (rewrite Permutation_alt; tauto).
Defined. Defined.
...@@ -2621,7 +2620,7 @@ Section Forall2. ...@@ -2621,7 +2620,7 @@ Section Forall2.
Qed. Qed.
Global Instance Forall2_dec `{dec : x y, Decision (P x y)} : Global Instance Forall2_dec `{dec : x y, Decision (P x y)} :
l k, Decision (Forall2 P l k). RelDecision (Forall2 P).
Proof. Proof.
refine ( refine (
fix go l k : Decision (Forall2 P l k) := fix go l k : Decision (Forall2 P l k) :=
......
...@@ -76,18 +76,18 @@ Section deciders. ...@@ -76,18 +76,18 @@ Section deciders.
match X1, X2 with Mapset m1, Mapset m2 => cast_if (decide (m1 = m2)) end); match X1, X2 with Mapset m1, Mapset m2 => cast_if (decide (m1 = m2)) end);
abstract congruence. abstract congruence.
Defined. Defined.
Global Instance mapset_equiv_dec (X1 X2 : mapset M) : Decision (X1 X2) | 1. Global Instance mapset_equiv_dec : RelDecision (@equiv (mapset M)_) | 1.
Proof. refine (cast_if (decide (X1 = X2))); abstract (by fold_leibniz). Defined. Proof. refine (λ X1 X2, cast_if (decide (X1 = X2))); abstract (by fold_leibniz). Defined.
Global Instance mapset_elem_of_dec x (X : mapset M) : Decision (x X) | 1. Global Instance mapset_elem_of_dec : RelDecision (@elem_of _ (mapset M) _) | 1.
Proof. solve_decision. Defined. Proof. refine (λ x X, cast_if (decide (mapset_car X !! x = Some ()))); done. Defined.
Global Instance mapset_disjoint_dec (X1 X2 : mapset M) : Decision (X1 X2). Global Instance mapset_disjoint_dec : RelDecision (@disjoint (mapset M) _).
Proof. Proof.
refine (cast_if (decide (X1 X2 = ))); refine (λ X1 X2, cast_if (decide (X1 X2 = )));
abstract (by rewrite disjoint_intersection_L). abstract (by rewrite disjoint_intersection_L).
Defined. Defined.
Global Instance mapset_subseteq_dec (X1 X2 : mapset M) : Decision (X1 X2). Global Instance mapset_subseteq_dec : RelDecision (@subseteq (mapset M) _).
Proof. Proof.
refine (cast_if (decide (X1 X2 = X2))); refine (λ X1 X2, cast_if (decide (X1 X2 = X2)));
abstract (by rewrite subseteq_union_L). abstract (by rewrite subseteq_union_L).
Defined. Defined.
End deciders. End deciders.
......
...@@ -36,8 +36,8 @@ Infix "`max`" := Nat.max (at level 35) : nat_scope. ...@@ -36,8 +36,8 @@ Infix "`max`" := Nat.max (at level 35) : nat_scope.
Infix "`min`" := Nat.min (at level 35) : nat_scope. Infix "`min`" := Nat.min (at level 35) : nat_scope.
Instance nat_eq_dec: EqDecision nat := eq_nat_dec. Instance nat_eq_dec: EqDecision nat := eq_nat_dec.
Instance nat_le_dec: x y : nat, Decision (x y) := le_dec. Instance nat_le_dec: RelDecision le := le_dec.
Instance nat_lt_dec: x y : nat, Decision (x < y) := lt_dec. Instance nat_lt_dec: RelDecision lt := lt_dec.
Instance nat_inhabited: Inhabited nat := populate 0%nat. Instance nat_inhabited: Inhabited nat := populate 0%nat.
Instance S_inj: Inj (=) (=) S. Instance S_inj: Inj (=) (=) S.
Proof. by injection 1. Qed. Proof. by injection 1. Qed.
...@@ -77,9 +77,9 @@ Proof. intros. destruct (Nat_mul_split_l n x2 x1 y2 y1); auto with lia. Qed. ...@@ -77,9 +77,9 @@ Proof. intros. destruct (Nat_mul_split_l n x2 x1 y2 y1); auto with lia. Qed.
Notation lcm := Nat.lcm. Notation lcm := Nat.lcm.
Notation divide := Nat.divide. Notation divide := Nat.divide.
Notation "( x | y )" := (divide x y) : nat_scope. Notation "( x | y )" := (divide x y) : nat_scope.
Instance Nat_divide_dec x y : Decision (x | y). Instance Nat_divide_dec : RelDecision Nat.divide.
Proof. Proof.
refine (cast_if (decide (lcm x y = y))); by rewrite Nat.divide_lcm_iff. refine (λ x y, cast_if (decide (lcm x y = y))); by rewrite Nat.divide_lcm_iff.
Defined. Defined.
Instance: PartialOrder divide. Instance: PartialOrder divide.
Proof. Proof.
...@@ -130,6 +130,10 @@ Arguments Pos.of_nat : simpl never. ...@@ -130,6 +130,10 @@ Arguments Pos.of_nat : simpl never.
Arguments Pmult : simpl never. Arguments Pmult : simpl never.
Instance positive_eq_dec: EqDecision positive := Pos.eq_dec. Instance positive_eq_dec: EqDecision positive := Pos.eq_dec.
Instance positive_le_dec: RelDecision Pos.le.
Proof. refine (λ x y, decide ((x ?= y) Gt)). Defined.
Instance positive_lt_dec: RelDecision Pos.lt.
Proof. refine (λ x y, decide ((x ?= y) = Lt)). Defined.
Instance positive_inhabited: Inhabited positive := populate 1. Instance positive_inhabited: Inhabited positive := populate 1.
Instance maybe_xO : Maybe xO := λ p, match p with p~0 => Some p | _ => None end. Instance maybe_xO : Maybe xO := λ p, match p with p~0 => Some p | _ => None end.
...@@ -218,10 +222,10 @@ Instance Npos_inj : Inj (=) (=) Npos. ...@@ -218,10 +222,10 @@ Instance Npos_inj : Inj (=) (=) Npos.
Proof. by injection 1. Qed. Proof. by injection 1. Qed.
Instance N_eq_dec: EqDecision N := N.eq_dec. Instance N_eq_dec: EqDecision N := N.eq_dec.
Program Instance N_le_dec (x y : N) : Decision (x y)%N := Program Instance N_le_dec : RelDecision N.le := λ x y,
match Ncompare x y with Gt => right _ | _ => left _ end. match Ncompare x y with Gt => right _ | _ => left _ end.
Solve Obligations with naive_solver. Solve Obligations with naive_solver.
Program Instance N_lt_dec (x y : N) : Decision (x < y)%N := Program Instance N_lt_dec : RelDecision N.lt := λ x y,
match Ncompare x y with Lt => left _ | _ => right _ end. match Ncompare x y with Lt => left _ | _ => right _ end.
Solve Obligations with naive_solver. Solve Obligations with naive_solver.
Instance N_inhabited: Inhabited N := populate 1%N. Instance N_inhabited: Inhabited N := populate 1%N.
...@@ -259,8 +263,8 @@ Instance Z_of_nat_inj : Inj (=) (=) Z.of_nat. ...@@ -259,8 +263,8 @@ Instance Z_of_nat_inj : Inj (=) (=) Z.of_nat.
Proof. intros n1 n2. apply Nat2Z.inj. Qed. Proof. intros n1 n2. apply Nat2Z.inj. Qed.
Instance Z_eq_dec: EqDecision Z := Z.eq_dec. Instance Z_eq_dec: EqDecision Z := Z.eq_dec.
Instance Z_le_dec: x y : Z, Decision (x y) := Z_le_dec. Instance Z_le_dec: RelDecision Z.le := Z_le_dec.
Instance Z_lt_dec: x y : Z, Decision (x < y) := Z_lt_dec. Instance Z_lt_dec: RelDecision Z.lt := Z_lt_dec.
Instance Z_inhabited: Inhabited Z := populate 1. Instance Z_inhabited: Inhabited Z := populate 1.
Instance Z_le_po : PartialOrder (). Instance Z_le_po : PartialOrder ().
Proof. Proof.
...@@ -365,11 +369,11 @@ Hint Extern 1 (_ ≤ _) => reflexivity || discriminate. ...@@ -365,11 +369,11 @@ Hint Extern 1 (_ ≤ _) => reflexivity || discriminate.
Arguments Qred : simpl never. Arguments Qred : simpl never.
Instance Qc_eq_dec: EqDecision Qc := Qc_eq_dec. Instance Qc_eq_dec: EqDecision Qc := Qc_eq_dec.
Program Instance Qc_le_dec (x y : Qc) : Decision (x y) := Program Instance Qc_le_dec: RelDecision Qcle := λ x y,
if Qclt_le_dec y x then right _ else left _. if Qclt_le_dec y x then right _ else left _.
Next Obligation. intros x y; apply Qclt_not_le. Qed. Next Obligation. intros x y; apply Qclt_not_le. Qed.
Next Obligation. done. Qed. Next Obligation. done. Qed.
Program Instance Qc_lt_dec (x y : Qc) : Decision (x < y) := Program Instance Qc_lt_dec: RelDecision Qclt := λ x y,
if Qclt_le_dec x y then left _ else right _. if Qclt_le_dec x y then left _ else right _.
Solve Obligations with done. Solve Obligations with done.
Next Obligation. intros x y; apply Qcle_not_lt. Qed.