Section Vector_EqDec.
Variable A : Set.
Context `{eqd_A : EqDec A}.
Instance Vector_EqDec :
forall (n : nat),
EqDec (Vector.t A n).
intuition.
eapply (Build_EqDec (@eqb_vector A eqd_A n)).
intuition.
eapply eqb_vector_leibniz.
trivial.
subst.
apply eqb_vector_refl.
Qed.
End Vector_EqDec.
(* Fixpoint BvIsZero n (v : Bvector n) : bool  := match v with | Vector.nil => true | Vector.cons b _ v' => (andb (if (bool_dec b false) then true else false) (BvIsZero v')) end. *)
Instance unit_EqDec : EqDec unit.
refine {| eqb := (fun x y => true) |}.
intuition.
destruct x.
destruct y.
trivial.
Qed.
Instance bool_EqDec : EqDec bool.
refine {| eqb := Bool.eqb |}.
eapply eqb_true_iff.
Qed.
(* Bvector decidable equality was added before Vector.t decidable equality.  Definitions remain for compatibility. *)
Definition eqbBvector n (v1 v2 : Bvector n) : bool :=
(eqb_vector _ v1 v2).
intuition.
unfold eqbBvector in *.
eapply eqb_vector_leibniz.
trivial.
Qed.
intuition.
unfold eqbBvector.
apply eqb_vector_refl.
Qed.
Instance Bvector_EqDec n : EqDec (Bvector n).
refine {| eqb := (@eqbBvector n) |}.
intuition.
eapply eqbBvector_sound; auto.
intuition.
subst.
eapply eqbBvector_complete; eauto.
Defined.
Instance nat_EqDec : EqDec nat.
refine {| eqb := (fun x y => (leb x y) && (leb y x)) |}.
intuition.
apply andb_true_iff in H.
intuition.
eapply le_antisym;
eapply leb_iff; eauto.
apply andb_true_iff.
intuition;
eapply leb_iff; subst; eapply le_refl.
Qed.
Definition eqbPair (A B : Set)(dA : EqDec A)(dB : EqDec B)(p1 p2 : (A*B)) :=
(eqb (fst p1) (fst p2)) && (eqb (snd p1) (snd p2)).
Instance pair_EqDec (A B : Set) (dA : EqDec A) (dB : EqDec B) : EqDec (prod A B).
refine {| eqb := (@eqbPair A B dA dB) |}.
intuition; unfold eqbPair in *; simpl in *.
apply andb_true_iff in H.
intuition.
f_equal;
eapply eqb_leibniz; trivial.
inversion H; subst; clear H.
apply andb_true_iff; intuition;
eapply eqb_leibniz; trivial.
Defined.
Definition eqbSum(A B : Set)(dA : EqDec A)(dB : EqDec B)(s1 s2 : (A + B)) :=
match s1 with
| inl a1 =>
match s2 with
| inl a2 => eqb a1 a2
| inr b2 => false
end
| inr b1 =>
match s2 with
| inl a2 => false
| inr b2 => eqb b1 b2
end
end.
Instance sum_EqDec (A B : Set) (dA : EqDec A) (dB : EqDec B) :
EqDec (sum A B).
refine {| eqb := (@eqbSum A B dA dB) |}.
intuition; unfold eqbSum in *; try
match goal with
| [H : eqb _ _ = true |-_] => rewrite eqb_leibniz in H
| [H : inl _ = inl _ |-_] => inversion H
| [H : inr _ = inr _ |-_] => inversion H
end; subst; try rewrite eqb_refl; trivial; try discriminate.
Defined.
Definition eqbOption (A : Set)(dA : EqDec A)(o1 o2 : option A) :=
match o1 with
| None =>
match o2 with
| None => true
| Some _ => false
end
| Some a1 =>
match o2 with
| None => false
| Some a2 => (eqb a1 a2)
end
end.
Instance option_EqDec (A : Set) (dA : EqDec A) : EqDec (option A).
refine {| eqb := (@eqbOption A dA ) |}.
intuition; unfold eqbOption in *; simpl in *.
destruct x.
destruct y.
f_equal.
eapply eqb_leibniz; trivial.
discriminate.
destruct y.
discriminate.
trivial.
subst.
destruct y.
eapply eqb_leibniz; trivial.
trivial.
Qed.
Local Open Scope list_scope.
Fixpoint eqbList(A : Set)(eqd : EqDec A)(ls1 ls2 : list A) :=
match ls1 with
| nil =>
match ls2 with
| nil => true
| _ :: _ => false
end
| a1 :: ls1' =>
match ls2 with
| nil => false
| a2 :: ls2' =>
(eqb a1 a2) && (eqbList _ ls1' ls2')
end
end.
induction ls1; destruct ls2; intuition; simpl in *; try discriminate.
apply andb_true_iff in H.
intuition.
f_equal.
eapply eqb_leibniz.
trivial.
eauto.
Qed.
induction ls1; destruct ls2; intuition; simpl in *; try discriminate.
inversion H; clear H; subst.
apply andb_true_iff.
intuition.
eapply eqb_leibniz.
trivial.
Qed.
Instance list_EqDec (A : Set) (dA : EqDec A) : EqDec (list A).
refine {| eqb := (@eqbList A dA ) |}.
intuition.
eapply eqbList_correct1; trivial.
eapply eqbList_correct2; trivial.
Qed.

Theorem eqb_false_iff :
forall (A : Set)(eqd : EqDec A)(a1 a2 : A),
eqb a1 a2 = false <->
a1 <> a2.