(** [Comparable] provides a decidable equality. **)
Definition compare_eqdec {A:Type} {C:Comparable A} {U:ComparableUsualEq C} (x y:A):
  {x = y} + {x <> y}.Instance NComparableUsualEq : ComparableUsualEq natComparable := Nat.compare_eq.(** A pair of ComparableUsualEq is ComparableUsualEq **)
Instance PairComparableUsualEq
  {A:Type} {CA:Comparable A} (UA:ComparableUsualEq CA)
  {B:Type} {CB:Comparable B} (UB:ComparableUsualEq CB) :
    ComparableUsualEq (PairComparable CA CB).(** An [Finite] type is a type with the list of all elements. **)
Class Finite (A:Type) := {
  all_list : list A;
  all_list_forall : forall x:A, In x all_list
}.(** An [Finite] type is a type with the list of all elements. **)
Class Finite (A:Type) := {
  all_list : list A;
  all_list_forall : forall x:A, In x all_list
}.(** An [Finite] type is a type with the list of all elements. **)
Class Finite (A:Type) := {
  all_list : list A;
  all_list_forall : forall x:A, In x all_list
}.(** An alphabet is both [ComparableUsualEq] and [Finite]. **)
Class Alphabet (A:Type) := {
  AlphabetComparable :> Comparable A;
  AlphabetComparableUsualEq :> ComparableUsualEq AlphabetComparable;
  AlphabetFinite :> Finite A
}.(** An alphabet is both [ComparableUsualEq] and [Finite]. **)
Class Alphabet (A:Type) := {
  AlphabetComparable :> Comparable A;
  AlphabetComparableUsualEq :> ComparableUsualEq AlphabetComparable;
  AlphabetFinite :> Finite A
}.(** An alphabet is both [ComparableUsualEq] and [Finite]. **)
Class Alphabet (A:Type) := {
  AlphabetComparable :> Comparable A;
  AlphabetComparableUsualEq :> ComparableUsualEq AlphabetComparable;
  AlphabetFinite :> Finite A
}.(** An alphabet is both [ComparableUsualEq] and [Finite]. **)
Class Alphabet (A:Type) := {
  AlphabetComparable :> Comparable A;
  AlphabetComparableUsualEq :> ComparableUsualEq AlphabetComparable;
  AlphabetFinite :> Finite A
}.(** The [Numbered] class provides a conveniant way to build [Alphabet] instances,
   with a good computationnal complexity. It is mainly a injection from it to
   [Int31] **)
Class Numbered (A:Type) := {
  inj : A -> int31;
  surj : int31 -> A;
  surj_inj_compat : forall x, surj (inj x) = x;
  inj_bound : int31;
  inj_bound_spec : forall x, (phi (inj x) < phi inj_bound)%Z
}.(** The [Numbered] class provides a conveniant way to build [Alphabet] instances,
   with a good computationnal complexity. It is mainly a injection from it to
   [Int31] **)
Class Numbered (A:Type) := {
  inj : A -> int31;
  surj : int31 -> A;
  surj_inj_compat : forall x, surj (inj x) = x;
  inj_bound : int31;
  inj_bound_spec : forall x, (phi (inj x) < phi inj_bound)%Z
}.(** The [Numbered] class provides a conveniant way to build [Alphabet] instances,
   with a good computationnal complexity. It is mainly a injection from it to
   [Int31] **)
Class Numbered (A:Type) := {
  inj : A -> int31;
  surj : int31 -> A;
  surj_inj_compat : forall x, surj (inj x) = x;
  inj_bound : int31;
  inj_bound_spec : forall x, (phi (inj x) < phi inj_bound)%Z
}.(** The [Numbered] class provides a conveniant way to build [Alphabet] instances,
   with a good computationnal complexity. It is mainly a injection from it to
   [Int31] **)
Class Numbered (A:Type) := {
  inj : A -> int31;
  surj : int31 -> A;
  surj_inj_compat : forall x, surj (inj x) = x;
  inj_bound : int31;
  inj_bound_spec : forall x, (phi (inj x) < phi inj_bound)%Z
}.(** The [Numbered] class provides a conveniant way to build [Alphabet] instances,
   with a good computationnal complexity. It is mainly a injection from it to
   [Int31] **)
Class Numbered (A:Type) := {
  inj : A -> int31;
  surj : int31 -> A;
  surj_inj_compat : forall x, surj (inj x) = x;
  inj_bound : int31;
  inj_bound_spec : forall x, (phi (inj x) < phi inj_bound)%Z
}.(** The [Numbered] class provides a conveniant way to build [Alphabet] instances,
   with a good computationnal complexity. It is mainly a injection from it to
   [Int31] **)
Class Numbered (A:Type) := {
  inj : A -> int31;
  surj : int31 -> A;
  surj_inj_compat : forall x, surj (inj x) = x;
  inj_bound : int31;
  inj_bound_spec : forall x, (phi (inj x) < phi inj_bound)%Z
}.(** Previous class instances for [option A] **)
Program Instance OptionComparable {A:Type} (C:Comparable A) : Comparable (option A) :=
  { compare := fun x y =>
      match x, y return comparison with
        | None, None => Eq
        | None, Some _ => Lt
        | Some _, None => Gt
        | Some x, Some y => compare x y
      end }.Instance OptionComparableUsualEq {A:Type} {C:Comparable A} (U:ComparableUsualEq C) :
  ComparableUsualEq (OptionComparable C).Program Instance OptionFinite {A:Type} (E:Finite A) : Finite (option A) :=
  { all_list := None :: map Some all_list }.Definition t := C.t.Definition compare : t -> t -> comparison := compare.Infix "?=" := compare (at level 70, no associativity).

(* Specifications: *)
Lemma compare_sym x y : (y?=x) = CompOpp (x?=y).
Lemma compare_trans c x y z : (x?=y) = c -> (y?=z) = c -> (x?=z) = c.