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 RelationClasses. Require Import Bool Morphisms Setoid. Set Implicit Arguments. Unset Strict Implicit.
Structure with nothing inside.
Used to force a module type T into a module via Nop <+ T. (HACK!)
Module Type Nop. End Nop.
Module Type Typ. Parameter Inline(10) t : Type. End Typ.
Module Type HasEq (Import T:Typ). Parameter Inline(30) eq : t -> t -> Prop. End HasEq. Module Type Eq := Typ <+ HasEq. Module Type EqNotation (Import E:Eq). Infix "==" := eq (at level 70, no associativity). Notation "x ~= y" := (~eq x y) (at level 70, no associativity). End EqNotation. Module Type Eq' := Eq <+ EqNotation.
Module Type IsEq (Import E:Eq). Declare Instance eq_equiv : Equivalence eq. End IsEq.
Module Type IsEqOrig (Import E:Eq'). Axiom eq_refl : forall x : t, x==x. Axiom eq_sym : forall x y : t, x==y -> y==x. Axiom eq_trans : forall x y z : t, x==y -> y==z -> x==z. Hint Immediate eq_sym : core. Hint Resolve eq_refl eq_trans : core. End IsEqOrig.
Module Type HasEqDec (Import E:Eq'). Parameter eq_dec : forall x y : t, { x==y } + { ~ x==y }. End HasEqDec.
Having eq_dec is the same as having a boolean equality plus
a correctness proof.
Module Type HasEqb (Import T:Typ). Parameter Inline eqb : t -> t -> bool. End HasEqb. Module Type EqbSpec (T:Typ)(X:HasEq T)(Y:HasEqb T). Parameter eqb_eq : forall x y, Y.eqb x y = true <-> X.eq x y. End EqbSpec. Module Type EqbNotation (T:Typ)(E:HasEqb T). Infix "=?" := E.eqb (at level 70, no associativity). End EqbNotation. Module Type HasEqBool (E:Eq) := HasEqb E <+ EqbSpec E E.
From these basic blocks, we can build many combinations
of static standalone module types.
Module Type EqualityType := Eq <+ IsEq. Module Type EqualityTypeOrig := Eq <+ IsEqOrig. Module Type EqualityTypeBoth <: EqualityType <: EqualityTypeOrig := Eq <+ IsEq <+ IsEqOrig. Module Type DecidableType <: EqualityType := Eq <+ IsEq <+ HasEqDec. Module Type DecidableTypeOrig <: EqualityTypeOrig := Eq <+ IsEqOrig <+ HasEqDec. Module Type DecidableTypeBoth <: DecidableType <: DecidableTypeOrig := EqualityTypeBoth <+ HasEqDec. Module Type BooleanEqualityType <: EqualityType := Eq <+ IsEq <+ HasEqBool. Module Type BooleanDecidableType <: DecidableType <: BooleanEqualityType := Eq <+ IsEq <+ HasEqDec <+ HasEqBool. Module Type DecidableTypeFull <: DecidableTypeBoth <: BooleanDecidableType := Eq <+ IsEq <+ IsEqOrig <+ HasEqDec <+ HasEqBool.
Same, with notation for eq
Module Type EqualityType' := EqualityType <+ EqNotation. Module Type EqualityTypeOrig' := EqualityTypeOrig <+ EqNotation. Module Type EqualityTypeBoth' := EqualityTypeBoth <+ EqNotation. Module Type DecidableType' := DecidableType <+ EqNotation. Module Type DecidableTypeOrig' := DecidableTypeOrig <+ EqNotation. Module Type DecidableTypeBoth' := DecidableTypeBoth <+ EqNotation. Module Type BooleanEqualityType' := BooleanEqualityType <+ EqNotation <+ EqbNotation. Module Type BooleanDecidableType' := BooleanDecidableType <+ EqNotation <+ EqbNotation. Module Type DecidableTypeFull' := DecidableTypeFull <+ EqNotation.
Module BackportEq (E:Eq)(F:IsEq E) <: IsEqOrig E. Definition eq_refl := @Equivalence_Reflexive _ _ F.eq_equiv. Definition eq_sym := @Equivalence_Symmetric _ _ F.eq_equiv. Definition eq_trans := @Equivalence_Transitive _ _ F.eq_equiv. End BackportEq. Module UpdateEq (E:Eq)(F:IsEqOrig E) <: IsEq E.Equivalence E.eqexact (Build_Equivalence _ F.eq_refl F.eq_sym F.eq_trans). Qed. End UpdateEq. Module Backport_ET (E:EqualityType) <: EqualityTypeBoth := E <+ BackportEq. Module Update_ET (E:EqualityTypeOrig) <: EqualityTypeBoth := E <+ UpdateEq. Module Backport_DT (E:DecidableType) <: DecidableTypeBoth := E <+ BackportEq. Module Update_DT (E:DecidableTypeOrig) <: DecidableTypeBoth := E <+ UpdateEq.Equivalence E.eq
Module HasEqDec2Bool (E:Eq)(F:HasEqDec E) <: HasEqBool E. Definition eqb x y := if F.eq_dec x y then true else false.forall x y : E.t, eqb x y = true <-> E.eq x yforall x y : E.t, eqb x y = true <-> E.eq x yx, y:E.teqb x y = true <-> E.eq x yx, y:E.t(if F.eq_dec x y then true else false) = true <-> E.eq x yx, y:E.tEQ:E.eq x ytrue = true <-> E.eq x yx, y:E.tNEQ:~ E.eq x yfalse = true <-> E.eq x yauto with *.x, y:E.tEQ:E.eq x ytrue = true <-> E.eq x yx, y:E.tNEQ:~ E.eq x yfalse = true <-> E.eq x yx, y:E.tNEQ:~ E.eq x yfalse = true -> E.eq x yx, y:E.tNEQ:~ E.eq x yE.eq x y -> false = truediscriminate.x, y:E.tNEQ:~ E.eq x yfalse = true -> E.eq x yintro EQ; elim NEQ; auto. Qed. End HasEqDec2Bool. Module HasEqBool2Dec (E:Eq)(F:HasEqBool E) <: HasEqDec E.x, y:E.tNEQ:~ E.eq x yE.eq x y -> false = trueforall x y : E.t, {E.eq x y} + {~ E.eq x y}forall x y : E.t, {E.eq x y} + {~ E.eq x y}x, y:E.t{E.eq x y} + {~ E.eq x y}x, y:E.tH:F.eqb x y = true <-> E.eq x y{E.eq x y} + {~ E.eq x y}x, y:E.tH:true = true <-> E.eq x yE.eq x yx, y:E.tH:false = true <-> E.eq x y~ E.eq x yapply -> H; auto.x, y:E.tH:true = true <-> E.eq x yE.eq x yx, y:E.tH:false = true <-> E.eq x y~ E.eq x yx, y:E.tH:false = true <-> E.eq x yEQ:E.eq x yFalsediscriminate. Defined. End HasEqBool2Dec. Module Dec2Bool (E:DecidableType) <: BooleanDecidableType := E <+ HasEqDec2Bool. Module Bool2Dec (E:BooleanEqualityType) <: BooleanDecidableType := E <+ HasEqBool2Dec.x, y:E.tH:false = true <-> E.eq x yEQ:false = trueFalse
Some properties of boolean equality
Module BoolEqualityFacts (Import E : BooleanEqualityType').
eqb is compatible with eq
Proper (eq ==> eq ==> Logic.eq) eqbProper (eq ==> eq ==> Logic.eq) eqbx, x':tExx':x == x'y, y':tEyy':y == y'(x =? y) = (x' =? y')now rewrite 2 eqb_eq, Exx', Eyy'. Qed.x, x':tExx':x == x'y, y':tEyy':y == y'(x =? y) = true <-> (x' =? y') = true
Alternative specification of eqb based on reflect.
x, y:treflect (x == y) (x =? y)x, y:treflect (x == y) (x =? y)x, y:tx == y <-> (x =? y) = trueapply eqb_eq. Defined.x, y:t(x =? y) = true <-> x == y
Negated form of eqb_eq
x, y:t(x =? y) = false <-> x ~= ynow rewrite <- not_true_iff_false, eqb_eq. Qed.x, y:t(x =? y) = false <-> x ~= y
Basic equality laws for eqb
x:t(x =? x) = truenow apply eqb_eq. Qed.x:t(x =? x) = truex, y:t(x =? y) = (y =? x)x, y:t(x =? y) = (y =? x)now rewrite 2 eqb_eq. Qed.x, y:t(x =? y) = true <-> (y =? x) = true
Transitivity is a particular case of eqb_compat
End BoolEqualityFacts.
Module Type HasUsualEq (Import T:Typ) <: HasEq T. Definition eq := @Logic.eq t. End HasUsualEq. Module Type UsualEq <: Eq := Typ <+ HasUsualEq. Module Type UsualIsEq (E:UsualEq) <: IsEq E. (* No Instance syntax to avoid saturating the Equivalence tables *) Definition eq_equiv : Equivalence E.eq := eq_equivalence. End UsualIsEq. Module Type UsualIsEqOrig (E:UsualEq) <: IsEqOrig E. Definition eq_refl := @Logic.eq_refl E.t. Definition eq_sym := @Logic.eq_sym E.t. Definition eq_trans := @Logic.eq_trans E.t. End UsualIsEqOrig. Module Type UsualEqualityType <: EqualityType := UsualEq <+ UsualIsEq. Module Type UsualDecidableType <: DecidableType := UsualEq <+ UsualIsEq <+ HasEqDec. Module Type UsualDecidableTypeOrig <: DecidableTypeOrig := UsualEq <+ UsualIsEqOrig <+ HasEqDec. Module Type UsualDecidableTypeBoth <: DecidableTypeBoth := UsualEq <+ UsualIsEq <+ UsualIsEqOrig <+ HasEqDec. Module Type UsualBoolEq := UsualEq <+ HasEqBool. Module Type UsualDecidableTypeFull <: DecidableTypeFull := UsualEq <+ UsualIsEq <+ UsualIsEqOrig <+ HasEqDec <+ HasEqBool.
Some shortcuts for easily building a UsualDecidableType
Module Type MiniDecidableType. Include Typ. Parameter eq_dec : forall x y : t, {x=y}+{~x=y}. End MiniDecidableType. Module Make_UDT (M:MiniDecidableType) <: UsualDecidableTypeBoth := M <+ HasUsualEq <+ UsualIsEq <+ UsualIsEqOrig. Module Make_UDTF (M:UsualBoolEq) <: UsualDecidableTypeFull := M <+ UsualIsEq <+ UsualIsEqOrig <+ HasEqBool2Dec.