End FSetLogicalFacts.
(** * Auxiliary Tactics Again, these lemmas and tactics are in a module so that they do not affect the namespace if you import the enclosing module [Decide].  *)
Module FSetDecideAuxiliary.
(** ** Generic Tactics We begin by defining a few generic, useful tactics. *)
(** [if t then t1 else t2] executes [t] and, if it does not fail, then [t1] will be applied to all subgoals produced.  If [t] fails, then [t2] is executed. *)
Tactic Notation
"if" tactic(t)
"then" tactic(t1)
"else" tactic(t2) :=
first [ t; first [ t1 | fail 2 ] | t2 ].
(** [prop P holds by t] succeeds (but does not modify the goal or context) if the proposition [P] can be proved by [t] in the current context.  Otherwise, the tactic fails. *)
Tactic Notation "prop" constr(P) "holds" "by" tactic(t) :=
let H := fresh in
assert P as H by t;
clear H.
(** This tactic acts just like [assert ... by ...] but will fail if the context already contains the proposition. *)
Tactic Notation "assert" "new" constr(e) "by" tactic(t) :=
match goal with
| H: e |- _ => fail 1
| _ => assert e by t
end.
(** [subst++] is similar to [subst] except that - it never fails (as [subst] does on recursive equations), - it substitutes locally defined variable for their definitions, - it performs beta reductions everywhere, which may arise after substituting a locally defined function for its definition. *)
Tactic Notation "subst" "++" :=
repeat (
match goal with
| x : _ |- _ => subst x
end);
cbv zeta beta in *.
(** [decompose records] calls [decompose record H] on every relevant hypothesis [H]. *)
Tactic Notation "decompose" "records" :=
repeat (
match goal with
| H: _ |- _ => progress (decompose record H); clear H
end).
(** ** Discarding Irrelevant Hypotheses We will want to clear the context of any non-FSet-related hypotheses in order to increase the speed of the tactic.  To do this, we will need to be able to decide which are relevant.  We do this by making a simple inductive definition classifying the propositions of interest. *)
Inductive FSet_elt_Prop : Prop -> Prop :=
| eq_Prop : forall (S : Type) (x y : S),
FSet_elt_Prop (x = y)
| eq_elt_prop : forall x y,
FSet_elt_Prop (E.eq x y)
| In_elt_prop : forall x s,
FSet_elt_Prop (In x s)
| True_elt_prop :
FSet_elt_Prop True
| False_elt_prop :
FSet_elt_Prop False
| conj_elt_prop : forall P Q,
FSet_elt_Prop P ->
FSet_elt_Prop Q ->
FSet_elt_Prop (P /\ Q)
| disj_elt_prop : forall P Q,
FSet_elt_Prop P ->
FSet_elt_Prop Q ->
FSet_elt_Prop (P \/ Q)
| impl_elt_prop : forall P Q,
FSet_elt_Prop P ->
FSet_elt_Prop Q ->
FSet_elt_Prop (P -> Q)
| not_elt_prop : forall P,
FSet_elt_Prop P ->
FSet_elt_Prop (~ P).
Inductive FSet_Prop : Prop -> Prop :=
| elt_FSet_Prop : forall P,
FSet_elt_Prop P ->
FSet_Prop P
| Empty_FSet_Prop : forall s,
FSet_Prop (Empty s)
| Subset_FSet_Prop : forall s1 s2,
FSet_Prop (Subset s1 s2)
| Equal_FSet_Prop : forall s1 s2,
FSet_Prop (Equal s1 s2).
(** Here is the tactic that will throw away hypotheses that are not useful (for the intended scope of the [fsetdec] tactic). *)
Hint Constructors FSet_elt_Prop FSet_Prop : FSet_Prop.
Ltac discard_nonFSet :=
repeat (
match goal with
| H : ?P |- _ =>
if prop (FSet_Prop P) holds by
(auto 100 with FSet_Prop)
then fail
else clear H
end).
(** ** Turning Set Operators into Propositional Connectives The lemmas from [FSetFacts] will be used to break down set operations into propositional formulas built over the predicates [In] and [E.eq] applied only to variables.  We are going to use them with [autorewrite]. *)
Hint Rewrite
F.empty_iff F.singleton_iff F.add_iff F.remove_iff
F.union_iff F.inter_iff F.diff_iff
: set_simpl.
(** ** Decidability of FSet Propositions *)

(** [E.eq] is decidable. *)
Lemma dec_eq : forall (x y : E.t),
decidable (E.eq x y).