(************************************************************************)
(*         *      The Rocq Prover / The Rocq Development Team           *)
(*  v      *         Copyright INRIA, CNRS and contributors             *)
(* <O___,, * (see version control and CREDITS file for authors & dates) *)
(*   \VV/  **************************************************************)
(*    //   *    This file is distributed under the terms of the         *)
(*         *     GNU Lesser General Public License Version 2.1          *)
(*         *     (see LICENSE file for the text of the license)         *)
(************************************************************************)
(* Finite sets library. * Authors: Pierre Letouzey and Jean-Christophe Filliâtre * Institution: LRI, CNRS UMR 8623 - Université Paris Sud *              91405 Orsay, France *)
RelationPairs EqualitiesFacts.
(** * Examples of Ordered Type structures. *)
(** Ordered Type for [bool], [nat], [Positive], [N], [Z], [ascii], [string] with the usual or lexicographic order. *)
Module Bool_as_OT := BoolOrder.BoolOrd.
Module Nat_as_OT := PeanoNat.Nat.
Module Positive_as_OT := BinPos.Pos.
Module N_as_OT := BinNat.N.
Module Z_as_OT := BinInt.Z.
(** An OrderedType can now directly be seen as a DecidableType *)
Module OT_as_DT (O:OrderedType) <: DecidableType := O.
(** (Usual) Decidable Type for [bool], [nat], [positive], [N], [Z] *)
Module Bool_as_DT <: UsualDecidableType := Bool_as_OT.
Module Nat_as_DT <: UsualDecidableType := Nat_as_OT.
Module Positive_as_DT <: UsualDecidableType := Positive_as_OT.
Module N_as_DT <: UsualDecidableType := N_as_OT.
Module Z_as_DT <: UsualDecidableType := Z_as_OT.
(** From two ordered types, we can build a new OrderedType over their cartesian product, using the lexicographic order. *)
Module PairOrderedType(O1 O2:OrderedType) <: OrderedType.
Include PairDecidableType O1 O2.
Definition lt :=
(relation_disjunction (O1.lt @@1) (O1.eq * O2.lt))%signature.
#[global]
Instance lt_strorder : StrictOrder lt.
#[global]
Instance lt_compat : Proper (eq==>eq==>iff) lt.
Definition compare x y :=
match O1.compare (fst x) (fst y) with
| Eq => O2.compare (snd x) (snd y)
| Lt => Lt
| Gt => Gt
end.

(* Specifications: *)
Lemma compare_spec : forall x y, CompSpec eq lt x y (compare x y).
End PairOrderedType.