(* Copyright 2012-2015 by Adam Petcher.				* * Use of this source code is governed by the license described	* * in the LICENSE file at the root of the source tree.		*)
(* a type class and other definitions for decidable equality *)
Set Implicit Arguments.
Definition eq_dec(A : Set) := forall (a1 a2 : A), {a1 = a2} + {a1 <> a2}.
Class EqDec (A : Set) := {
eqb : A -> A -> bool ;
eqb_leibniz : forall x y, eqb x y = true <-> x = y
}.
Infix "?=" := eqb (at level 70) : eq_scope.
Infix "!=" := (fun x y => negb (eqb x y)) (at level 70) : eq_scope.
intuition.
eapply eqb_leibniz.
trivial.
Qed.
intuition.
case_eq (eqb x y); intuition.
rewrite eqb_leibniz in H.
subst.
rewrite eqb_refl.
trivial.
case_eq (eqb y x); intuition.
rewrite eqb_leibniz in H0; subst.
rewrite eqb_refl in H.
discriminate.
Qed.
intuition.
remember (eqb a b) as x.
destruct x.
left.
eapply eqb_leibniz.
auto.
right.
intuition.
subst.
assert (eqb b b = true -> False).
intuition.
congruence.
eapply H0.
eapply eqb_leibniz.
trivial.
Qed.
intuition.
eapply (Build_EqDec (fun a1 a2 => if (eqd a1 a2) then true else false)).
intuition.
destruct (eqd x y); trivial.
discriminate.
destruct (eqd x y); trivial.
congruence.
Qed.
intuition.
eapply (Vector.case0 (fun v => v = [])).
trivial.
Qed.
intuition.
induction n, v using Vector.rectS.
econstructor. econstructor. eauto.
econstructor. econstructor. eauto.
Qed.
Definition eqb_vector(A : Set)(eqd : EqDec A)(n : nat)(v1 v2 : Vector.t A n) :=
Vector.fold_left2 (fun b a1 a2 => b && (eqb a1 a2)) true v1 v2.
induction n; intuition; simpl in *.
rewrite (vector_0 v).
unfold eqb_vector.
simpl.
trivial.
destruct (vector_S v).
destruct H.
subst.
unfold eqb_vector.
simpl.
rewrite eqb_refl.
eapply IHn.
Qed.
induction n; intuition; simpl in *.
rewrite (vector_0 v1).
rewrite (vector_0 v2).
simpl.
trivial.
destruct (vector_S v1).
destruct (vector_S v2).
destruct H.
destruct H0.
subst.
simpl.
eapply IHn.
Qed.

Theorem eqb_vector_leibniz:
forall (A : Set)(eqd : EqDec A)(n : nat)(v1 v2 : Vector.t A n),
eqb_vector _ v1 v2 = true -> v1 = v2.