(************************************************************************)
(*         *      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)         *)
(************************************************************************)
(** * A Generic construction of min and max *)
(** ** First, an interface for types with [max] and/or [min] *)
Module Type HasMax (Import E:EqLe').
Parameter Inline max : t -> t -> t.
Parameter max_l : forall x y, y<=x -> max x y == x.
Parameter max_r : forall x y, x<=y -> max x y == y.
End HasMax.
Module Type HasMin (Import E:EqLe').
Parameter Inline min : t -> t -> t.
Parameter min_l : forall x y, x<=y -> min x y == x.
Parameter min_r : forall x y, y<=x -> min x y == y.
End HasMin.
Module Type HasMinMax (E:EqLe) := HasMax E <+ HasMin E.
(** ** Any [OrderedTypeFull] can be equipped by [max] and [min] based on the compare function. *)
Definition gmax {A} (cmp : A->A->comparison) x y :=
match cmp x y with Lt => y | _ => x end.
Definition gmin {A} (cmp : A->A->comparison) x y :=
match cmp x y with Gt => y | _ => x end.
Module GenericMinMax (Import O:OrderedTypeFull') <: HasMinMax O.
Definition max := gmax O.compare.
Definition min := gmin O.compare.

(* Specifications: *)
Lemma ge_not_lt x y : y<=x -> x<y -> False.
Lemma max_l x y : y<=x -> max x y == x.
Lemma max_r x y : x<=y -> max x y == y.
Lemma min_l x y : x<=y -> min x y == x.
Lemma min_r x y : y<=x -> min x y == y.
End GenericMinMax.