Proof with intuition (fsetdec || eauto using binds_dom_contradiction).
clear. intros H1.
autorewrite with rewr_uniq in H1. unfold disjoint in H1.
assert (H : x `notin` dom F \/ x `notin` dom E) by fsetdec.
rewrite binds_app...
Qed.
End MoreBindsProperties.
Hint Rewrite binds_app_uniq using solve_uniq : rewr_binds_uniq.
(** The [apply_binds_dom_contradiction] tactic solves a goal by applying the [binds_dom_contradiction] lemma.  The tactic succeeds only if the the hypotheses of the lemma are immediately satisfied. *)
Ltac apply_binds_dom_contradiction :=
match goal with
| H : binds ?x ?a ?E, J : ?x `notin` (dom ?E) |- _ =>
assert False by apply (@binds_dom_contradiction _ _ _ _ H J);
intuition
| H : binds ?x ?a ?E, J : ?x `in` (dom ?E) -> False |- _ =>
assert False by apply (@binds_dom_contradiction _ _ _ _ H J);
intuition
end.
(** The [solve_binds] tactic attempts to solve goals about [binds]. Given its definition, it's likely to work only when the hypotheses in the goal already contain all the relevant [binds] propositions.  Thus, the tactic may not be generally useful.  It is useful, however, for proving facts about [binds] such as the ones below. *)
Ltac solve_binds :=
simpl_asnlist in *;
autorewrite with rewr_binds in *;
intuition (auto || fsetdec || apply_binds_dom_contradiction)
|| fail.
(** The tactics [analyze_binds] and [analyze_binds_uniq] tactics take as an argument a hypotheses about [binds] and perform a case analysis based on the structure of the association list. In the case of [analyze_binds_uniq], the analysis is performed assuming that the association list is [uniq].  The lemmas [binds_app] and [binds_app_uniq] are examples of such case analysis.  Implementation notes:  - The initial calls to [simpl_asnlist] put the relevant association lists into normal form. - In the case of [binds_app_uniq], we assert that the association list is [uniq].  This enables the [autorewrite] step to succeed. - Rather than work on [H] itself, we copy it and work on the copy.  Thus, in instances where the analysis leaves unsolved subgoals, it is still possible to see the original hypothesis. - The rest of the tactic breaks apart the copy of H and tries several simple means for solving the resulting subgoals. *)
Ltac analyze_binds H :=
simpl_asnlist;
simpl_asnlist in H;
match type of H with
| binds ?x ?a ?E =>
let J := fresh in
pose proof H as J;
autorewrite with rewr_binds in J;
simpl_asnlist in J;
try (progress decompose [and or] J; clear J);
try solve [trivial | discriminate | intuition | fsetdec]
end.
Ltac analyze_binds_uniq H :=
simpl_asnlist;
simpl_asnlist in H;
match type of H with
| binds ?x ?a ?E =>
match goal with
| H : uniq ?E |- _ => idtac
| _ => assert (uniq E); [ try solve_uniq | ]
end;
let J := fresh in
pose proof H as J;
autorewrite with rewr_binds_uniq in J;
simpl_asnlist in J;
try (progress decompose [and or] J; clear J);
try solve [trivial | discriminate | intuition | fsetdec]
end.
(* ********************************************************************* *)
(** ** Facts about [binds] *)
Section BindsDerived.
Variables A B : Set.
Variables f1 : A -> A.
Variables f2 : B -> B.
Variables x y : atom.
Variables a b : A.
Variables E F G : list (asn A B).

(* Specifications: *)
Lemma binds_map_2 :
binds x a E ->
binds x (f1 a) (map f1 f2 E).
Lemma binds_weaken :
binds x a (E ++ G) ->
binds x a (E ++ F ++ G).
Lemma fresh_app_l :
uniq (F ++ E) ->
binds x a E ->
x `notin` dom F.
Lemma fresh_app_r :
uniq (F ++ E) ->
binds x a F ->
x `notin` dom E.