aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--Makefile.common1
-rw-r--r--contrib/setoid_ring/Ring_theory.v2
-rw-r--r--contrib/setoid_ring/newring.ml48
-rw-r--r--tactics/class_tactics.ml4223
-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
-rw-r--r--theories/FSets/FMapFacts.v2
-rw-r--r--theories/FSets/FSetFacts.v4
-rw-r--r--theories/Lists/List.v4
-rw-r--r--theories/Program/Syntax.v2
-rw-r--r--theories/QArith/QArith_base.v2
-rw-r--r--theories/Setoids/Setoid.v20
-rw-r--r--toplevel/classes.ml5
17 files changed, 648 insertions, 442 deletions
diff --git a/Makefile.common b/Makefile.common
index 11a7cbd0f..8421d397e 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -744,6 +744,7 @@ SETOIDSVO:= theories/Setoids/Setoid.vo # theories/Setoids/Setoid_tac.vo theories
UNICODEVO:= theories/Unicode/Utf8.vo
CLASSESVO:= theories/Classes/Init.vo theories/Classes/RelationClasses.vo theories/Classes/Morphisms.vo \
+ theories/Classes/Morphisms_Prop.vo theories/Classes/Morphisms_Relations.vo \
theories/Classes/Functions.vo theories/Classes/Equivalence.vo theories/Classes/SetoidTactics.vo \
theories/Classes/SetoidClass.vo theories/Classes/SetoidAxioms.vo theories/Classes/EquivDec.vo \
theories/Classes/SetoidDec.vo
diff --git a/contrib/setoid_ring/Ring_theory.v b/contrib/setoid_ring/Ring_theory.v
index cefdcf52b..4c542ffdd 100644
--- a/contrib/setoid_ring/Ring_theory.v
+++ b/contrib/setoid_ring/Ring_theory.v
@@ -257,7 +257,7 @@ Section ALMOST_RING.
(** Leibniz equality leads to a setoid theory and is extensional*)
Lemma Eqsth : Setoid_Theory R (@eq R).
- Proof. constructor;intros;subst;trivial. Qed.
+ Proof. constructor;red;intros;subst;trivial. Qed.
Lemma Eq_s_ext : sring_eq_ext radd rmul (@eq R).
Proof. constructor;intros;subst;trivial. Qed.
diff --git a/contrib/setoid_ring/newring.ml4 b/contrib/setoid_ring/newring.ml4
index 7cf642ce7..c80b37d91 100644
--- a/contrib/setoid_ring/newring.ml4
+++ b/contrib/setoid_ring/newring.ml4
@@ -527,7 +527,7 @@ let ring_equality (r,add,mul,opp,req) =
(setoid,op_morph)
| _ ->
let setoid = setoid_of_relation (Global.env ()) r req in
- let signature = [Some (r,req);Some (r,req)],Some(r,req) in
+ let signature = [Some (r,req);Some (r,req)],Some(Lazy.lazy_from_val (r,req)) in
let add_m, add_m_lem =
try Class_tactics.default_morphism signature add
with Not_found ->
@@ -540,7 +540,7 @@ let ring_equality (r,add,mul,opp,req) =
match opp with
| Some opp ->
(let opp_m,opp_m_lem =
- try Class_tactics.default_morphism ([Some(r,req)],Some(r,req)) opp
+ try Class_tactics.default_morphism ([Some(r,req)],Some(Lazy.lazy_from_val (r,req))) opp
with Not_found ->
error "ring opposite should be declared as a morphism" in
let op_morph =
@@ -830,7 +830,7 @@ let ring_lookup (f:glob_tactic_expr) lH rl t gl =
TACTIC EXTEND ring_lookup
| [ "ring_lookup" tactic(f) "[" constr_list(lH) "]" constr_list(lr)
"[" constr(t) "]" ] ->
- [ring_lookup (fst f) lH lr t]
+ [ring_lookup (fst f) lH lr t]
END
@@ -1037,7 +1037,7 @@ let field_equality r inv req =
mkApp((Coqlib.build_coq_eq_data()).congr,[|r;r;inv|])
| _ ->
let _setoid = setoid_of_relation (Global.env ()) r req in
- let signature = [Some (r,req)],Some(r,req) in
+ let signature = [Some (r,req)],Some(Lazy.lazy_from_val (r,req)) in
let inv_m, inv_m_lem =
try Class_tactics.default_morphism signature inv
with Not_found ->
diff --git a/tactics/class_tactics.ml4 b/tactics/class_tactics.ml4
index 075077048..bbd29e665 100644
--- a/tactics/class_tactics.ml4
+++ b/tactics/class_tactics.ml4
@@ -130,6 +130,7 @@ type search_state = {
tacres : goal list sigma * validation;
pri : int;
last_tactic : std_ppcmds;
+(* filter : constr -> constr -> bool; *)
dblist : Auto.Hint_db.t list;
localdb : Auto.Hint_db.t list }
@@ -148,23 +149,23 @@ module SearchProblem = struct
prlist (pr_ev evars) (sig_it gls)
let filter_tactics (glls,v) l =
- if !debug then
- (let _ = Proof_trees.db_pr_goal (List.hd (sig_it glls)) in
- let evars = Evarutil.nf_evars (Refiner.project glls) in
- msg (str"Goal: " ++ pr_ev evars (List.hd (sig_it glls)) ++ str"\n"));
+(* if !debug then *)
+(* (let _ = Proof_trees.db_pr_goal (List.hd (sig_it glls)) in *)
+(* let evars = Evarutil.nf_evars (Refiner.project glls) in *)
+(* msg (str"Goal: " ++ pr_ev evars (List.hd (sig_it glls)) ++ str"\n")); *)
let rec aux = function
| [] -> []
| (tac,pri,pptac) :: tacl ->
try
- if !debug then msg (str"\nTrying tactic: " ++ pptac ++ str"\n");
+(* if !debug then msg (str"\nTrying tactic: " ++ pptac ++ str"\n"); *)
let (lgls,ptl) = apply_tac_list tac glls in
let v' p = v (ptl p) in
- if !debug then
- begin
- let evars = Evarutil.nf_evars (Refiner.project glls) in
- msg (str"\nOn goal: " ++ pr_ev evars (List.hd (sig_it glls)) ++ str"\n");
- msg (hov 1 (pptac ++ str" gives: \n" ++ pr_goals lgls ++ str"\n"))
- end;
+(* if !debug then *)
+(* begin *)
+(* let evars = Evarutil.nf_evars (Refiner.project glls) in *)
+(* msg (str"\nOn goal: " ++ pr_ev evars (List.hd (sig_it glls)) ++ str"\n"); *)
+(* msg (hov 1 (pptac ++ str" gives: \n" ++ pr_goals lgls ++ str"\n")) *)
+(* end; *)
((lgls,v'),pri,pptac) :: aux tacl
with e when Logic.catchable_exception e ->
(* if !debug then msg (str"failed\n"); *)
@@ -195,31 +196,33 @@ module SearchProblem = struct
let nbgl = List.length (sig_it lg) in
assert (nbgl > 0);
let g = find_first_goal lg in
+(* let filt = s.filter (pf_concl g) in *)
let assumption_tacs =
let l =
filter_tactics s.tacres
(List.map
(fun id -> (Eauto.e_give_exact_constr (mkVar id), 0,
(str "exact" ++ spc () ++ pr_id id)))
- (pf_ids_of_hyps g))
+(* (List.filter (fun id -> filt (pf_get_hyp_typ g id)) *)
+ (pf_ids_of_hyps g))
in
List.map (fun (res,pri,pp) -> { s with tacres = res; pri = 0;
last_tactic = pp; localdb = List.tl s.localdb }) l
in
- let intro_tac =
- List.map
- (fun ((lgls,_) as res,pri,pp) ->
- let g' = first_goal lgls in
- let hintl =
- make_resolve_hyp (pf_env g') (project g') (pf_last_hyp g')
- in
- let ldb = Hint_db.add_list hintl (match s.localdb with [] -> assert false | hd :: _ -> hd) in
- { s with tacres = res;
- last_tactic = pp;
- pri = pri;
- localdb = ldb :: List.tl s.localdb })
- (filter_tactics s.tacres [Tactics.intro,1,(str "intro")])
- in
+(* let intro_tac = *)
+(* List.map *)
+(* (fun ((lgls,_) as res,pri,pp) -> *)
+(* let g' = first_goal lgls in *)
+(* let hintl = *)
+(* make_resolve_hyp (pf_env g') (project g') (pf_last_hyp g') *)
+(* in *)
+(* let ldb = Hint_db.add_list hintl (match s.localdb with [] -> assert false | hd :: _ -> hd) in *)
+(* { s with tacres = res; *)
+(* last_tactic = pp; *)
+(* pri = pri; *)
+(* localdb = ldb :: List.tl s.localdb }) *)
+(* (filter_tactics s.tacres [Tactics.intro,1,(str "intro")]) *)
+(* in *)
let possible_resolve ((lgls,_) as res, pri, pp) =
let nbgl' = List.length (sig_it lgls) in
if nbgl' < nbgl then
@@ -232,17 +235,13 @@ module SearchProblem = struct
localdb =
list_addn (nbgl'-nbgl) (List.hd s.localdb) s.localdb }
in
-(* let custom_tac = *)
-(* List.map possible_resolve *)
-(* (filter_tactics s.tacres [s.custom_tactic,(str "custom_tactic")]) *)
-(* in *)
let rec_tacs =
let l =
filter_tactics s.tacres (e_possible_resolve s.dblist (List.hd s.localdb) (pf_concl g))
in
List.map possible_resolve l
in
- List.sort compare (assumption_tacs @ intro_tac (* @ custom_tac *) @ rec_tacs)
+ List.sort compare (assumption_tacs (* @intro_tac @ custom_tac *) @ rec_tacs)
let pp s =
msg (hov 0 (str " depth=" ++ int s.depth ++ spc () ++
@@ -252,10 +251,48 @@ end
module Search = Explore.Make(SearchProblem)
+
+let filter_pat c =
+ try
+ let morg = Nametab.global (Qualid (dummy_loc, qualid_of_string "Coq.Classes.Morphisms.Morphism")) in
+ let morc = constr_of_global morg in
+ match kind_of_term c with
+ | App(morph, [| t; r; m |]) when eq_constr morph morc ->
+ (fun y ->
+ (match y.pat with
+ Some (PApp (PRef mor, [| t'; r'; m' |])) when mor = morg ->
+ (match m' with
+ | PRef c -> if isConst m then eq_constr (constr_of_global c) m else false
+ | _ -> true)
+ | _ -> true))
+ | _ -> fun _ -> true
+ with _ -> fun _ -> true
+
+let morphism_class =
+ lazy (class_info (Nametab.global (Qualid (dummy_loc, qualid_of_string "Coq.Classes.Morphisms.Morphism"))))
+
+let filter c =
+ try let morc = constr_of_global (Nametab.global (Qualid (dummy_loc, qualid_of_string "Coq.Classes.Morphisms.Morphism"))) in
+ match kind_of_term c with
+ | App(morph, [| t; r; m |]) when eq_constr morph morc ->
+ (fun y ->
+ let (_, r) = decompose_prod y in
+ (match kind_of_term r with
+ App (morph', [| t'; r'; m' |]) when eq_constr morph' morc ->
+ (match kind_of_term m' with
+ | Rel n -> true
+ | Const c -> eq_constr m m'
+ | App _ -> true
+ | _ -> false)
+ | _ -> false))
+ | _ -> fun _ -> true
+ with _ -> fun _ -> true
+
let make_initial_state n gls dblist localdbs =
{ depth = n;
tacres = gls;
pri = 0;
+(* filter = filter; *)
last_tactic = (mt ());
dblist = dblist;
localdb = localdbs }
@@ -422,9 +459,6 @@ END
(** Typeclass-based rewriting. *)
-let morphism_class =
- lazy (class_info (Nametab.global (Qualid (dummy_loc, qualid_of_string "Coq.Classes.Morphisms.Morphism"))))
-
let respect_proj = lazy (mkConst (List.hd (Lazy.force morphism_class).cl_projs))
let make_dir l = make_dirpath (List.map id_of_string (List.rev l))
@@ -499,7 +533,7 @@ let split_head = function
hd :: tl -> hd, tl
| [] -> assert(false)
-let build_signature isevars env m (cstrs : 'a option list) (finalcstr : 'a option) (f : 'a -> constr) =
+let build_signature isevars env m (cstrs : 'a option list) (finalcstr : 'a Lazy.t option) (f : 'a -> constr) =
let new_evar isevars env t =
Evarutil.e_new_evar isevars env
(* ~src:(dummy_loc, ImplicitArg (ConstRef (Lazy.force respectful), (n, Some na))) *) t
@@ -527,7 +561,8 @@ let build_signature isevars env m (cstrs : 'a option list) (finalcstr : 'a optio
let t = Reductionops.nf_betaiota t in
let rel = mk_relty t None in
t, rel, [t, rel]
- | Some (t, rel) -> t, rel, [t, rel])
+ | Some codom -> let (t, rel) = Lazy.force codom in
+ t, rel, [t, rel])
in aux m cstrs
let reflexivity_proof_evar env evars carrier relation x =
@@ -554,26 +589,17 @@ let reflexive_proof env = find_class_proof reflexive_type reflexive_proof env
let symmetric_proof env = find_class_proof symmetric_type symmetric_proof env
let transitive_proof env = find_class_proof transitive_type transitive_proof env
+exception FoundInt of int
+
+let array_find (arr: 'a array) (pred: int -> 'a -> bool): int =
+ try
+ for i=0 to Array.length arr - 1 do if pred i (arr.(i)) then raise (FoundInt i) done;
+ raise Not_found
+ with FoundInt i -> i
+
let resolve_morphism env sigma oldt m ?(fnewt=fun x -> x) args args' cstr evars =
let morph_instance, proj, sigargs, m', args, args' =
-(* if is_equiv env sigma m then *)
-(* let params, rest = array_chop 3 args in *)
-(* let a, r, s = params.(0), params.(1), params.(2) in *)
-(* let params', rest' = array_chop 3 args' in *)
-(* let inst = mkApp (Lazy.force setoid_morphism, params) in *)
-(* (* Equiv gives a binary morphism *) *)
-(* let (cl, proj) = Lazy.force class_two in *)
-(* let ctxargs = [ a; r; s; a; r; s; mkProp; Lazy.force iff; Lazy.force iff_setoid; ] in *)
-(* let m' = mkApp (m, [| a; r; s |]) in *)
-(* inst, proj, ctxargs, m', rest, rest' *)
-(* else *)
- let first =
- let first = ref (-1) in
- for i = 0 to Array.length args' - 1 do
- if !first = -1 && args'.(i) <> None then first := i
- done;
- !first
- in
+ let first = try (array_find args' (fun i b -> b <> None)) with Not_found -> raise (Invalid_argument "resolve_morphism") in
let morphargs, morphobjs = array_chop first args in
let morphargs', morphobjs' = array_chop first args' in
let appm = mkApp(m, morphargs) in
@@ -736,9 +762,47 @@ let unfold_all t =
| _ -> assert false)
| _ -> assert false
-type rewrite_flags = { under_lambdas : bool }
+(* let lift_cstr env sigma evars args cstr = *)
+(* let codom = *)
+(* match cstr with *)
+(* | Some c -> c *)
+(* | None -> *)
+(* let ty = Evarutil.e_new_evar evars env (new_Type ()) in *)
+(* let rel = Evarutil.e_new_evar evars env (mk_relation ty) in *)
+(* (ty, rel) *)
+(* in *)
+(* Array.fold_right *)
+(* (fun arg (car, rel) -> *)
+(* let ty = Typing.type_of env sigma arg in *)
+(* let car' = mkProd (Anonymous, ty, car) in *)
+(* let rel' = mkApp (Lazy.force pointwise_relation, [| ty; car; rel |]) in *)
+(* (car', rel')) *)
+(* args codom *)
+
+let rec decomp_pointwise n c =
+ if n = 0 then c
+ else
+ match kind_of_term c with
+ | App (pointwise, [| a; b; relb |]) -> decomp_pointwise (pred n) relb
+ | _ -> raise Not_found
+
+let lift_cstr env sigma evars args cstr =
+ match cstr with
+ | Some codom ->
+ let cstr () =
+ Array.fold_right
+ (fun arg (car, rel) ->
+ let ty = Typing.type_of env sigma arg in
+ let car' = mkProd (Anonymous, ty, car) in
+ let rel' = mkApp (Lazy.force pointwise_relation, [| ty; car; rel |]) in
+ (car', rel'))
+ args (Lazy.force codom)
+ in Some (Lazy.lazy_from_fun cstr)
+ | None -> None
+
+type rewrite_flags = { under_lambdas : bool; on_morphisms : bool }
-let default_flags = { under_lambdas = true }
+let default_flags = { under_lambdas = true; on_morphisms = true; }
let build_new gl env sigma flags occs hypinfo concl cstr evars =
let is_occ occ = occs = [] || List.mem occ occs in
@@ -763,19 +827,36 @@ let build_new gl env sigma flags occs hypinfo concl cstr evars =
| None ->
match kind_of_term t with
| App (m, args) ->
- let args', occ =
- Array.fold_left
- (fun (acc, occ) arg -> let res, occ = aux env arg occ None in (res :: acc, occ))
- ([], occ) args
+ let rewrite_args () =
+ let args', occ =
+ Array.fold_left
+ (fun (acc, occ) arg -> let res, occ = aux env arg occ None in (res :: acc, occ))
+ ([], occ) args
+ in
+ let res =
+ if List.for_all (fun x -> x = None) args' then None
+ else
+ let args' = Array.of_list (List.rev args') in
+ (try Some (resolve_morphism env sigma t m args args' cstr evars)
+ with Not_found -> None)
+ in res, occ
in
- let res =
- if List.for_all (fun x -> x = None) args' then None
- else
- let args' = Array.of_list (List.rev args') in
- (try Some (resolve_morphism env sigma t m args args' cstr evars)
- with Not_found -> None)
- in res, occ
-
+ if flags.on_morphisms then
+ let m', occ = aux env m occ (lift_cstr env sigma evars args cstr) in
+ match m' with
+ None -> rewrite_args () (* Standard path, try rewrite on arguments *)
+ | Some (prf, (car, rel, c1, c2)) ->
+ (* We rewrote the function and get a proof of pointwise rel for the arguments.
+ We just apply it. *)
+ let nargs = Array.length args in
+ let decompprod c = snd (Reductionops.decomp_n_prod env (Evd.evars_of !evars) nargs c) in
+ let res =
+ try Some (mkApp (prf, args),
+ (decompprod car, decomp_pointwise nargs rel, mkApp(c1, args), mkApp(c2, args)))
+ with Not_found -> None
+ in res, occ
+ else rewrite_args ()
+
| Prod (_, x, b) when not (dependent (mkRel 1) b) ->
let x', occ = aux env x occ None in
let b', occ = aux env b occ None in
@@ -832,8 +913,6 @@ let resolve_typeclass_evars d p env evd onlyargs =
(fun ev evi -> class_of_constr evi.Evd.evar_concl <> None)
in resolve_all_evars d p env pred evd
-let cl_rewrite_tactic = lazy (Tacinterp.interp <:tactic<setoid_rewrite_tac>>)
-
let cl_rewrite_clause_aux ?(flags=default_flags) hypinfo goal_meta occs clause gl =
let concl, is_hyp =
match clause with
@@ -848,7 +927,7 @@ let cl_rewrite_clause_aux ?(flags=default_flags) hypinfo goal_meta occs clause g
let evars = ref (Evd.create_evar_defs Evd.empty) in
let env = pf_env gl in
let sigma = project gl in
- let eq, _ = build_new gl env sigma flags occs hypinfo concl (Some cstr) evars in
+ let eq, _ = build_new gl env sigma flags occs hypinfo concl (Some (Lazy.lazy_from_val cstr)) evars in
match eq with
Some (p, (_, _, oldt, newt)) ->
(try
@@ -1322,7 +1401,7 @@ let get_hyp gl c clause l2r =
unification_rewrite hi.l2r hi.c1 hi.c2 hi.cl hi.rel but gl
| _ -> decompose_setoid_eqhyp (pf_env gl) (project gl) c l2r
-let general_rewrite_flags = { under_lambdas = false }
+let general_rewrite_flags = { under_lambdas = false; on_morphisms = false }
let general_s_rewrite l2r c ~new_goals gl =
let meta = Evarutil.new_meta() in
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)
diff --git a/theories/FSets/FMapFacts.v b/theories/FSets/FMapFacts.v
index 6d77a6a0c..617ea6f4f 100644
--- a/theories/FSets/FMapFacts.v
+++ b/theories/FSets/FMapFacts.v
@@ -651,7 +651,7 @@ Proof. unfold Equal; congruence. Qed.
Definition Equal_ST : forall elt:Type, Setoid_Theory (t elt) (@Equal _).
Proof.
-constructor; [apply Equal_refl | apply Equal_sym | apply Equal_trans].
+constructor; red; [apply Equal_refl | apply Equal_sym | apply Equal_trans].
Qed.
Add Relation key E.eq
diff --git a/theories/FSets/FSetFacts.v b/theories/FSets/FSetFacts.v
index 0c19176f8..6afb8fcb7 100644
--- a/theories/FSets/FSetFacts.v
+++ b/theories/FSets/FSetFacts.v
@@ -295,12 +295,12 @@ End BoolSpec.
Definition E_ST : Setoid_Theory elt E.eq.
Proof.
-constructor; [apply E.eq_refl|apply E.eq_sym|apply E.eq_trans].
+constructor ; red; [apply E.eq_refl|apply E.eq_sym|apply E.eq_trans].
Qed.
Definition Equal_ST : Setoid_Theory t Equal.
Proof.
-constructor; [apply eq_refl | apply eq_sym | apply eq_trans].
+constructor ; red; [apply eq_refl | apply eq_sym | apply eq_trans].
Qed.
Add Relation elt E.eq
diff --git a/theories/Lists/List.v b/theories/Lists/List.v
index 6b30f6351..5ab27cfc7 100644
--- a/theories/Lists/List.v
+++ b/theories/Lists/List.v
@@ -9,7 +9,6 @@
(*i $Id$ i*)
Require Import Le Gt Minus Min Bool.
-Require Import Coq.Setoids.Setoid.
Set Implicit Arguments.
@@ -554,8 +553,7 @@ Section Elts.
simpl; intros; split; [destruct 1 | apply gt_irrefl].
simpl. intro x; destruct (eqA_dec y x) as [Heq|Hneq].
rewrite Heq; intuition.
- rewrite <- (IHl x).
- tauto.
+ pose (IHl x). intuition.
Qed.
Theorem count_occ_inv_nil : forall (l : list A), (forall x:A, count_occ l x = 0) <-> l = nil.
diff --git a/theories/Program/Syntax.v b/theories/Program/Syntax.v
index a518faa57..6158e88f7 100644
--- a/theories/Program/Syntax.v
+++ b/theories/Program/Syntax.v
@@ -44,7 +44,7 @@ Implicit Arguments cons [[A]].
Notation " [] " := nil.
Notation " [ x ] " := (cons x nil).
-Notation " [ x ; .. ; y ] " := (cons x .. (cons y nil) ..).
+Notation " [ x ; .. ; y ] " := (cons x .. (cons y nil) ..) (at level 1).
(** n-ary exists ! *)
diff --git a/theories/QArith/QArith_base.v b/theories/QArith/QArith_base.v
index 26638893a..2265715b7 100644
--- a/theories/QArith/QArith_base.v
+++ b/theories/QArith/QArith_base.v
@@ -121,7 +121,7 @@ Defined.
Definition Q_Setoid : Setoid_Theory Q Qeq.
Proof.
- split; unfold Qeq in |- *; auto; apply Qeq_trans.
+ split; red; unfold Qeq in |- *; auto; apply Qeq_trans.
Qed.
Add Setoid Q Qeq Q_Setoid as Qsetoid.
diff --git a/theories/Setoids/Setoid.v b/theories/Setoids/Setoid.v
index 983c651ab..8f59c048f 100644
--- a/theories/Setoids/Setoid.v
+++ b/theories/Setoids/Setoid.v
@@ -8,22 +8,18 @@
(*i $Id$: i*)
-Set Implicit Arguments.
-
Require Export Coq.Classes.SetoidTactics.
(** For backward compatibility *)
-Record Setoid_Theory (A: Type) (Aeq: relation A) : Prop :=
- { Seq_refl : forall x:A, Aeq x x;
- Seq_sym : forall x y:A, Aeq x y -> Aeq y x;
- Seq_trans : forall x y z:A, Aeq x y -> Aeq y z -> Aeq x z }.
-
-Implicit Arguments Setoid_Theory [].
-Implicit Arguments Seq_refl [].
-Implicit Arguments Seq_sym [].
-Implicit Arguments Seq_trans [].
-
+Definition Setoid_Theory := @Equivalence.
+Definition Build_Setoid_Theory := @Build_Equivalence.
+Definition Seq_refl A Aeq (s : Setoid_Theory A Aeq) : forall x:A, Aeq x x :=
+ Eval compute in reflexivity.
+Definition Seq_sym A Aeq (s : Setoid_Theory A Aeq) : forall x y:A, Aeq x y -> Aeq y x :=
+ Eval compute in symmetry.
+Definition Seq_trans A Aeq (s : Setoid_Theory A Aeq) : forall x y z:A, Aeq x y -> Aeq y z -> Aeq x z :=
+ Eval compute in transitivity.
(** Some tactics for manipulating Setoid Theory not officially
declared as Setoid. *)
diff --git a/toplevel/classes.ml b/toplevel/classes.ml
index bc627a283..203fe118d 100644
--- a/toplevel/classes.ml
+++ b/toplevel/classes.ml
@@ -552,8 +552,9 @@ let new_instance ctx (instid, bk, cl) props ?(tac:Proof_type.tactic option) ?(ho
let kind = Decl_kinds.Global, Decl_kinds.DefinitionBody Decl_kinds.Instance in
Flags.silently (fun () ->
Command.start_proof id kind termtype (fun _ -> function ConstRef cst -> hook cst | _ -> assert false);
- Pfedit.by (* (Refiner.tclTHEN (Refiner.tclEVARS (Evd.evars_of !isevars)) *)
- (!refine_ref (evm, term));
+ if props <> [] then
+ Pfedit.by (* (Refiner.tclTHEN (Refiner.tclEVARS (Evd.evars_of !isevars)) *)
+ (!refine_ref (evm, term));
(match tac with Some tac -> Pfedit.by tac | None -> ())) ();
Flags.if_verbose (msg $$ Printer.pr_open_subgoals) ();
id