Built with Alectryon, running Coq+SerAPI v8.10.0+0.7.0. Coq sources are in this panel; goals and messages will appear in the other. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑ Ctrl+↓ to navigate, Ctrl+🖱️ to focus.
(************************************************************************) (* * The Coq Proof Assistant / The Coq Development Team *) (* v * INRIA, CNRS and contributors - Copyright 1999-2018 *) (* <O___,, * (see CREDITS file for the list of authors) *) (* \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) *) (************************************************************************) Require Export Relations Morphisms Setoid Equalities. Set Implicit Arguments. Unset Strict Implicit.
First, signatures with only the order relations
Module Type HasLt (Import T:Typ). Parameter Inline(40) lt : t -> t -> Prop. End HasLt. Module Type HasLe (Import T:Typ). Parameter Inline(40) le : t -> t -> Prop. End HasLe. Module Type EqLt := Typ <+ HasEq <+ HasLt. Module Type EqLe := Typ <+ HasEq <+ HasLe. Module Type EqLtLe := Typ <+ HasEq <+ HasLt <+ HasLe.
Versions with nice notations
Module Type LtNotation (E:EqLt). Infix "<" := E.lt. Notation "x > y" := (y<x) (only parsing). Notation "x < y < z" := (x<y /\ y<z). End LtNotation. Module Type LeNotation (E:EqLe). Infix "<=" := E.le. Notation "x >= y" := (y<=x) (only parsing). Notation "x <= y <= z" := (x<=y /\ y<=z). End LeNotation. Module Type LtLeNotation (E:EqLtLe). Include LtNotation E <+ LeNotation E. Notation "x <= y < z" := (x<=y /\ y<z). Notation "x < y <= z" := (x<y /\ y<=z). End LtLeNotation. Module Type EqLtNotation (E:EqLt) := EqNotation E <+ LtNotation E. Module Type EqLeNotation (E:EqLe) := EqNotation E <+ LeNotation E. Module Type EqLtLeNotation (E:EqLtLe) := EqNotation E <+ LtLeNotation E. Module Type EqLt' := EqLt <+ EqLtNotation. Module Type EqLe' := EqLe <+ EqLeNotation. Module Type EqLtLe' := EqLtLe <+ EqLtLeNotation.
Versions with logical specifications
Module Type IsStrOrder (Import E:EqLt). Declare Instance lt_strorder : StrictOrder lt. Declare Instance lt_compat : Proper (eq==>eq==>iff) lt. End IsStrOrder. Module Type LeIsLtEq (Import E:EqLtLe'). Axiom le_lteq : forall x y, x<=y <-> x<y \/ x==y. End LeIsLtEq. Module Type StrOrder := EqualityType <+ HasLt <+ IsStrOrder. Module Type StrOrder' := StrOrder <+ EqLtNotation.
Versions with a decidable ternary comparison
Module Type HasCmp (Import T:Typ). Parameter Inline compare : t -> t -> comparison. End HasCmp. Module Type CmpNotation (T:Typ)(C:HasCmp T). Infix "?=" := C.compare (at level 70, no associativity). End CmpNotation. Module Type CmpSpec (Import E:EqLt')(Import C:HasCmp E). Axiom compare_spec : forall x y, CompareSpec (x==y) (x<y) (y<x) (compare x y). End CmpSpec. Module Type HasCompare (E:EqLt) := HasCmp E <+ CmpSpec E. Module Type DecStrOrder := StrOrder <+ HasCompare. Module Type DecStrOrder' := DecStrOrder <+ EqLtNotation <+ CmpNotation. Module Type OrderedType <: DecidableType := DecStrOrder <+ HasEqDec. Module Type OrderedType' := OrderedType <+ EqLtNotation <+ CmpNotation. Module Type OrderedTypeFull := OrderedType <+ HasLe <+ LeIsLtEq. Module Type OrderedTypeFull' := OrderedTypeFull <+ EqLtLeNotation <+ CmpNotation.
NB: in OrderedType, an eq_dec could be deduced from compare.
But adding this redundant field allows seeing an OrderedType as a
DecidableType.
Module Type UsualStrOrder := UsualEqualityType <+ HasLt <+ IsStrOrder. Module Type UsualDecStrOrder := UsualStrOrder <+ HasCompare. Module Type UsualOrderedType <: UsualDecidableType <: OrderedType := UsualDecStrOrder <+ HasEqDec. Module Type UsualOrderedTypeFull := UsualOrderedType <+ HasLe <+ LeIsLtEq.
NB: in UsualOrderedType, the field lt_compat is
useless since eq is Leibniz, but it should be
there for subtyping.
Module Type UsualStrOrder' := UsualStrOrder <+ LtNotation. Module Type UsualDecStrOrder' := UsualDecStrOrder <+ LtNotation. Module Type UsualOrderedType' := UsualOrderedType <+ LtNotation. Module Type UsualOrderedTypeFull' := UsualOrderedTypeFull <+ LtLeNotation.
Module Type LtIsTotal (Import E:EqLt'). Axiom lt_total : forall x y, x<y \/ x==y \/ y<x. End LtIsTotal. Module Type TotalOrder := StrOrder <+ HasLe <+ LeIsLtEq <+ LtIsTotal. Module Type UsualTotalOrder <: TotalOrder := UsualStrOrder <+ HasLe <+ LeIsLtEq <+ LtIsTotal. Module Type TotalOrder' := TotalOrder <+ EqLtLeNotation. Module Type UsualTotalOrder' := UsualTotalOrder <+ LtLeNotation.
From compare to eqb, and then eq_dec
Module Compare2EqBool (Import O:DecStrOrder') <: HasEqBool O. Definition eqb x y := match compare x y with Eq => true | _ => false end.forall x y : t, eqb x y = true <-> x == yforall x y : t, eqb x y = true <-> x == yforall x y : t, match x ?= y with | Eq => true | _ => false end = true <-> x == yx, y:tmatch x ?= y with | Eq => true | _ => false end = true <-> x == yx, y:tH:x < yx == y -> false = truex, y:tH:y < xx == y -> false = trueintros EQ; rewrite EQ in H; elim (StrictOrder_Irreflexive _ H).x, y:tH:x < yx == y -> false = trueintros EQ; rewrite EQ in H; elim (StrictOrder_Irreflexive _ H). Qed. End Compare2EqBool. Module DSO_to_OT (O:DecStrOrder) <: OrderedType := O <+ Compare2EqBool <+ HasEqBool2Dec.x, y:tH:y < xx == y -> false = true
From OrderedType To OrderedTypeFull (adding ≤)
Module OT_to_Full (O:OrderedType') <: OrderedTypeFull. Include O. Definition le x y := x<y \/ x==y.forall x y : t, le x y <-> x < y \/ x == yunfold le; split; auto. Qed. End OT_to_Full.forall x y : t, le x y <-> x < y \/ x == y
From computational to logical versions
Module OTF_LtIsTotal (Import O:OrderedTypeFull') <: LtIsTotal O.forall x y : t, x < y \/ x == y \/ y < xintros; destruct (compare_spec x y); auto. Qed. End OTF_LtIsTotal. Module OTF_to_TotalOrder (O:OrderedTypeFull) <: TotalOrder := O <+ OTF_LtIsTotal.forall x y : t, x < y \/ x == y \/ y < x
For stating properties like transitivity of leb,
we coerce bool into Prop.
Coercion is_true : bool >-> Sortclass. Hint Unfold is_true : core. Module Type HasLeb (Import T:Typ). Parameter Inline leb : t -> t -> bool. End HasLeb. Module Type HasLtb (Import T:Typ). Parameter Inline ltb : t -> t -> bool. End HasLtb. Module Type LebNotation (T:Typ)(E:HasLeb T). Infix "<=?" := E.leb (at level 35). End LebNotation. Module Type LtbNotation (T:Typ)(E:HasLtb T). Infix "<?" := E.ltb (at level 35). End LtbNotation. Module Type LebSpec (T:Typ)(X:HasLe T)(Y:HasLeb T). Parameter leb_le : forall x y, Y.leb x y = true <-> X.le x y. End LebSpec. Module Type LtbSpec (T:Typ)(X:HasLt T)(Y:HasLtb T). Parameter ltb_lt : forall x y, Y.ltb x y = true <-> X.lt x y. End LtbSpec. Module Type LeBool := Typ <+ HasLeb. Module Type LtBool := Typ <+ HasLtb. Module Type LeBool' := LeBool <+ LebNotation. Module Type LtBool' := LtBool <+ LtbNotation. Module Type LebIsTotal (Import X:LeBool'). Axiom leb_total : forall x y, (x <=? y) = true \/ (y <=? x) = true. End LebIsTotal. Module Type TotalLeBool := LeBool <+ LebIsTotal. Module Type TotalLeBool' := LeBool' <+ LebIsTotal. Module Type LebIsTransitive (Import X:LeBool'). Axiom leb_trans : Transitive X.leb. End LebIsTransitive. Module Type TotalTransitiveLeBool := TotalLeBool <+ LebIsTransitive. Module Type TotalTransitiveLeBool' := TotalLeBool' <+ LebIsTransitive.
Grouping all boolean comparison functions
Module Type HasBoolOrdFuns (T:Typ) := HasEqb T <+ HasLtb T <+ HasLeb T. Module Type HasBoolOrdFuns' (T:Typ) := HasBoolOrdFuns T <+ EqbNotation T <+ LtbNotation T <+ LebNotation T. Module Type BoolOrdSpecs (O:EqLtLe)(F:HasBoolOrdFuns O) := EqbSpec O O F <+ LtbSpec O O F <+ LebSpec O O F. Module Type OrderFunctions (E:EqLtLe) := HasCompare E <+ HasBoolOrdFuns E <+ BoolOrdSpecs E. Module Type OrderFunctions' (E:EqLtLe) := HasCompare E <+ CmpNotation E <+ HasBoolOrdFuns' E <+ BoolOrdSpecs E.
Module OTF_to_TTLB (Import O : OrderedTypeFull') <: TotalTransitiveLeBool. Definition leb x y := match compare x y with Gt => false | _ => true end.forall x y : t, leb x y <-> x <= yforall x y : t, leb x y <-> x <= yx, y:tleb x y <-> x <= yx, y:tmatch x ?= y with | Gt => false | _ => true end <-> x <= yx, y:tmatch x ?= y with | Gt => false | _ => true end <-> x < y \/ x == yx, y:tGT:y < xfalse -> x < y \/ x == yx, y:tGT:y < xx < y \/ x == y -> falsediscriminate.x, y:tGT:y < xfalse -> x < y \/ x == yx, y:tGT:y < xx < y \/ x == y -> falsex, y:tGT:y < xLE:x < y \/ x == yis_true falsex, y:tGT:y < xLE:x < y \/ x == yx < xx, y:tGT:y < xLT:x < yx < xx, y:tGT:y < xEQ:x == yx < xnow transitivity y.x, y:tGT:y < xLT:x < yx < xnow rewrite <- EQ in GT. Qed.x, y:tGT:y < xEQ:x == yx < xforall x y : t, leb x y \/ leb y xforall x y : t, leb x y \/ leb y xx, y:tleb x y \/ leb y xx, y:tx <= y \/ y <= xdestruct (compare_spec x y); intuition. Qed.x, y:t(x < y \/ x == y) \/ y < x \/ y == xTransitive (fun x y : t => leb x y)Transitive (fun x y : t => leb x y)x, y, z:tleb x y -> leb y z -> leb x zx, y, z:tx < y \/ x == y -> y < z \/ y == z -> x < z \/ x == zx, y, z:tHxy:x < yHyz:y < zx < z \/ x == zx, y, z:tHxy:x < yHyz:y == zx < z \/ x == zx, y, z:tHxy:x == yHyz:y < zx < z \/ x == zx, y, z:tHxy:x == yHyz:y == zx < z \/ x == zleft; transitivity y; auto.x, y, z:tHxy:x < yHyz:y < zx < z \/ x == zleft; rewrite <- Hyz; auto.x, y, z:tHxy:x < yHyz:y == zx < z \/ x == zleft; rewrite Hxy; auto.x, y, z:tHxy:x == yHyz:y < zx < z \/ x == zright; transitivity y; auto. Qed. Definition t := t. End OTF_to_TTLB.x, y, z:tHxy:x == yHyz:y == zx < z \/ x == z
From TotalTransitiveLeBool to OrderedTypeFull
Local Open Scope bool_scope. Module TTLB_to_OTF (Import O : TotalTransitiveLeBool') <: OrderedTypeFull. Definition t := t. Definition le x y : Prop := x <=? y. Definition eq x y : Prop := le x y /\ le y x. Definition lt x y : Prop := le x y /\ ~le y x. Definition compare x y := if x <=? y then (if y <=? x then Eq else Lt) else Gt.forall x y : O.t, CompSpec eq lt x y (compare x y)forall x y : O.t, CompSpec eq lt x y (compare x y)x, y:O.tCompSpec eq lt x y (compare x y)x, y:O.tCompSpec eq lt x y (if x <=? y then if y <=? x then Eq else Lt else Gt)x, y:O.tx <=? y = true -> CompSpec eq lt x y (if y <=? x then Eq else Lt)x, y:O.tx <=? y = false -> CompSpec eq lt x y Gtx, y:O.tx <=? y = true -> CompSpec eq lt x y (if y <=? x then Eq else Lt)x, y:O.ty <=? x = true -> x <=? y = true -> CompSpec eq lt x y Eqx, y:O.ty <=? x = false -> x <=? y = true -> CompSpec eq lt x y Ltx, y:O.ty <=? x = true -> x <=? y = true -> CompSpec eq lt x y Eqsplit; auto.x, y:O.tH:y <=? x = trueH0:x <=? y = trueeq x yx, y:O.ty <=? x = false -> x <=? y = true -> CompSpec eq lt x y Ltsplit; congruence.x, y:O.tH:y <=? x = falseH0:x <=? y = truelt x yx, y:O.tx <=? y = false -> CompSpec eq lt x y Gtdestruct (leb_total x y); split; congruence. Qed. Definition eqb x y := (x <=? y) && (y <=? x).x, y:O.tH:x <=? y = falselt y xforall x y : O.t, eqb x y <-> eq x yforall x y : O.t, eqb x y <-> eq x yx, y:O.teqb x y <-> eq x ycase leb; simpl; intuition; discriminate. Qed. Include HasEqBool2Dec.x, y:O.tx <=? y && y <=? x <-> x <=? y /\ y <=? xEquivalence eqEquivalence eqReflexive eqSymmetric eqTransitive eqReflexive eqdestruct (leb_total x x); auto.x:O.tx <=? x /\ x <=? xSymmetric eqintuition.x, y:O.tx <=? y /\ y <=? x -> y <=? x /\ x <=? yTransitive eqintuition; apply leb_trans with y; auto. Qed.x, y, z:O.tx <=? y /\ y <=? x -> y <=? z /\ z <=? y -> x <=? z /\ z <=? xStrictOrder ltStrictOrder ltIrreflexive ltTransitive ltIrreflexive ltunfold lt; red; intuition.x:O.tcomplement lt x xTransitive ltx, y, z:O.tx <=? y /\ ~ y <=? x -> y <=? z /\ ~ z <=? y -> x <=? z /\ ~ z <=? xx, y, z:O.tH1:is_true (x <=? y)H2:y <=? x -> FalseH:is_true (y <=? z)H3:z <=? y -> Falseis_true (x <=? z)x, y, z:O.tH1:is_true (x <=? y)H2:y <=? x -> FalseH:is_true (y <=? z)H3:z <=? y -> FalseH0:is_true (z <=? x)Falseapply leb_trans with y; auto.x, y, z:O.tH1:is_true (x <=? y)H2:y <=? x -> FalseH:is_true (y <=? z)H3:z <=? y -> Falseis_true (x <=? z)x, y, z:O.tH1:is_true (x <=? y)H2:y <=? x -> FalseH:is_true (y <=? z)H3:z <=? y -> FalseH0:is_true (z <=? x)Falseapply leb_trans with x; auto. Qed.x, y, z:O.tH1:is_true (x <=? y)H2:y <=? x -> FalseH:is_true (y <=? z)H3:z <=? y -> FalseH0:is_true (z <=? x)is_true (z <=? y)Proper (eq ==> eq ==> iff) ltProper (eq ==> eq ==> iff) ltProper (eq ==> eq ==> Basics.impl) ltx, x':O.tHx:eq x x'y, y':O.tHy':eq y y'H:lt x ylt x' y'x, x':O.tHx:x <=? x' /\ x' <=? xy, y':O.tHy':y <=? y' /\ y' <=? yH:x <=? y /\ ~ y <=? xx' <=? y' /\ ~ y' <=? x'x, x', y, y':O.tH0:is_true (x <=? x')H1:is_true (x' <=? x)H2:is_true (y <=? y')H3:is_true (y' <=? y)H4:is_true (x <=? y)H5:y <=? x -> Falseis_true (x' <=? y')x, x', y, y':O.tH0:is_true (x <=? x')H1:is_true (x' <=? x)H2:is_true (y <=? y')H3:is_true (y' <=? y)H4:is_true (x <=? y)H5:y <=? x -> FalseH:is_true (y' <=? x')Falsex, x', y, y':O.tH0:is_true (x <=? x')H1:is_true (x' <=? x)H2:is_true (y <=? y')H3:is_true (y' <=? y)H4:is_true (x <=? y)H5:y <=? x -> Falseis_true (x' <=? y')apply leb_trans with y; auto.x, x', y, y':O.tH0:is_true (x <=? x')H1:is_true (x' <=? x)H2:is_true (y <=? y')H3:is_true (y' <=? y)H4:is_true (x <=? y)H5:y <=? x -> Falseis_true (x <=? y')x, x', y, y':O.tH0:is_true (x <=? x')H1:is_true (x' <=? x)H2:is_true (y <=? y')H3:is_true (y' <=? y)H4:is_true (x <=? y)H5:y <=? x -> FalseH:is_true (y' <=? x')Falsex, x', y, y':O.tH0:is_true (x <=? x')H1:is_true (x' <=? x)H2:is_true (y <=? y')H3:is_true (y' <=? y)H4:is_true (x <=? y)H5:y <=? x -> FalseH:is_true (y' <=? x')is_true (y <=? x)apply leb_trans with y'; auto. Qed.x, x', y, y':O.tH0:is_true (x <=? x')H1:is_true (x' <=? x)H2:is_true (y <=? y')H3:is_true (y' <=? y)H4:is_true (x <=? y)H5:y <=? x -> FalseH:is_true (y' <=? x')is_true (y <=? x')forall x y : O.t, le x y <-> lt x y \/ eq x yforall x y : O.t, le x y <-> lt x y \/ eq x yx, y:O.tle x y <-> lt x y \/ eq x yx, y:O.tx <=? y <-> x <=? y /\ ~ y <=? x \/ x <=? y /\ y <=? xx, y:O.tx <=? y -> x <=? y /\ ~ y <=? x \/ x <=? y /\ y <=? xcase_eq (y <=? x); [right|left]; intuition; try discriminate. Qed. End TTLB_to_OTF.x, y:O.tLE:is_true (x <=? y)x <=? y /\ ~ y <=? x \/ x <=? y /\ y <=? x