End AssortedListProperties.
(* *********************************************************************** *)
(** * Tactic support for [disjoint] and [uniq] *)
(** [destruct_uniq] decomposes all [uniq] and [disjoint] hypotheses. *)
Ltac destruct_uniq :=
match goal with
| H : uniq nil |- _ =>
clear H;
destruct_uniq
| H : uniq (?x ~ ?a) |- _ =>
clear H;
destruct_uniq
| H : uniq ((?x, ?a) :: ?E) |- _ =>
let J := fresh "UniqTac" in
pose proof H as J;
apply uniq_cons_1 in H;
apply uniq_cons_2 in J;
autorewrite with rewr_dom in J;
destruct_uniq
| H : uniq (?E ++ ?F) |- _ =>
let J1 := fresh "UniqTac" in
let J2 := fresh "UniqTac" in
pose proof H as J1;
pose proof H as J2;
apply uniq_app_1 in H;
apply uniq_app_2 in J1;
apply uniq_app_3 in J2;
destruct_uniq
| H : uniq (map ?f ?E) |- _ =>
apply uniq_map_1 in H;
destruct_uniq
| H : disjoint nil ?E |- _ =>
clear H;
destruct_uniq
| H : disjoint (?x ~ ?a) ?F |- _ =>
apply disjoint_one_1 in H;
autorewrite with rewr_dom in H;
destruct_uniq
| H : disjoint ((?x, ?a) :: ?E) ?F |- _ =>
let J := fresh "UniqTac" in
pose proof H as J;
apply disjoint_cons_1 in H;
apply disjoint_cons_2 in J;
autorewrite with rewr_dom in H;
destruct_uniq
| H : disjoint (?E ++ ?F) ?G |- _ =>
let J := fresh "UniqTac" in
pose proof H as J;
apply disjoint_app_1 in H;
apply disjoint_app_2 in J;
destruct_uniq
| H : disjoint (map ?f ?E) ?F |- _ =>
apply disjoint_map_1 in H;
destruct_uniq
| H : disjoint ?E nil |- _ =>
clear H;
destruct_uniq
| H : disjoint ?F (?x ~ ?a) |- _ =>
apply disjoint_sym_1 in H;
destruct_uniq
| H : disjoint ?F ((?x, ?a) :: ?E) |- _ =>
apply disjoint_sym_1 in H;
destruct_uniq
| H : disjoint ?G (?E ++ ?F) |- _ =>
apply disjoint_sym_1 in H;
destruct_uniq
| H : disjoint ?F (map ?f ?E) |- _ =>
apply disjoint_sym_1 in H;
destruct_uniq
| _ =>
idtac
end.
(** [solve_uniq] attempts to solve goals by first decomposing hypotheses about [disjoint] and [uniq] and then trying some simple, if perhaps slow, heuristics. *)
Ltac solve_uniq :=
intros;
destruct_uniq;
repeat first [ apply uniq_push
| apply uniq_cons_3
| apply uniq_app_4
| apply uniq_one_1
| apply uniq_nil ];
auto;
try tauto;
unfold disjoint in *;
try fsetdec;
fail "Not solvable by [solve_uniq]; try [destruct_uniq]".
(* *********************************************************************** *)
(** * Facts about [uniq] *)
Section UniqDerived.
Variable  A     : Type.
Variables x y   : atom.
Variables a b   : A.
Variables E F G : list (atom*A).

(* Specifications: *)
Axiom uniq_insert_mid :
uniq (G ++ E) ->
~ In x (dom G) ->
~ In x (dom E) ->
uniq (G ++ (x ~ a) ++ E).
Axiom uniq_remove_mid :
uniq (E ++ F ++ G) ->
uniq (E ++ G).
Axiom uniq_reorder_1 :
uniq (E ++ F) ->
uniq (F ++ E).
Axiom uniq_reorder_2 :
uniq (E ++ F ++ G) ->
uniq (F ++ E ++ G).
Axiom uniq_map_app_l : forall (f : A -> A),
uniq (F ++ E) ->
uniq (map f F ++ E).
Axiom fresh_mid_tail :
uniq (F ++ (x ~ a) ++ E) ->
~ In x (dom E).
Axiom fresh_mid_head :
uniq (F ++ (x ~ a) ++ E) ->
~ In x (dom F).