Proof using.
intros.
destruct (prod_eq_dec A_eq_dec A_eq_dec (x, y) (x', y')); subst;
repeat first [rewrite update2_diff_prod by congruence |
rewrite update2_eq_prod  by auto ]; auto.
Qed.
Ltac update2_destruct_goal :=
match goal with
| [ |- context [ update2 ?eq_dec _ ?x ?y _ ?x' ?y' ] ] =>
destruct (prod_eq_dec eq_dec eq_dec (x, y) (x', y'))
end.
Ltac update2_destruct_hyp :=
match goal with
| [ _ : context [ update2 ?eq_dec _ ?x ?y _ ?x' ?y' ] |- _ ] =>
destruct (prod_eq_dec eq_dec eq_dec (x, y) (x', y'))
end.
Ltac update2_destruct := update2_destruct_goal || update2_destruct_hyp.
Ltac rewrite_update2' H :=
first [rewrite update2_diff_prod in H by congruence |
rewrite update2_eq_prod in H by auto ].
Ltac rewrite_update2 :=
repeat match goal with
| [ H : context [ update2 _ _ _ _ _ _ _ ] |- _ ] =>
rewrite_update2' H; repeat rewrite_update2' H
| [ |- _ ] => repeat (try rewrite update2_diff_prod by congruence;
try rewrite update2_eq_prod by auto)
end.
Ltac destruct_update2 :=
repeat (update2_destruct; subst; rewrite_update2).
Ltac destruct_update2_hyp :=
repeat ((update2_destruct_hyp || update2_destruct_goal); subst; rewrite_update2).
Ltac update2_destruct_simplify :=
update2_destruct; subst; rewrite_update2; simpl in *.
Ltac update2_destruct_simplify_hyp :=
update2_destruct_hyp || update2_destruct_goal; subst; rewrite_update2; simpl in *.
Ltac update2_destruct_max_simplify :=
update2_destruct; subst_max; rewrite_update2; simpl in *.
Section Update2Rel.
Variables A B : Type.
Variable R : relation A.
Hypothesis A_eq_dec : forall x y : A, {x = y} + {x <> y}.
Hypothesis R_dec : forall x y : A, {R x y} + {~ R x y}.

(* Specifications: *)
Lemma filter_rel_related :
forall n n' ns,
In n' (filter_rel R_dec n ns) ->
In n' ns /\ R n n'.