(* Copyright (C) 2012  G. Gonthier, B. Ziliani, A. Nanevski, D. Dreyer  This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.  You should have received a copy of the GNU General Public License along with this program.  If not, see <http://www.gnu.org/licenses/>. *)
From mathcomp
From LemmaOverloading
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
(**********)
(* Posets *)
(**********)
(* We put bottom in posets right away, instead of adding it later both in *)
(* lattices and in cpos. Since we never consider bottom-less posets, this *)
(* saves some tedium and name space. *)
Module Poset.
Section RawMixin.
Record mixin_of (T : Type) := Mixin {
mx_leq : T -> T -> Prop;
mx_bot : T;
_ : forall x, mx_leq mx_bot x;
_ : forall x, mx_leq x x;
_ : forall x y, mx_leq x y -> mx_leq y x -> x = y;
_ : forall x y z, mx_leq x y -> mx_leq y z -> mx_leq x z}.
End RawMixin.
Section ClassDef.
Record class_of T := Class {mixin : mixin_of T}.
Structure type : Type := Pack {sort : Type; _ : class_of sort; _ : Type}.
Local Coercion sort : type >-> Sortclass.
Variables (T : Type) (cT : type).
Definition class := let: Pack _ c _ as cT' := cT return class_of cT' in c.
Definition clone c of phant_id class c := @Pack T c T.
(* produce a poset type out of the mixin *)
(* equalize m0 and m by means of a phantom *)
Definition pack (m0 : mixin_of T) :=
fun m & phant_id m0 m => Pack (@Class T m) T.
Definition leq := mx_leq (mixin class).
Definition bot := mx_bot (mixin class).
End ClassDef.
Module Exports.
Coercion sort : type >-> Sortclass.
Notation poset := Poset.type.
Notation PosetMixin := Poset.Mixin.
Notation Poset T m := (@pack T _ m id).
Notation "[ 'poset' 'of' T 'for' cT ]" := (@clone T cT _ id)
(at level 0, format "[ 'poset'  'of'  T  'for'  cT ]") : form_scope.
Notation "[ 'poset' 'of' T ]" := (@clone T _ _ id)
(at level 0, format "[ 'poset'  'of'  T ]") : form_scope.
Notation "x <== y" := (Poset.leq x y) (at level 70).
Notation bot := Poset.bot.
Arguments Poset.bot [cT].
Prenex Implicits Poset.bot.
(* re-state lattice properties using the exported notation *)
Section Laws.
Variable T : poset.

(* Specifications: *)
Lemma botP (x : T) : bot <== x.
Lemma sub_trans x y z : sub_leq x y -> sub_leq y z -> sub_leq x z.
Definition subPosetMixin := PosetMixin sub_botP sub_refl sub_asym sub_trans.