(************************************************************************) (* * 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) *) (************************************************************************)
(** * Typeclass-based morphism definition and standard, minimal instances
Author: Matthieu Sozeau Institution: LRI, CNRS UMR 8623 - University Paris Sud
*)
GeneralizableVariables A eqA B C D R RA RB RC m f x y. Local Obligation Tactic := try solve [ simpl_crelation ].
LocalArguments transitivity {A R Transitive x} y {z}.
Set Universe Polymorphism.
(** * Morphisms.
We now turn to the definition of [Proper] and declare standard instances.
These will be used by the [setoid_rewrite] tactic later. *)
(** A morphism for a relation [R] is a proper element of the relation. The relation [R] will be instantiated by [respectful] and [A] by an arrow
type for usual morphisms. *) SectionProper.
Context {A : Type}.
ClassProper (R : crelation A) (m : A) :=
proper_prf : R m m.
(** Every element in the carrier of a reflexive relation is a morphism for this relation. We use a proxy class for this case which is used internally to discharge reflexivity constraints. The [Reflexive] instance will almost always be used, but it won't apply in general to any kind of [Proper (A -> B) _ _] goal, making proof-search much slower. A cleaner solution would be to be able to set different priorities in different hint bases and select a particular hint
database for resolution of a type class constraint. *)
Class ProperProxy (R : crelation A) (m : A) :=
proper_proxy : R m m.
Lemma eq_proper_proxy (x : A) : ProperProxy (@eq A) x. Proof. firstorder. Qed.
Lemma reflexive_proper_proxy `(Reflexive A R) (x : A) : ProperProxy R x. Proof. firstorder. Qed.
Lemma proper_proper_proxy x `(Proper R x) : ProperProxy R x. Proof. firstorder. Qed.
(** Respectful morphisms. *)
(** The fully dependent version, not used yet. *)
Definition respectful_hetero
(A B : Type)
(C : A -> Type) (D : B -> Type)
(R : A -> B -> Type)
(R' : forall (x : A) (y : B), C x -> D y -> Type) :
(forall x : A, C x) -> (forall x : B, D x) -> Type := fun f g => forall x y, R x y -> R' x y (f x) (g y).
(** The non-dependent version is an instance where we forget dependencies. *)
Definition respectful {B} (R : crelation A) (R' : crelation B) : crelation (A -> B) := Evalcompute in @respectful_hetero A A (fun _ => B) (fun _ => B) R (fun _ _ => R'). EndProper.
(** We favor the use of Leibniz equality or a declared reflexive crelation when resolving [ProperProxy], otherwise, if the crelation is given (not an evar),
we fall back to [Proper]. *)
#[global] Hint Extern 1 (ProperProxy _ _) =>
class_apply @eq_proper_proxy || class_apply @reflexive_proper_proxy : typeclass_instances.
(** [solve_proper] try to solve the goal [Proper (?==> ... ==>?) f] by repeated introductions and setoid rewrites. It should work fine when [f] is a combination of already known morphisms and
quantifiers. *)
Ltac solve_respectful t := matchgoalwith
| |- respectful _ _ _ _ => let H := fresh "H" in intros ? ? H; solve_respectful ltac:(setoid_rewrite H; t)
| _ => t; reflexivity end.
(** [f_equiv] is a clone of [f_equal] that handles setoid equivalences. For example, if we know that [f] is a morphism for [E1==>E2==>E], then the goal [E (f x y) (f x' y')] will be transformed by [f_equiv] into the subgoals [E1 x x'] and [E2 y y'].
*)
Ltac f_equiv := matchgoalwith
| |- ?R (?f ?x) (?f' _) => let T := type of x in let Rx := fresh "R" in
evar (Rx : crelation T); let H := fresh in assert (H : (Rx==>R)%signatureT f f'); unfold Rx in *; clear Rx; [ f_equiv | apply H; clear H; tryreflexivity ]
| |- ?R ?f ?f' =>
solve [change (Proper R f); eauto with typeclass_instances | reflexivity ]
| _ => idtac end.
Section Relations.
Context {A : Type}.
(** [forall_def] reifies the dependent product as a definition. *)
Definition forall_def (P : A -> Type) : Type := forall x : A, P x.
(** Dependent pointwise lifting of a crelation on the range. *)
Definition forall_relation (P : A -> Type)
(sig : forall a, crelation (P a)) : crelation (forall x, P x) := fun f g => forall a, sig a (f a) (g a).
(** Non-dependent pointwise lifting *) Definition pointwise_relation {B} (R : crelation B) : crelation (A -> B) := fun f g => forall a, R (f a) (g a).
(** Subcrelations induce a morphism on the identity. *)
GlobalInstance subrelation_id_proper `(subrelation A RA RA') : Proper (RA ==> RA') id. Proof. firstorder. Qed.
(** The subrelation property goes through products as usual. *)
Lemma subrelation_respectful `(subl : subrelation A RA' RA, subr : subrelation B RB RB') : subrelation (RA ==> RB) (RA' ==> RB'). Proof. simpl_crelation. Qed.
(** And of course it is reflexive. *)
Lemma subrelation_refl R : @subrelation A R R. Proof. simpl_crelation. Qed.
(** [Proper] is itself a covariant morphism for [subrelation]. We use an unconvertible premise to avoid looping.
*)
Lemma subrelation_proper `(mor : Proper A R' m)
`(unc : Unconvertible (crelation A) R R')
`(sub : subrelation A R' R) : Proper R m. Proof. intros. apply sub. apply mor. Qed.
GlobalInstance pointwise_subrelation `(sub : subrelation B R R') : subrelation (pointwise_relation R) (pointwise_relation R') | 4. Proof. reduce. unfold pointwise_relation in *. apply sub. auto. Qed.
(** For dependent function types. *) Lemma forall_subrelation (P : A -> Type) (R S : forall x : A, crelation (P x)) :
(forall a, subrelation (R a) (S a)) -> subrelation (forall_relation P R) (forall_relation P S). Proof. reduce. firstorder. Qed. End Relations. Global Typeclasses Opaque respectful pointwise_relation forall_relation. Arguments forall_relation {A P}%_type sig%_signatureT _ _. Arguments pointwise_relation A%_type {B}%_type R%_signatureT _ _.
(** Resolution with subrelation: favor decomposing products over applying reflexivity
for unconstrained goals. *) Ltac subrelation_tac T U :=
(is_ground T ; is_ground U ; class_apply @subrelation_refl) ||
class_apply @subrelation_respectful || class_apply @subrelation_refl.
#[global] Hint Extern 3 (@subrelation _ ?T ?U) => subrelation_tac T U : typeclass_instances.
#[global] Hint Extern 4 (subrelation (@forall_relation ?A ?B ?R) (@forall_relation _ _ ?S)) => apply (@forall_subrelation A B R S) ; intro : typeclass_instances.
Section GenericInstances. (* Share universes *) Implicit Types A B C : Type.
(** We can build a PER on the Rocq function space if we have PERs on the domain and
codomain. *)
ProgramInstance respectful_per `(PER A R, PER B R') : PER (R ==> R').
Next Obligation. Proofwithauto. intros A R H B R' H0 x y z X X0 x0 y0 X1. assert(R x0 x0).
- eapply transitivity with y0... nowapplysymmetry.
- eapply transitivity with (y x0)... Qed.
Unset Strict Universe Declaration.
(** The complement of a crelation conserves its proper elements. *)
(** The [flip] too, actually the [flip] instance is a bit more general. *) ProgramDefinition flip_proper
`(mor : Proper (A -> B -> C) (RA ==> RB ==> RC) f) : Proper (RB ==> RA ==> RC) (flip f) := _.
Next Obligation. Proof. intros A B C RA RB RC f mor x y X x0 y0 X0. apply mor ; auto. Qed.
(** Every Transitive crelation gives rise to a binary morphism on [impl],
contravariant in the first argument, covariant in the second. *)
GlobalProgram Instance trans_contra_co_type_morphism
`(Transitive A R) : Proper (R --> R ++> arrow) R.
Next Obligation. Proofwithauto. intros A R H x y X x0 y0 X0 X1. apply transitivity with x... apply transitivity with x0... Qed.
(** Proper declarations for partial applications. *)
Next Obligation. Proofwithauto. intros A R H x x0 y X. split.
- intros ; apply transitivity with x0...
- intros. apply transitivity with y... applysymmetry... Qed.
(** Every Transitive crelation induces a morphism by "pushing" an [R x y] on the left of an [R x z] proof to get an [R y z] goal. *)
GlobalProgram Instance trans_co_eq_inv_arrow_morphism
`(Transitive A R) : Proper (R ==> (@eq A) ==> flip arrow) R | 2.
Next Obligation. Proofwithauto. intros A R H x y X y0 y1 e X0; destruct e. apply transitivity with y... Qed.
(** Every Symmetric and Transitive crelation gives rise to an equivariant morphism. *)
GlobalProgram Instance PER_type_morphism `(PER A R) : Proper (R ==> R ==> iffT) R | 1.
Next Obligation. Proofwithauto. intros A R H x y X x0 y0 X0. split ; intros.
- apply transitivity with x0... apply transitivity with x... applysymmetry...
- apply transitivity with y... apply transitivity with y0... applysymmetry... Qed.
Lemma symmetric_equiv_flip `(Symmetric A R) : relation_equivalence R (flip R). Proof. firstorder. Qed.
GlobalProgramInstance compose_proper A B C RA RB RC : Proper ((RB ==> RC) ==> (RA ==> RB) ==> (RA ==> RC)) (@compose A B C).
Next Obligation. Proof.
simpl_crelation. unfold compose. firstorder. Qed.
(** Rocq functions are morphisms for Leibniz equality,
applied only if really needed. *)
GlobalInstance reflexive_eq_dom_reflexive `(Reflexive B R') {A} :
Reflexive (@Logic.eq A ==> R'). Proof. simpl_crelation. Qed.
(** [respectful] is a morphism for crelation equivalence . *)
GlobalInstance respectful_morphism {A B} : Proper (relation_equivalence ++> relation_equivalence ++> relation_equivalence)
(@respectful A B). Proof. intros R R' HRR' S S' HSS' f g. unfold respectful , relation_equivalence in *; simpl in *. split ; intros H x y Hxy.
- apply (fst (HSS' _ _)). apply H. nowapply (snd (HRR' _ _)).
- apply (snd (HSS' _ _)). apply H. nowapply (fst (HRR' _ _)). Qed.
(** [R] is Reflexive, hence we can build the needed proof. *)
Lemma Reflexive_partial_app_morphism `(Proper (A -> B) (R ==> R') m, ProperProxy A R x) : Proper R' (m x). Proof. simpl_crelation. Qed.
Ltac partial_application_tactic := let rec do_partial_apps H m cont := match m with
| ?m' ?x => class_apply @Reflexive_partial_app_morphism ;
[(do_partial_apps H m' ltac:(idtac))|clear H]
| _ => cont end
in let rec do_partial H ar m := match ar with
| 0%nat => do_partial_apps H m ltac:(fail 1)
| S ?n' => match m with
?m' ?x => do_partial H n' m' end end
in let params m sk fk :=
(let m' := fresh in head_of_constr m' m ; let n := fresh in evar (n:nat) ; let v := evalcompute in n in clear n ; let H := fresh in assert(H:Params m' v) by typeclasses eauto ; let v' := evalcompute in v in subst m';
(sk H v' || fail 1))
|| fk
in let on_morphism m cont :=
params m ltac:(fun H n => do_partial H n m) ltac:(cont)
in matchgoalwith
| [ _ : normalization_done |- _ ] => fail 1
| [ _ : @Params _ _ _ |- _ ] => fail 1
| [ |- @Proper ?T _ (?m ?x) ] => matchgoalwith
| [ H : PartialApplication |- _ ] =>
class_apply @Reflexive_partial_app_morphism; [|clear H]
| _ => on_morphism (m x) ltac:(class_apply @Reflexive_partial_app_morphism) end end.
(** Bootstrap !!! *)
#[global] Instance proper_proper {A} : Proper (relation_equivalence ==> eq ==> iffT) (@Proper A). Proof. intros R R' HRR' x y <-. red in HRR'. split ; red ; intros.
- nowapply (fst (HRR' _ _)).
- nowapply (snd (HRR' _ _)). Qed.
(** When the crelation on the domain is symmetric, we can
flip the crelation on the codomain. Same for binary functions. *)
Lemma proper_sym_flip : forall `(Symmetric A R1)`(Proper (A->B) (R1==>R2) f), Proper (R1==>flip R2) f. Proof. intros A R1 Sym B R2 f Hf. intros x x' Hxx'. apply Hf, Sym, Hxx'. Qed.
Lemma proper_sym_flip_2 : forall `(Symmetric A R1)`(Symmetric B R2)`(Proper (A->B->C) (R1==>R2==>R3) f), Proper (R1==>R2==>flip R3) f. Proof. intros A R1 Sym1 B R2 Sym2 C R3 f Hf. intros x x' Hxx' y y' Hyy'. apply Hf; auto. Qed.
(** When the crelation on the domain is symmetric, a predicate is compatible with [iff] as soon as it is compatible with [impl].
Same with a binary crelation. *)
Lemma proper_sym_impl_iff : forall `(Symmetric A R)`(Proper _ (R==>impl) f), Proper (R==>iff) f. Proof. intros A R Sym f Hf x x' Hxx'. repeatred in Hf. split; eauto. Qed.
Lemma proper_sym_arrow_iffT : forall `(Symmetric A R)`(Proper _ (R==>arrow) f), Proper (R==>iffT) f. Proof. intros A R Sym f Hf x x' Hxx'. repeatred in Hf. split; eauto. Qed.
Lemma proper_sym_impl_iff_2 : forall `(Symmetric A R)`(Symmetric B R')`(Proper _ (R==>R'==>impl) f), Proper (R==>R'==>iff) f. Proof. intros A R Sym B R' Sym' f Hf x x' Hxx' y y' Hyy'. repeatred in Hf. split; eauto. Qed.
Lemma proper_sym_arrow_iffT_2 : forall `(Symmetric A R)`(Symmetric B R')`(Proper _ (R==>R'==>arrow) f), Proper (R==>R'==>iffT) f. Proof. intros A R Sym B R' Sym' f Hf x x' Hxx' y y' Hyy'. repeatred in Hf. split; eauto. Qed.
(** A [PartialOrder] is compatible with its underlying equivalence. *) RequireImport Relation_Definitions.
#[global] Instance PartialOrder_proper_type `(PartialOrder A eqA R) : Proper (eqA==>eqA==>iffT) R. Proof. intros. apply proper_sym_arrow_iffT_2. 1-2: typeclasses eauto. intros x x' Hx y y' Hy Hr. apply transitivity with x.
- generalize (partial_order_equivalence x x'); compute; intuition.
- apply transitivity with y; auto. generalize (partial_order_equivalence y y'); compute; intuition. Qed.
(** From a [PartialOrder] to the corresponding [StrictOrder]: [lt = le /\ ~eq].
If the order is total, we could also say [gt = ~le]. *)
Lemma PartialOrder_StrictOrder `(PartialOrder A eqA R) :
StrictOrder (relation_conjunction R (complement eqA)). Proof. split; compute.
- intros x (_,Hx). apply Hx, Equivalence_Reflexive.
- intros x y z (Hxy,Hxy') (Hyz,Hyz'). split.
+ apply PreOrder_Transitive with y; assumption.
+ intro Hxz. apply Hxy'. apply partial_order_antisym; auto. apply transitivity with z; [assumption|]. nowapply H. Qed.
(** From a [StrictOrder] to the corresponding [PartialOrder]: [le = lt \/ eq].
If the order is total, we could also say [ge = ~lt]. *)
Lemma StrictOrder_PreOrder
`(Equivalence A eqA, StrictOrder A R, Proper _ (eqA==>eqA==>iffT) R) :
PreOrder (relation_disjunction R eqA). Proof. split.
- intros x. right. applyreflexivity.
- intros x y z [Hxy|Hxy] [Hyz|Hyz].
+ left. apply transitivity with y; auto.
+ left. eapply H1; try eassumption.
* applyreflexivity.
* nowapplysymmetry.
+ left. eapply H1; [eassumption|applyreflexivity|eassumption].
+ right. apply transitivity with y; auto. Qed.
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.