aboutsummaryrefslogtreecommitdiffhomepage
path: root/theories/Classes
diff options
context:
space:
mode:
Diffstat (limited to 'theories/Classes')
-rw-r--r--theories/Classes/Equivalence.v123
-rw-r--r--theories/Classes/Morphisms.v288
-rw-r--r--theories/Classes/Morphisms_Prop.v131
-rw-r--r--theories/Classes/Morphisms_Relations.v47
-rw-r--r--theories/Classes/RelationClasses.v226
-rw-r--r--theories/Classes/SetoidTactics.v2
6 files changed, 474 insertions, 343 deletions
diff --git a/theories/Classes/Equivalence.v b/theories/Classes/Equivalence.v
index 0ec6c11f9..d7774a2d7 100644
--- a/theories/Classes/Equivalence.v
+++ b/theories/Classes/Equivalence.v
@@ -35,23 +35,25 @@ Instance [ Equivalence A R ] =>
Definition equiv [ Equivalence A R ] : relation A := R.
-(** Shortcuts to make proof search possible (unification won't unfold equiv). *)
+Typeclasses unfold @equiv.
-Program Instance [ sa : Equivalence A ] => equiv_refl : Reflexive equiv.
+(* (** Shortcuts to make proof search possible (unification won't unfold equiv). *) *)
-Program Instance [ sa : Equivalence A ] => equiv_sym : Symmetric equiv.
+(* Program Instance [ sa : Equivalence A ] => equiv_refl : Reflexive equiv. *)
- Next Obligation.
- Proof.
- symmetry ; auto.
- Qed.
+(* Program Instance [ sa : Equivalence A ] => equiv_sym : Symmetric equiv. *)
-Program Instance [ sa : Equivalence A ] => equiv_trans : Transitive equiv.
+(* Next Obligation. *)
+(* Proof. *)
+(* symmetry ; auto. *)
+(* Qed. *)
- Next Obligation.
- Proof.
- transitivity y ; auto.
- Qed.
+(* Program Instance [ sa : Equivalence A ] => equiv_trans : Transitive equiv. *)
+
+(* Next Obligation. *)
+(* Proof. *)
+(* transitivity y ; auto. *)
+(* Qed. *)
(** Overloaded notations for setoid equivalence and inequivalence. Not to be confused with [eq] and [=]. *)
@@ -64,23 +66,6 @@ Notation " x =/= y " := (complement equiv x y) (at level 70, no associativity) :
Open Local Scope equiv_scope.
-(** Use the [clsubstitute] command which substitutes an equality in every hypothesis. *)
-
-Ltac setoid_subst H :=
- match type of H with
- ?x === ?y => substitute H ; clear H x
- end.
-
-Ltac setoid_subst_nofail :=
- match goal with
- | [ H : ?x === ?y |- _ ] => setoid_subst H ; setoid_subst_nofail
- | _ => idtac
- end.
-
-(** [subst*] will try its best at substituting every equality in the goal. *)
-
-Tactic Notation "subst" "*" := subst_no_fail ; setoid_subst_nofail.
-
Lemma nequiv_equiv_trans : forall [ Equivalence A ] (x y z : A), x =/= y -> y === z -> x =/= z.
Proof with auto.
intros; intro.
@@ -97,6 +82,23 @@ Proof.
contradiction.
Qed.
+(** Use the [substitute] command which substitutes an applied relation in every hypothesis. *)
+
+Ltac setoid_subst H :=
+ match type of H with
+ ?x === ?y => substitute H ; clear H x
+ end.
+
+Ltac setoid_subst_nofail :=
+ match goal with
+ | [ H : ?x === ?y |- _ ] => setoid_subst H ; setoid_subst_nofail
+ | _ => idtac
+ end.
+
+(** [subst*] will try its best at substituting every equality in the goal. *)
+
+Tactic Notation "subst" "*" := subst_no_fail ; setoid_subst_nofail.
+
Ltac equiv_simplify_one :=
match goal with
| [ H : ?x === ?x |- _ ] => clear H
@@ -117,34 +119,28 @@ Ltac equivify := repeat equivify_tac.
(** Every equivalence relation gives rise to a morphism, as it is Transitive and Symmetric. *)
-Instance [ sa : Equivalence ] => equiv_morphism : Morphism (equiv ++> equiv ++> iff) equiv :=
- respect := respect.
-
-(** The partial application too as it is Reflexive. *)
+(* Instance [ sa : Equivalence ] => equiv_morphism : Morphism (equiv ++> equiv ++> iff) equiv := *)
+(* respect := respect. *)
-Instance [ sa : Equivalence A ] (x : A) =>
- equiv_partial_app_morphism : Morphism (equiv ++> iff) (equiv x) :=
- respect := respect.
+(* (** The partial application too as it is Reflexive. *) *)
-Definition type_eq : relation Type :=
- fun x y => x = y.
+(* Instance [ sa : Equivalence A ] (x : A) => *)
+(* equiv_partial_app_morphism : Morphism (equiv ++> iff) (equiv x) := *)
+(* respect := respect. *)
-Program Instance type_equivalence : Equivalence Type type_eq.
+(** Instance not exported by default, as comparing types for equivalence may be unintentional. *)
- Solve Obligations using constructor ; unfold type_eq ; program_simpl.
+Section Type_Equivalence.
-Ltac morphism_tac := try red ; unfold arrow ; intros ; program_simpl ; try tauto.
-
-Ltac obligations_tactic ::= morphism_tac.
-
-(** These are morphisms used to rewrite at the top level of a proof,
- using [iff_impl_id_morphism] if the proof is in [Prop] and
- [eq_arrow_id_morphism] if it is in Type. *)
-
-Program Instance iff_impl_id_morphism :
- Morphism (iff ++> impl) id.
+ Definition type_eq : relation Type :=
+ fun x y => x = y.
+
+ Program Instance type_equivalence : Equivalence Type type_eq.
+
+ Next Obligation.
+ Proof. unfold type_eq in *. subst. reflexivity. Qed.
-(* Program Instance eq_arrow_id_morphism : ? Morphism (eq +++> arrow) id. *)
+End Type_Equivalence.
(** Partial equivs don't require reflexivity so we can build a partial equiv on the function space. *)
@@ -152,11 +148,32 @@ Class PartialEquivalence (carrier : Type) (pequiv : relation carrier) :=
pequiv_prf :> PER carrier pequiv.
Definition pequiv [ PartialEquivalence A R ] : relation A := R.
+Typeclasses unfold @pequiv.
(** Overloaded notation for partial equiv equivalence. *)
Notation " x =~= y " := (pequiv x y) (at level 70, no associativity) : type_scope.
-(** Reset the default Program tactic. *)
+Section Respecting.
+
+ (** Here we build an equivalence instance for functions which relates respectful ones only,
+ we do not export it. *)
+
+ Definition respecting [ Equivalence A (R : relation A), Equivalence B (R' : relation B) ] : Type :=
+ { morph : A -> B | respectful R R' morph morph }.
+
+ Program Instance [ Equivalence A R, Equivalence B R' ] =>
+ respecting_equiv : Equivalence respecting
+ (fun (f g : respecting) => forall (x y : A), R x y -> R' (proj1_sig f x) (proj1_sig g y)).
+
+ Solve Obligations using unfold respecting in * ; simpl_relation ; program_simpl.
+
+ Next Obligation.
+ Proof.
+ unfold respecting in *. program_simpl. red in H2,H3,H4.
+ transitivity (y x0) ; auto.
+ transitivity (y y0) ; auto.
+ symmetry. auto.
+ Qed.
-Ltac obligations_tactic ::= program_simpl.
+End Respecting. \ No newline at end of file
diff --git a/theories/Classes/Morphisms.v b/theories/Classes/Morphisms.v
index d10cb9724..7cabc836d 100644
--- a/theories/Classes/Morphisms.v
+++ b/theories/Classes/Morphisms.v
@@ -1,4 +1,4 @@
-(* -*- coq-prog-args: ("-emacs-U" "-top" "Coq.Classes.Morphisms") -*- *)
+(* -*- coq-prog-args: ("-emacs-U" "-top" "Coq.Classes.Morphisms"); compile-command: "make -C ../.. TIME='time'" -*- *)
(************************************************************************)
(* v * The Coq Proof Assistant / The Coq Development Team *)
(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
@@ -7,7 +7,7 @@
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
-(* Typeclass-based morphisms with standard instances for equivalence relations.
+(* Typeclass-based morphism definition and standard, minimal instances.
Author: Matthieu Sozeau
Institution: LRI, CNRS UMR 8623 - UniversitÃcopyright Paris Sud
@@ -26,7 +26,7 @@ Unset Strict Implicit.
(** * Morphisms.
We now turn to the definition of [Morphism] and declare standard instances.
- These will be used by the [clrewrite] tactic later. *)
+ These will be used by the [setoid_rewrite] tactic later. *)
(** Respectful morphisms. *)
@@ -71,49 +71,6 @@ Class Morphism A (R : relation A) (m : A) : Prop :=
Arguments Scope Morphism [type_scope signature_scope].
-(** Here we build an equivalence instance for functions which relates respectful ones only. *)
-
-Definition respecting [ Equivalence A (R : relation A), Equivalence B (R' : relation B) ] : Type :=
- { morph : A -> B | respectful R R' morph morph }.
-
-Ltac obligations_tactic ::= program_simpl.
-
-Program Instance [ Equivalence A R, Equivalence B R' ] =>
- respecting_equiv : Equivalence respecting
- (fun (f g : respecting) => forall (x y : A), R x y -> R' (proj1_sig f x) (proj1_sig g y)).
-
- Next Obligation.
- Proof.
- red ; intros.
- destruct x ; simpl.
- apply r ; auto.
- Qed.
-
- Next Obligation.
- Proof.
- red ; intros.
- symmetry ; apply H.
- symmetry ; auto.
- Qed.
-
- Next Obligation.
- Proof.
- red ; intros.
- transitivity (proj1_sig y y0).
- apply H ; auto.
- apply H0. reflexivity.
- Qed.
-
-(** Can't use the definition [notT] as it gives a universe inconsistency. *)
-
-Ltac obligations_tactic ::= program_simpl ; simpl_relation.
-
-Program Instance not_impl_morphism :
- Morphism (Prop -> Prop) (impl --> impl) not.
-
-Program Instance not_iff_morphism :
- Morphism (Prop -> Prop) (iff ++> iff) not.
-
(** We make the type implicit, it can be infered from the relations. *)
Implicit Arguments Morphism [A].
@@ -139,41 +96,41 @@ Proof. firstorder. Qed.
(** [Morphism] is itself a covariant morphism for [subrelation]. *)
-Lemma subrelation_morphism [ subrelation A R₁ R₂, ! Morphism R₁ m ] : Morphism R₂ m.
+Lemma subrelation_morphism [ sub : subrelation A R₁ R₂, mor : Morphism A R₁ m ] : Morphism R₂ m.
Proof.
- intros. apply* H. apply H0.
+ intros. apply sub. apply mor.
Qed.
Instance morphism_subrelation_morphism :
Morphism (subrelation ++> @eq _ ==> impl) (@Morphism A).
Proof. reduce. subst. firstorder. Qed.
-Inductive done : nat -> Type :=
- did : forall n : nat, done n.
+(** We use an external tactic to manage the application of subrelation, which is otherwise
+ always applicable. We allow its use only once per branch. *)
+
+Inductive subrelation_done : Prop :=
+ did_subrelation : subrelation_done.
Ltac subrelation_tac :=
match goal with
- | [ H : done 1 |- @Morphism _ _ _ ] => fail
+ | [ H : subrelation_done |- _ ] => fail
| [ |- @Morphism _ _ _ ] => let H := fresh "H" in
- set(H:=did 1) ; eapply @subrelation_morphism
+ set(H:=did_subrelation) ; eapply @subrelation_morphism
end.
-(* Hint Resolve @subrelation_morphism 4 : typeclass_instances. *)
-
Hint Extern 4 (@Morphism _ _ _) => subrelation_tac : typeclass_instances.
-(** Logical implication [impl] is a morphism for logical equivalence. *)
+(** Essential subrelation instances for [iff], [impl] and [pointwise_relation]. *)
-Program Instance iff_iff_iff_impl_morphism : Morphism (iff ==> iff ==> iff) impl.
+Instance iff_impl_subrelation : subrelation iff impl.
+Proof. firstorder. Qed.
-(* Typeclasses eauto := debug. *)
+Instance iff_inverse_impl_subrelation : subrelation iff (inverse impl).
+Proof. firstorder. Qed.
-Program Instance [ Symmetric A R, Morphism _ (R ==> impl) m ] => Reflexive_impl_iff : Morphism (R ==> iff) m.
-
- Next Obligation.
- Proof.
- split ; apply respect ; [ auto | symmetry ] ; auto.
- Qed.
+Instance [ subrelation A R R' ] => pointwise_subrelation :
+ subrelation (pointwise_relation (A:=B) R) (pointwise_relation R') | 4.
+Proof. reduce. unfold pointwise_relation in *. apply subrelation0. apply H. Qed.
(** The complement of a relation conserves its morphisms. *)
@@ -183,28 +140,26 @@ Program Instance [ mR : Morphism (A -> A -> Prop) (RA ==> RA ==> iff) R ] =>
Next Obligation.
Proof.
unfold complement.
- pose (respect).
- pose (r x y H).
- pose (r0 x0 y0 H0).
+ pose (mR x y H x0 y0 H0).
intuition.
Qed.
(** The inverse too. *)
-Program Instance [ Morphism (A -> _) (RA ==> RA ==> iff) R ] =>
+Program Instance [ mor : Morphism (A -> _) (RA ==> RA ==> iff) R ] =>
inverse_morphism : Morphism (RA ==> RA ==> iff) (inverse R).
Next Obligation.
Proof.
- apply respect ; auto.
+ apply mor ; auto.
Qed.
-Program Instance [ Morphism (A -> B -> C) (RA ==> RB ==> RC) f ] =>
+Program Instance [ mor : Morphism (A -> B -> C) (RA ==> RB ==> RC) f ] =>
flip_morphism : Morphism (RB ==> RA ==> RC) (flip f).
Next Obligation.
Proof.
- apply respect ; auto.
+ apply mor ; auto.
Qed.
(** Every Transitive relation gives rise to a binary morphism on [impl],
@@ -229,18 +184,6 @@ Program Instance [ Transitive A R ] =>
apply* trans_contra_co_morphism ; eauto. eauto.
Qed.
-(* Program Instance [ Transitive A (R : relation A), Symmetric A R ] => *)
-(* trans_sym_contra_co_inv_impl_morphism : ? Morphism (R --> R ++> inverse impl) R. *)
-
-(* Next Obligation. *)
-(* Proof with auto. *)
-(* trans y... *)
-(* sym... *)
-(* trans y0... *)
-(* sym... *)
-(* Qed. *)
-
-
(** Morphism declarations for partial applications. *)
Program Instance [ Transitive A R ] (x : A) =>
@@ -286,18 +229,6 @@ Program Instance [ Equivalence A R ] (x : A) =>
symmetry...
Qed.
-(** With Symmetric relations, variance is no issue ! *)
-
-(* Program Instance (A B : Type) (R : relation A) (R' : relation B) *)
-(* [ Morphism _ (R ==> R') m ] [ Symmetric A R ] => *)
-(* sym_contra_morphism : Morphism (R --> R') m. *)
-
-(* Next Obligation. *)
-(* Proof with auto. *)
-(* repeat (red ; intros). apply respect. *)
-(* sym... *)
-(* Qed. *)
-
(** [R] is Reflexive, hence we can build the needed proof. *)
Program Instance [ Morphism (A -> B) (R ==> R') m, Reflexive _ R ] (x : A) =>
@@ -360,57 +291,9 @@ Program Instance iff_impl_id :
Program Instance inverse_iff_impl_id :
Morphism (iff --> impl) id.
-(** Standard instances for [iff] and [impl]. *)
-
-(** Logical conjunction. *)
-
-Program Instance and_impl_iff_morphism :
- Morphism (impl ==> iff ==> impl) and.
-
-Program Instance and_iff_impl_morphism :
- Morphism (iff ==> impl ==> impl) and.
-
-Program Instance and_inverse_impl_iff_morphism :
- Morphism (inverse impl ==> iff ==> inverse impl) and.
-
-Program Instance and_iff_inverse_impl_morphism :
- Morphism (iff ==> inverse impl ==> inverse impl) and.
-
-Program Instance and_iff_morphism :
- Morphism (iff ==> iff ==> iff) and.
-
-(** Logical disjunction. *)
-
-Program Instance or_impl_iff_morphism :
- Morphism (impl ==> iff ==> impl) or.
-
-Program Instance or_iff_impl_morphism :
- Morphism (iff ==> impl ==> impl) or.
-
-Program Instance or_inverse_impl_iff_morphism :
- Morphism (inverse impl ==> iff ==> inverse impl) or.
-
-Program Instance or_iff_inverse_impl_morphism :
- Morphism (iff ==> inverse impl ==> inverse impl) or.
-
-Program Instance or_iff_morphism :
- Morphism (iff ==> iff ==> iff) or.
-
(** Coq functions are morphisms for leibniz equality,
applied only if really needed. *)
-(* Instance {A B : Type} (m : A -> B) => *)
-(* any_eq_eq_morphism : Morphism (@Logic.eq A ==> @Logic.eq B) m | 4. *)
-(* Proof. *)
-(* red ; intros. subst ; reflexivity. *)
-(* Qed. *)
-
-(* Instance {A : Type} (m : A -> Prop) => *)
-(* any_eq_iff_morphism : Morphism (@Logic.eq A ==> iff) m | 4. *)
-(* Proof. *)
-(* red ; intros. subst ; split; trivial. *)
-(* Qed. *)
-
Instance (A : Type) [ Reflexive B R ] (m : A -> B) =>
eq_reflexive_morphism : Morphism (@Logic.eq A ==> R) m | 3.
Proof. simpl_relation. Qed.
@@ -419,18 +302,13 @@ Instance (A : Type) [ Reflexive B R' ] =>
Reflexive (@Logic.eq A ==> R').
Proof. simpl_relation. Qed.
-Instance [ Morphism (A -> B) (inverse R ==> R') m ] =>
- Morphism (R ==> inverse R') m | 10.
-Proof. firstorder. Qed.
-
(** [respectful] is a morphism for relation equivalence. *)
Instance respectful_morphism :
Morphism (relation_equivalence ++> relation_equivalence ++> relation_equivalence) (@respectful A B).
Proof.
- do 2 red ; intros.
- unfold respectful, relation_equivalence in *.
- red ; intros.
+ reduce.
+ unfold respectful, relation_equivalence, predicate_equivalence in * ; simpl in *.
split ; intros.
rewrite <- H0.
@@ -452,21 +330,18 @@ Proof.
split ; intros ; intuition.
Qed.
+
Class (A : Type) (R : relation A) => Normalizes (m : A) (m' : A) : Prop :=
normalizes : R m m'.
Instance (A : Type) (R : relation A) (B : Type) (R' : relation B) =>
- Normalizes relation_equivalence (inverse R ==> inverse R') (inverse (R ==> R')) .
-Proof.
- reduce.
- symmetry ; apply inverse_respectful.
-Qed.
+ Normalizes subrelation (inverse R ==> inverse R') (inverse (R ==> R')) .
+Proof. simpl_relation. Qed.
Instance [ Normalizes (relation B) relation_equivalence R' (inverse R'') ] =>
! Normalizes (relation (A -> B)) relation_equivalence (inverse R ==> R') (inverse (R ==> R'')) .
-Proof.
- red.
- pose normalizes.
+Proof. red ; intros.
+ pose normalizes as r.
setoid_rewrite r.
setoid_rewrite inverse_respectful.
reflexivity.
@@ -479,23 +354,23 @@ Program Instance [ Morphism A R m ] =>
Instance morphism_morphism : Morphism (relation_equivalence ==> @eq _ ==> iff) (@Morphism A).
Proof.
- simpl_relation.
- unfold relation_equivalence in H.
+ simpl_relation.
+ reduce in H.
split ; red ; intros.
setoid_rewrite <- H.
- apply respect.
+ apply H0.
setoid_rewrite H.
- apply respect.
+ apply H0.
Qed.
-
+
Lemma morphism_releq_morphism
[ Normalizes (relation A) relation_equivalence R R',
Morphism _ R' m ] : Morphism R m.
Proof.
intros.
- pose respect.
- assert(n:=normalizes).
- setoid_rewrite n.
+ pose respect as r.
+ pose normalizes as norm.
+ setoid_rewrite norm.
assumption.
Qed.
@@ -510,86 +385,3 @@ Ltac morphism_normalization :=
Hint Extern 5 (@Morphism _ _ _) => morphism_normalization : typeclass_instances.
-(** Morphisms for relations *)
-
-Instance [ PartialOrder A eqA R ] =>
- partial_order_morphism : Morphism (eqA ==> eqA ==> iff) R.
-Proof with auto.
- intros. rewrite partial_order_equivalence.
- simpl_relation. firstorder.
- transitivity x... transitivity x0...
- transitivity y... transitivity y0...
-Qed.
-
-Instance Morphism (relation_equivalence (A:=A) ==>
- relation_equivalence ==> relation_equivalence) relation_conjunction.
- Proof. firstorder. Qed.
-
-Instance Morphism (relation_equivalence (A:=A) ==>
- relation_equivalence ==> relation_equivalence) relation_disjunction.
- Proof. firstorder. Qed.
-
-
-(** Morphisms for quantifiers *)
-
-Program Instance {A : Type} => ex_iff_morphism : Morphism (pointwise_relation iff ==> iff) (@ex A).
-
- Next Obligation.
- Proof.
- unfold pointwise_relation in H.
- split ; intros.
- destruct H0 as [x₁ H₁].
- exists x₁. rewrite H in H₁. assumption.
-
- destruct H0 as [x₁ H₁].
- exists x₁. rewrite H. assumption.
- Qed.
-
-Program Instance {A : Type} => ex_impl_morphism :
- Morphism (pointwise_relation impl ==> impl) (@ex A).
-
- Next Obligation.
- Proof.
- unfold pointwise_relation in H.
- exists H0. apply H. assumption.
- Qed.
-
-Program Instance {A : Type} => ex_inverse_impl_morphism :
- Morphism (pointwise_relation (inverse impl) ==> inverse impl) (@ex A).
-
- Next Obligation.
- Proof.
- unfold pointwise_relation in H.
- exists H0. apply H. assumption.
- Qed.
-
-Program Instance {A : Type} => all_iff_morphism :
- Morphism (pointwise_relation iff ==> iff) (@all A).
-
- Next Obligation.
- Proof.
- unfold pointwise_relation, all in *.
- intuition ; specialize (H x0) ; intuition.
- Qed.
-
-Program Instance {A : Type} => all_impl_morphism :
- Morphism (pointwise_relation impl ==> impl) (@all A).
-
- Next Obligation.
- Proof.
- unfold pointwise_relation, all in *.
- intuition ; specialize (H x0) ; intuition.
- Qed.
-
-Program Instance {A : Type} => all_inverse_impl_morphism :
- Morphism (pointwise_relation (inverse impl) ==> inverse impl) (@all A).
-
- Next Obligation.
- Proof.
- unfold pointwise_relation, all in *.
- intuition ; specialize (H x0) ; intuition.
- Qed.
-
-Lemma inverse_pointwise_relation A (R : relation A) :
- relation_equivalence (pointwise_relation (inverse R)) (inverse (pointwise_relation (A:=A) R)).
-Proof. reflexivity. Qed.
diff --git a/theories/Classes/Morphisms_Prop.v b/theories/Classes/Morphisms_Prop.v
new file mode 100644
index 000000000..d22ab06cb
--- /dev/null
+++ b/theories/Classes/Morphisms_Prop.v
@@ -0,0 +1,131 @@
+(* -*- coq-prog-args: ("-emacs-U" "-top" "Coq.Classes.Morphisms") -*- *)
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* Morphism instances for propositional connectives.
+
+ Author: Matthieu Sozeau
+ Institution: LRI, CNRS UMR 8623 - UniversitÃcopyright Paris Sud
+ 91405 Orsay, France *)
+
+Require Import Coq.Classes.Morphisms.
+Require Import Coq.Program.Program.
+
+(** Standard instances for [not], [iff] and [impl]. *)
+
+(** Logical negation. *)
+
+Program Instance not_impl_morphism :
+ Morphism (impl --> impl) not.
+
+Program Instance not_iff_morphism :
+ Morphism (iff ++> iff) not.
+
+(** Logical conjunction. *)
+
+Program Instance and_impl_iff_morphism :
+ Morphism (impl ==> impl ==> impl) and.
+
+(* Program Instance and_impl_iff_morphism : *)
+(* Morphism (impl ==> iff ==> impl) and. *)
+
+(* Program Instance and_iff_impl_morphism : *)
+(* Morphism (iff ==> impl ==> impl) and. *)
+
+(* Program Instance and_inverse_impl_iff_morphism : *)
+(* Morphism (inverse impl ==> iff ==> inverse impl) and. *)
+
+(* Program Instance and_iff_inverse_impl_morphism : *)
+(* Morphism (iff ==> inverse impl ==> inverse impl) and. *)
+
+Program Instance and_iff_morphism :
+ Morphism (iff ==> iff ==> iff) and.
+
+(** Logical disjunction. *)
+
+Program Instance or_impl_iff_morphism :
+ Morphism (impl ==> impl ==> impl) or.
+
+(* Program Instance or_impl_iff_morphism : *)
+(* Morphism (impl ==> iff ==> impl) or. *)
+
+(* Program Instance or_iff_impl_morphism : *)
+(* Morphism (iff ==> impl ==> impl) or. *)
+
+(* Program Instance or_inverse_impl_iff_morphism : *)
+(* Morphism (inverse impl ==> iff ==> inverse impl) or. *)
+
+(* Program Instance or_iff_inverse_impl_morphism : *)
+(* Morphism (iff ==> inverse impl ==> inverse impl) or. *)
+
+Program Instance or_iff_morphism :
+ Morphism (iff ==> iff ==> iff) or.
+
+(** Logical implication [impl] is a morphism for logical equivalence. *)
+
+Program Instance iff_iff_iff_impl_morphism : Morphism (iff ==> iff ==> iff) impl.
+
+(** Morphisms for quantifiers *)
+
+Program Instance {A : Type} => ex_iff_morphism : Morphism (pointwise_relation iff ==> iff) (@ex A).
+
+ Next Obligation.
+ Proof.
+ unfold pointwise_relation in H.
+ split ; intros.
+ destruct H0 as [x₁ H₁].
+ exists x₁. rewrite H in H₁. assumption.
+
+ destruct H0 as [x₁ H₁].
+ exists x₁. rewrite H. assumption.
+ Qed.
+
+Program Instance {A : Type} => ex_impl_morphism :
+ Morphism (pointwise_relation impl ==> impl) (@ex A).
+
+ Next Obligation.
+ Proof.
+ unfold pointwise_relation in H.
+ exists H0. apply H. assumption.
+ Qed.
+
+Program Instance {A : Type} => ex_inverse_impl_morphism :
+ Morphism (pointwise_relation (inverse impl) ==> inverse impl) (@ex A).
+
+ Next Obligation.
+ Proof.
+ unfold pointwise_relation in H.
+ exists H0. apply H. assumption.
+ Qed.
+
+Program Instance {A : Type} => all_iff_morphism :
+ Morphism (pointwise_relation iff ==> iff) (@all A).
+
+ Next Obligation.
+ Proof.
+ unfold pointwise_relation, all in *.
+ intuition ; specialize (H x0) ; intuition.
+ Qed.
+
+Program Instance {A : Type} => all_impl_morphism :
+ Morphism (pointwise_relation impl ==> impl) (@all A).
+
+ Next Obligation.
+ Proof.
+ unfold pointwise_relation, all in *.
+ intuition ; specialize (H x0) ; intuition.
+ Qed.
+
+Program Instance {A : Type} => all_inverse_impl_morphism :
+ Morphism (pointwise_relation (inverse impl) ==> inverse impl) (@all A).
+
+ Next Obligation.
+ Proof.
+ unfold pointwise_relation, all in *.
+ intuition ; specialize (H x0) ; intuition.
+ Qed.
diff --git a/theories/Classes/Morphisms_Relations.v b/theories/Classes/Morphisms_Relations.v
new file mode 100644
index 000000000..284810e94
--- /dev/null
+++ b/theories/Classes/Morphisms_Relations.v
@@ -0,0 +1,47 @@
+(* -*- coq-prog-args: ("-emacs-U" "-top" "Coq.Classes.Morphisms") -*- *)
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* Morphism instances for relations.
+
+ Author: Matthieu Sozeau
+ Institution: LRI, CNRS UMR 8623 - UniversitÃcopyright Paris Sud
+ 91405 Orsay, France *)
+
+(** Morphisms for relations *)
+
+Instance relation_conjunction_morphism : Morphism (relation_equivalence (A:=A) ==>
+ relation_equivalence ==> relation_equivalence) relation_conjunction.
+ Proof. firstorder. Qed.
+
+Instance relation_disjunction_morphism : Morphism (relation_equivalence (A:=A) ==>
+ relation_equivalence ==> relation_equivalence) relation_disjunction.
+ Proof. firstorder. Qed.
+
+(* Predicate equivalence is exactly the same as the pointwise lifting of [iff]. *)
+
+Require Import List.
+
+Lemma predicate_equivalence_pointwise (l : list Type) :
+ Morphism (@predicate_equivalence l ==> lift_pointwise l iff) id.
+Proof. do 2 red. unfold predicate_equivalence. auto. Qed.
+
+Lemma predicate_implication_pointwise (l : list Type) :
+ Morphism (@predicate_implication l ==> lift_pointwise l impl) id.
+Proof. do 2 red. unfold predicate_implication. auto. Qed.
+
+(** The instanciation at relation allows to rewrite applications of relations [R x y] to [R' x y] *)
+(* when [R] and [R'] are in [relation_equivalence]. *)
+
+Instance relation_equivalence_pointwise :
+ Morphism (relation_equivalence ==> pointwise_relation (A:=A) (pointwise_relation (A:=A) iff)) id.
+Proof. apply (predicate_equivalence_pointwise (l:=(cons A (cons A nil)))). Qed.
+
+Instance subrelation_pointwise :
+ Morphism (subrelation ==> pointwise_relation (A:=A) (pointwise_relation (A:=A) impl)) id.
+Proof. apply (predicate_implication_pointwise (l:=(cons A (cons A nil)))). Qed.
diff --git a/theories/Classes/RelationClasses.v b/theories/Classes/RelationClasses.v
index f5d3cc1c4..8dfb662b2 100644
--- a/theories/Classes/RelationClasses.v
+++ b/theories/Classes/RelationClasses.v
@@ -21,9 +21,6 @@ Require Import Coq.Program.Basics.
Require Import Coq.Program.Tactics.
Require Export Coq.Relations.Relation_Definitions.
-Set Implicit Arguments.
-Unset Strict Implicit.
-
(** Default relation on a given support. *)
Class DefaultRelation A (R : relation A).
@@ -50,6 +47,9 @@ Proof. reflexivity. Qed.
(** We rebind relations in separate classes to be able to overload each proof. *)
+Set Implicit Arguments.
+Unset Strict Implicit.
+
Class Reflexive A (R : relation A) :=
reflexivity : forall x, R x x.
@@ -73,6 +73,8 @@ Implicit Arguments Transitive [A].
Hint Resolve @irreflexivity : ord.
+Unset Implicit Arguments.
+
(** We can already dualize all these properties. *)
Program Instance [ Reflexive A R ] => flip_Reflexive : Reflexive (flip R) :=
@@ -115,12 +117,20 @@ Program Instance [ Symmetric A (R : relation A) ] => complement_Symmetric : Symm
(** * Standard instances. *)
+Ltac reduce_hyp H :=
+ match type of H with
+ | context [ _ <-> _ ] => fail 1
+ | _ => red in H ; try reduce_hyp H
+ end.
+
Ltac reduce_goal :=
match goal with
| [ |- _ <-> _ ] => fail 1
| _ => red ; intros ; try reduce_goal
end.
+Tactic Notation "reduce" "in" hyp(Hid) := reduce_hyp Hid.
+
Ltac reduce := reduce_goal.
Tactic Notation "apply" "*" constr(t) :=
@@ -203,52 +213,187 @@ Program Instance eq_equivalence : Equivalence A (@eq A) | 10.
Program Instance iff_equivalence : Equivalence Prop iff.
-(** The following is not definable. *)
-(*
-Program Instance [ sa : Equivalence a R, sb : Equivalence b R' ] => equiv_setoid :
- Equivalence (a -> b)
- (fun f g => forall (x y : a), R x y -> R' (f x) (g y)).
-*)
+(** We now develop a generalization of results on relations for arbitrary predicates.
+ The resulting theory can be applied to homogeneous binary relations but also to
+ arbitrary n-ary predicates. *)
+Require Import List.
-(** We define the various operations which define the algebra on relations.
- They are essentially liftings of the logical operations. *)
+(* Notation " [ ] " := nil : list_scope. *)
+(* Notation " [ x ; .. ; y ] " := (cons x .. (cons y nil) ..) (at level 1) : list_scope. *)
-Definition relation_equivalence {A : Type} : relation (relation A) :=
- fun (R R' : relation A) => forall x y, R x y <-> R' x y.
+(* Open Local Scope list_scope. *)
-Class subrelation {A:Type} (R R' : relation A) :=
- is_subrelation : forall x y, R x y -> R' x y.
+(** A compact representation of non-dependent arities, with the codomain singled-out. *)
-Implicit Arguments subrelation [[A]].
+Fixpoint arrows (l : list Type) (r : Type) : Type :=
+ match l with
+ | nil => r
+ | A :: l' => A -> arrows l' r
+ end.
+(** We can define abbreviations for operation and relation types based on [arrows]. *)
-Definition relation_conjunction {A} (R : relation A) (R' : relation A) : relation A :=
- fun x y => R x y /\ R' x y.
+Definition unary_operation A := arrows (cons A nil) A.
+Definition binary_operation A := arrows (cons A (cons A nil)) A.
+Definition ternary_operation A := arrows (cons A (cons A (cons A nil))) A.
-Definition relation_disjunction {A} (R : relation A) (R' : relation A) : relation A :=
- fun x y => R x y \/ R' x y.
+(** We define n-ary [predicate]s as functions into [Prop]. *)
-(* Infix "<R>" := relation_equivalence (at level 95, no associativity) : relation_scope. *)
-(* Infix "-R>" := subrelation (at level 70) : relation_scope. *)
-(* Infix "/R\" := relation_conjunction (at level 80, right associativity) : relation_scope. *)
-(* Infix "\R/" := relation_disjunction (at level 85, right associativity) : relation_scope. *)
+Definition predicate (l : list Type) := arrows l Prop.
-(* Open Local Scope relation_scope. *)
+(** Unary predicates, or sets. *)
-(** Relation equivalence is an equivalence, and subrelation defines a partial order. *)
+Definition unary_predicate A := predicate (cons A nil).
-Program Instance relation_equivalence_equivalence :
- Equivalence (relation A) relation_equivalence.
+(** Homogenous binary relations, equivalent to [relation A]. *)
+
+Definition binary_relation A := predicate (cons A (cons A nil)).
+
+(** We can close a predicate by universal or existential quantification. *)
+
+Fixpoint predicate_all (l : list Type) : predicate l -> Prop :=
+ match l with
+ | nil => fun f => f
+ | A :: tl => fun f => forall x : A, predicate_all tl (f x)
+ end.
+
+Fixpoint predicate_exists (l : list Type) : predicate l -> Prop :=
+ match l with
+ | nil => fun f => f
+ | A :: tl => fun f => exists x : A, predicate_exists tl (f x)
+ end.
+
+(** Pointwise extension of a binary operation on [T] to a binary operation
+ on functions whose codomain is [T]. *)
+
+Fixpoint pointwise_extension {l : list Type} {T : Type}
+ (op : binary_operation T) : binary_operation (arrows l T) :=
+ match l with
+ | nil => fun R R' => op R R'
+ | A :: tl => fun R R' =>
+ fun x => pointwise_extension op (R x) (R' x)
+ end.
+
+(** For an operator on [Prop] this lifts the operator to a binary operation. *)
+
+Definition pointwise_relation_extension (l : list Type) (op : binary_relation Prop) :
+ binary_operation (predicate l) := pointwise_extension op.
+
+(** Pointwise lifting, equivalent to doing [pointwise_extension] and closing using [predicate_all]. *)
+
+Fixpoint lift_pointwise (l : list Type) (op : binary_relation Prop) : binary_relation (predicate l) :=
+ match l with
+ | nil => fun R R' => op R R'
+ | A :: tl => fun R R' =>
+ forall x, lift_pointwise tl op (R x) (R' x)
+ end.
+
+(** The n-ary equivalence relation, defined by lifting the 0-ary [iff] relation. *)
+
+Definition predicate_equivalence {l : list Type} : binary_relation (predicate l) :=
+ lift_pointwise l iff.
+
+(** The n-ary implication relation, defined by lifting the 0-ary [impl] relation. *)
+
+Definition predicate_implication {l : list Type} :=
+ lift_pointwise l impl.
+
+(** Notations for pointwise equivalence and implication of predicates. *)
+
+Infix "<∙>" := predicate_equivalence (at level 95, no associativity) : predicate_scope.
+Infix "-∙>" := predicate_implication (at level 70) : predicate_scope.
+
+Open Local Scope predicate_scope.
+
+(** The pointwise liftings of conjunction and disjunctions.
+ Note that these are [binary_operation]s, building new relations out of old ones. *)
+
+Definition predicate_intersection {l : list Type} : binary_operation (predicate l) :=
+ pointwise_relation_extension l and.
+
+Definition predicate_union {l : list Type} : binary_operation (predicate l) :=
+ pointwise_relation_extension l or.
+
+Infix "/∙\" := predicate_intersection (at level 80, right associativity) : predicate_scope.
+Infix "\∙/" := predicate_union (at level 85, right associativity) : predicate_scope.
+
+(** The always [True] and always [False] predicates. *)
+
+Fixpoint true_predicate {l : list Type} : predicate l :=
+ match l with
+ | nil => True
+ | A :: tl => fun _ => @true_predicate tl
+ end.
+
+Fixpoint false_predicate {l : list Type} : predicate l :=
+ match l with
+ | nil => False
+ | A :: tl => fun _ => @false_predicate tl
+ end.
+
+Notation "∙⊤∙" := true_predicate : predicate_scope.
+Notation "∙⊥∙" := false_predicate : predicate_scope.
+
+(** Predicate equivalence is an equivalence, and predicate implication defines a preorder. *)
+
+Program Instance predicate_equivalence_equivalence :
+ Equivalence (predicate l) predicate_equivalence.
Next Obligation.
- Proof.
- unfold relation_equivalence in *.
- apply transitivity with (y x0 y0) ; [ apply H | apply H0 ].
+ induction l ; firstorder.
+ Qed.
+
+ Next Obligation.
+ induction l ; firstorder.
+ Qed.
+
+ Next Obligation.
+ fold lift_pointwise.
+ induction l. firstorder.
+ intros. simpl in *. intro. pose (IHl (x x0) (y x0) (z x0)).
+ firstorder.
+ Qed.
+
+Program Instance predicate_implication_preorder :
+ PreOrder (predicate l) predicate_implication.
+
+ Next Obligation.
+ induction l ; firstorder.
Qed.
-Program Instance subrelation_preorder :
- PreOrder (relation A) subrelation.
+ Next Obligation.
+ fold lift_pointwise.
+ induction l. firstorder.
+ unfold predicate_implication in *. simpl in *.
+ intro. pose (IHl (x x0) (y x0) (z x0)). firstorder.
+ Qed.
+
+(** We define the various operations which define the algebra on binary relations,
+ from the general ones. *)
+
+Definition relation_equivalence {A : Type} : relation (relation A) :=
+ @predicate_equivalence (cons _ (cons _ nil)).
+
+Class subrelation {A:Type} (R R' : relation A) : Prop :=
+ is_subrelation : @predicate_implication (cons A (cons A nil)) R R'.
+
+Implicit Arguments subrelation [[A]].
+
+Definition relation_conjunction {A} (R : relation A) (R' : relation A) : relation A :=
+ @predicate_intersection (cons A (cons A nil)) R R'.
+
+Definition relation_disjunction {A} (R : relation A) (R' : relation A) : relation A :=
+ @predicate_union (cons A (cons A nil)) R R'.
+
+(** Relation equivalence is an equivalence, and subrelation defines a partial order. *)
+
+Instance (A : Type) => relation_equivalence_equivalence :
+ Equivalence (relation A) relation_equivalence.
+Proof. intro A. exact (@predicate_equivalence_equivalence (cons A (cons A nil))). Qed.
+
+Instance relation_implication_preorder : PreOrder (relation A) subrelation.
+Proof. intro A. exact (@predicate_implication_preorder (cons A (cons A nil))). Qed.
(** *** Partial Order.
A partial order is a preorder which is additionally antisymmetric.
@@ -256,8 +401,7 @@ Program Instance subrelation_preorder :
on the carrier. *)
Class [ equ : Equivalence A eqA, PreOrder A R ] => PartialOrder :=
- partial_order_equivalence : relation_equivalence eqA (relation_conjunction R (flip R)).
-
+ partial_order_equivalence : relation_equivalence eqA (relation_conjunction R (inverse R)).
(** The equivalence proof is sufficient for proving that [R] must be a morphism
for equivalence (see Morphisms).
@@ -265,8 +409,8 @@ Class [ equ : Equivalence A eqA, PreOrder A R ] => PartialOrder :=
Instance [ PartialOrder A eqA R ] => partial_order_antisym : ! Antisymmetric A eqA R.
Proof with auto.
- reduce_goal. pose partial_order_equivalence. red in r.
- apply <- r. firstorder.
+ reduce_goal. pose partial_order_equivalence as poe. do 3 red in poe.
+ apply <- poe. firstorder.
Qed.
(** The partial order defined by subrelation and relation equivalence. *)
@@ -279,8 +423,6 @@ Program Instance subrelation_partial_order :
unfold relation_equivalence in *. firstorder.
Qed.
-Instance iff_impl_subrelation : subrelation iff impl.
-Proof. firstorder. Qed.
-
-Instance iff_inverse_impl_subrelation : subrelation iff (inverse impl).
-Proof. firstorder. Qed.
+Lemma inverse_pointwise_relation A (R : relation A) :
+ relation_equivalence (pointwise_relation (inverse R)) (inverse (pointwise_relation (A:=A) R)).
+Proof. reflexivity. Qed.
diff --git a/theories/Classes/SetoidTactics.v b/theories/Classes/SetoidTactics.v
index 38bdc0bc9..9d3648fef 100644
--- a/theories/Classes/SetoidTactics.v
+++ b/theories/Classes/SetoidTactics.v
@@ -17,6 +17,7 @@
Require Export Coq.Classes.RelationClasses.
Require Export Coq.Classes.Morphisms.
+Require Export Coq.Classes.Morphisms_Prop.
Require Export Coq.Classes.Equivalence.
Require Export Coq.Relations.Relation_Definitions.
@@ -89,6 +90,7 @@ Ltac reverse_arrows x :=
end.
Ltac default_add_morphism_tactic :=
+ intros ;
(try destruct_morphism) ;
match goal with
| [ |- (?x ==> ?y) _ _ ] => red_subst_eq_morphism (x ==> y) ; reverse_arrows (x ==> y)