aboutsummaryrefslogtreecommitdiff
path: root/theories/Classes/SetoidDec.v
blob: cd96269f8fc989dd37a92475ce50e0055393865b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
(* -*- coq-prog-args: ("-emacs-U" "-nois") -*- *)
(************************************************************************)
(*  v      *   The Coq Proof Assistant  /  The Coq Development Team     *)
(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
(*   \VV/  **************************************************************)
(*    //   *      This file is distributed under the terms of the       *)
(*         *       GNU Lesser General Public License Version 2.1        *)
(************************************************************************)

(* Certified Haskell Prelude.
 * Author: Matthieu Sozeau
 * Institution: LRI, CNRS UMR 8623 - Universit�copyright Paris Sud
 *              91405 Orsay, France *)

(* $Id: FSetAVL_prog.v 616 2007-08-08 12:28:10Z msozeau $ *)

Set Implicit Arguments.
Unset Strict Implicit.

Require Import Coq.Classes.SetoidClass.

Class [ Setoid A R ] => EqDec :=
  equiv_dec : forall x y : A, { x == y } + { x =!= y }.

Infix "==" := equiv_dec (no associativity, at level 70).

Require Import Coq.Program.Program.

Program Definition nequiv_dec [ EqDec A R ] (x y : A) : { x =!= y } + { x == y } :=
  if x == y then right else left.

Infix "<>" := nequiv_dec (no associativity, at level 70).

Definition equiv_decb [ EqDec A R ] (x y : A) : bool :=
  if x == y then true else false.

Definition nequiv_decb [ EqDec A R ] (x y : A) : bool :=
  negb (equiv_decb x y).

Infix "==b" := equiv_decb (no associativity, at level 70).
Infix "<>b" := nequiv_decb (no associativity, at level 70).

(** Decidable leibniz equality instances. *)

Implicit Arguments eq [[A]].

Require Import Coq.Arith.Arith.

Program Instance nat_eqdec : EqDec nat eq :=
  equiv_dec := eq_nat_dec.

Require Import Coq.Bool.Bool.

Program Instance bool_eqdec : EqDec bool eq :=
  equiv_dec := bool_dec.

Program Instance unit_eqdec : EqDec unit eq :=
  equiv_dec x y := left.

Next Obligation.
Proof.
  destruct x ; destruct y.
  reflexivity.
Qed.

Program Instance [ EqDec A eq, EqDec B eq ] => prod_eqdec : EqDec (prod A B) eq :=
  equiv_dec x y := 
    dest x as (x1, x2) in 
    dest y as (y1, y2) in 
    if x1 == y1 then 
      if x2 == y2 then left
      else right
    else right.

Solve Obligations using unfold equiv ; program_simpl ; try red ; intros ; autoinjections ; discriminates.

Program Instance [ EqDec A eq ] => bool_function_eqdec : EqDec (bool -> A) eq :=
  equiv_dec f g := 
    if f true == g true then
      if f false == g false then left
      else right
    else right.

Solve Obligations using unfold equiv ; program_simpl.

Require Import Coq.Program.FunctionalExtensionality.

Next Obligation.
Proof.
  unfold equiv.
  extensionality x.
  destruct x ; auto.
Qed.

Next Obligation.
Proof.
  unfold equiv in *.
  red ; intro ; subst.
  discriminates.
Qed.