Skip to content

Using new syntax for projection instance declarations #2263

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 28 additions & 16 deletions STYLE.md
Original file line number Diff line number Diff line change
Expand Up @@ -509,22 +509,34 @@ IsTrunc n (P a)`, and similarly for other data types. For instance,

### 3.7. Coercions and Existing Instances

A "coercion" from `A` to `B` is a function that Coq will insert
silently if given an `A` when it expects a `B`, and which it doesn't
display. For example, we have declared `equiv_fun` as a coercion from
`A <~> B` to `A -> B`, so that we can use an equivalence as a function
without needing to manually apply the projection `equiv_fun`.
Coercions can make code easier to read and write, but when used
carelessly they can have the opposite effect.

When defining a `Record`, Coq allows you to declare a field as a
coercion by writing its type with `:>` instead of `:`.
When defining a `Class`, the `:>` notation has a
different meaning: it declares a field as an `Existing Instance`.

(In addition, the `:>` notation is used when needed for path types
to indicate the type in which the paths are taken: `x = y :> A`
for `x, y : A`.)
A ["coercion" from `A` to
`B`](https://rocq-prover.org/refman/addendum/implicit-coercions.html)
is a function that Coq will insert silently if given an `A` when it
expects a `B`, and which it doesn't display. For example, we have
declared `equiv_fun` as a coercion from `A <~> B` to `A -> B`, so that
we can use an equivalence as a function without needing to manually
apply the projection `equiv_fun`. Coercions can make code easier to
read and write, but when used carelessly they can have the opposite
effect.

When making a record field `proj1` into a coercion, we prefer that the
coercion should not be reversible, because of the additional
complexity that reversible coercions add to unification problems, and
we prefer that coercions be conspicuous when reading the source code.
Therefore, define the coercion on its own line after the record
declaration as `Coercion proj1 : MyRec >-> FieldType` rather than
using the reversible coercion syntax `proj1 :> FieldType`.

(This library also uses the `:>` notation when needed for path types
to indicate the type in which the paths are taken: `x = y :> A` for
`x, y : A`.)

If `proj1` is a record field whose type is a typeclass and we'd
like to add this field as a typeclass instance, then we prefer
the concise ["substructure"
notation](https://rocq-prover.org/refman/addendum/type-classes.html#substructures)
`proj1 :: ClassType` over the separate vernacular command
`Existing Instance proj1.` after the record declaration.

## 4. Axioms

Expand Down
3 changes: 1 addition & 2 deletions theories/Algebra/AbGroups/AbelianGroup.v
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@ Local Open Scope mc_add_scope.

Record AbGroup := {
abgroup_group : Group;
abgroup_commutative : @Commutative abgroup_group _ (+);
abgroup_commutative :: @Commutative abgroup_group _ (+);
}.

Coercion abgroup_group : AbGroup >-> Group.
Existing Instance abgroup_commutative.

Definition zero_abgroup (A : AbGroup) : Zero A := mon_unit.
Definition negate_abgroup (A : AbGroup) : Negate A := inv.
Expand Down
3 changes: 1 addition & 2 deletions theories/Algebra/AbGroups/Abelianization.v
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ Definition group_precomp {a b} := @cat_precomp Group _ _ a b.

Class IsAbelianization {G : Group} (G_ab : AbGroup)
(eta : GroupHomomorphism G G_ab)
:= issurjinj_isabel : forall (A : AbGroup),
:= issurjinj_isabel :: forall (A : AbGroup),
IsSurjInj (group_precomp A eta).
Existing Instance issurjinj_isabel.

Definition isequiv_group_precomp_isabelianization `{Funext}
{G : Group} {G_ab : AbGroup} (eta : GroupHomomorphism G G_ab)
Expand Down
3 changes: 1 addition & 2 deletions theories/Algebra/AbGroups/FreeAbelianGroup.v
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ Definition FactorsThroughFreeAbGroup (S : Type) (F_S : AbGroup)

(** Universal property of a free abelian group on a set (type). *)
Class IsFreeAbGroupOn (S : Type) (F_S : AbGroup) (i : S -> F_S)
:= contr_isfreeabgroupon : forall (A : AbGroup) (g : S -> A),
:= contr_isfreeabgroupon :: forall (A : AbGroup) (g : S -> A),
Contr (FactorsThroughFreeAbGroup S F_S i A g).
Existing Instance contr_isfreeabgroupon.

(** A abelian group is free if there exists a generating type on which it is a free group (a basis). *)
Class IsFreeAbGroup (F_S : AbGroup)
Expand Down
8 changes: 3 additions & 5 deletions theories/Algebra/AbSES/Core.v
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,14 @@ Record AbSES' {B A : AbGroup@{u}} := Build_AbSES {
middle : AbGroup@{u};
inclusion : A $-> middle;
projection : middle $-> B;
isembedding_inclusion : IsEmbedding inclusion;
issurjection_projection : IsSurjection projection;
isexact_inclusion_projection : IsExact (Tr (-1)) inclusion projection;
isembedding_inclusion :: IsEmbedding inclusion;
issurjection_projection :: IsSurjection projection;
isexact_inclusion_projection :: IsExact (Tr (-1)) inclusion projection;
}.

(** Given a short exact sequence [A -> E -> B : AbSES B A], we coerce it to [E]. *)
Coercion middle : AbSES' >-> AbGroup.

Existing Instances isembedding_inclusion issurjection_projection isexact_inclusion_projection.

Arguments AbSES' B A : clear implicits.
Arguments Build_AbSES {B A}.

Expand Down
3 changes: 1 addition & 2 deletions theories/Algebra/Groups/Group.v
Original file line number Diff line number Diff line change
Expand Up @@ -1153,9 +1153,8 @@ Definition FactorsThroughFreeGroup (S : Type) (F_S : Group)

(** Universal property of a free group on a set (type). *)
Class IsFreeGroupOn (S : Type) (F_S : Group) (i : S -> F_S)
:= contr_isfreegroupon : forall (A : Group) (g : S -> A),
:= contr_isfreegroupon :: forall (A : Group) (g : S -> A),
Contr (FactorsThroughFreeGroup S F_S i A g).
Existing Instance contr_isfreegroupon.

(** A group is free if there exists a generating type on which it is a free group. *)
Class IsFreeGroup (F_S : Group)
Expand Down
10 changes: 3 additions & 7 deletions theories/Algebra/Groups/Subgroup.v
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,12 @@ Generalizable Variables G H A B C N f g.

(** A subgroup H of a group G is a predicate (i.e. an hProp-valued type family) on G which is closed under the group operations. The group underlying H is given by the total space { g : G & H g }, defined in [subgroup_group] below. *)
Class IsSubgroup {G : Group} (H : G -> Type) := {
issubgroup_predicate : forall x, IsHProp (H x) ;
issubgroup_predicate :: forall x, IsHProp (H x) ;
issubgroup_in_unit : H mon_unit ;
issubgroup_in_op : forall x y, H x -> H y -> H (x * y) ;
issubgroup_in_inv : forall x, H x -> H x^ ;
}.

Existing Instance issubgroup_predicate.

Definition issig_issubgroup {G : Group} (H : G -> Type) : _ <~> IsSubgroup H
:= ltac:(issig).

Expand Down Expand Up @@ -130,11 +128,10 @@ Defined.
(** The type (set) of subgroups of a group G. *)
Record Subgroup (G : Group) := {
subgroup_pred : G -> Type ;
subgroup_issubgroup : IsSubgroup subgroup_pred ;
subgroup_issubgroup :: IsSubgroup subgroup_pred ;
}.

Coercion subgroup_pred : Subgroup >-> Funclass.
Existing Instance subgroup_issubgroup.

Definition issig_subgroup {G : Group} : _ <~> Subgroup G
:= ltac:(issig).
Expand Down Expand Up @@ -442,13 +439,12 @@ Class IsNormalSubgroup {G : Group} (N : Subgroup G)

Record NormalSubgroup (G : Group) := {
normalsubgroup_subgroup : Subgroup G ;
normalsubgroup_isnormal : IsNormalSubgroup normalsubgroup_subgroup ;
normalsubgroup_isnormal :: IsNormalSubgroup normalsubgroup_subgroup ;
}.

Arguments Build_NormalSubgroup G N _ : rename.

Coercion normalsubgroup_subgroup : NormalSubgroup >-> Subgroup.
Existing Instance normalsubgroup_isnormal.

Definition equiv_symmetric_in_normalsubgroup {G : Group}
(N : Subgroup G) `{!IsNormalSubgroup N}
Expand Down
4 changes: 1 addition & 3 deletions theories/Algebra/Rings/Ring.v
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ Record Ring := Build_Ring' {
ring_mult_assoc_opp : forall z y x, (x * y) * z = x * (y * z);
}.


Arguments ring_mult {R} : rename.
Arguments ring_one {R} : rename.
Arguments ring_isring {R} : rename.
Expand Down Expand Up @@ -144,12 +143,11 @@ End RingHomoLaws.
(** Isomorphisms of commutative rings *)
Record RingIsomorphism (A B : Ring) := {
rng_iso_homo : RingHomomorphism A B ;
isequiv_rng_iso_homo : IsEquiv rng_iso_homo ;
isequiv_rng_iso_homo :: IsEquiv rng_iso_homo ;
}.

Arguments rng_iso_homo {_ _ }.
Coercion rng_iso_homo : RingIsomorphism >-> RingHomomorphism.
Existing Instance isequiv_rng_iso_homo.

Definition issig_RingIsomorphism {A B : Ring}
: _ <~> RingIsomorphism A B := ltac:(issig).
Expand Down
12 changes: 3 additions & 9 deletions theories/Algebra/Universal/Algebra.v
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,11 @@ Record Signature := Build_Signature
{ Sort : Type
; Symbol : Type
; symbol_types : Symbol -> SymbolTypeOf Sort
; hset_sort : IsHSet Sort
; hset_symbol : IsHSet Symbol }.
; hset_sort :: IsHSet Sort
; hset_symbol :: IsHSet Symbol }.

Notation SymbolType σ := (SymbolTypeOf (Sort σ)).

Existing Instance hset_sort.

Existing Instance hset_symbol.

Global Coercion symbol_types : Signature >-> Funclass.

(** Each [Algebra] has a collection of carrier types [Carriers σ],
Expand Down Expand Up @@ -81,14 +77,12 @@ Definition Operation {σ} (A : Carriers σ) (w : SymbolType σ) : Type
Record Algebra {σ : Signature} : Type := Build_Algebra
{ carriers : Carriers σ
; operations : forall (u : Symbol σ), Operation carriers (σ u)
; hset_algebra : forall (s : Sort σ), IsHSet (carriers s) }.
; hset_algebra :: forall (s : Sort σ), IsHSet (carriers s) }.

Arguments Algebra : clear implicits.

Arguments Build_Algebra {σ} carriers operations {hset_algebra}.

Existing Instance hset_algebra.

Global Coercion carriers : Algebra >-> Funclass.

Bind Scope Algebra_scope with Algebra.
Expand Down
12 changes: 3 additions & 9 deletions theories/Algebra/Universal/Congruence.v
Original file line number Diff line number Diff line change
Expand Up @@ -53,20 +53,14 @@ Section congruence.
mere equivalence relations and [OpsCompatible A Φ] holds. *)

Class IsCongruence : Type := Build_IsCongruence
{ is_mere_relation_cong : forall (s : Sort σ), is_mere_relation (A s) (Φ s)
; equiv_rel_cong : forall (s : Sort σ), EquivRel (Φ s)
; ops_compatible_cong : OpsCompatible }.
{ is_mere_relation_cong :: forall (s : Sort σ), is_mere_relation (A s) (Φ s)
; equiv_rel_cong :: forall (s : Sort σ), EquivRel (Φ s)
; ops_compatible_cong :: OpsCompatible }.

Global Arguments Build_IsCongruence {is_mere_relation_cong}
{equiv_rel_cong}
{ops_compatible_cong}.

#[export] Existing Instance is_mere_relation_cong.

#[export] Existing Instance equiv_rel_cong.

#[export] Existing Instance ops_compatible_cong.

#[export] Instance hprop_is_congruence `{Funext} : IsHProp IsCongruence.
Proof.
apply (equiv_hprop_allpath _)^-1.
Expand Down
4 changes: 1 addition & 3 deletions theories/Algebra/Universal/Homomorphism.v
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,14 @@ End is_homomorphism.

Record Homomorphism {σ} {A B : Algebra σ} : Type := Build_Homomorphism
{ def_homomorphism : forall (s : Sort σ), A s -> B s
; is_homomorphism : IsHomomorphism def_homomorphism }.
; is_homomorphism :: IsHomomorphism def_homomorphism }.

Arguments Homomorphism {σ}.

Arguments Build_Homomorphism {σ A B} def_homomorphism {is_homomorphism}.

Global Coercion def_homomorphism : Homomorphism >-> Funclass.

Existing Instance is_homomorphism.

Instance isgraph_algebra (σ : Signature) : IsGraph (Algebra σ)
:= Build_IsGraph (Algebra σ) Homomorphism.

Expand Down
4 changes: 1 addition & 3 deletions theories/Algebra/ooGroup.v
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,9 @@ Local Unset Keyed Unification.

Record ooGroup :=
{ classifying_space : pType ;
isconn_classifying_space : IsConnected 0 classifying_space
isconn_classifying_space :: IsConnected 0 classifying_space
}.

Existing Instance isconn_classifying_space.

Local Notation B := classifying_space.

Definition group_type (G : ooGroup) : Type
Expand Down
9 changes: 3 additions & 6 deletions theories/Basics/Decidable.v
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,7 @@ Ltac decidable_false p n :=
try intro.

Class DecidablePaths (A : Type) :=
dec_paths : forall (x y : A), Decidable (x = y).
Existing Instance dec_paths.
dec_paths :: forall (x y : A), Decidable (x = y).

Class Stable P := stable : ~~P -> P.

Expand Down Expand Up @@ -199,13 +198,11 @@ Defined.
(** A type is collapsible if it admits a weakly constant endomap. *)
Class Collapsible (A : Type) :=
{ collapse : A -> A ;
wconst_collapse : WeaklyConstant collapse
wconst_collapse :: WeaklyConstant collapse
}.
Existing Instance wconst_collapse.

Class PathCollapsible (A : Type) :=
path_coll : forall (x y : A), Collapsible (x = y).
Existing Instance path_coll.
path_coll :: forall (x y : A), Collapsible (x = y).

Instance collapsible_decidable (A : Type) `{Decidable A}
: Collapsible A.
Expand Down
15 changes: 4 additions & 11 deletions theories/Basics/Overture.v
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,8 @@ Class Transitive {A} (R : Relation A) :=

(** A [PreOrder] is both Reflexive and Transitive. *)
Class PreOrder {A} (R : Relation A) :=
{ PreOrder_Reflexive : Reflexive R | 2 ;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is funny. Back when the syntax was :> for an existing instance in a Class we had these priorities. When they were removed the parser still accepted and ignored them. Now that we are adding them back in, the priority is back to the original one.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was pleasantly surprised that this notation was accepted by the parser.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does that mean that this change is also a semantic one? Why should we set the cost of this instance to something other than the default? (And since this wasn't just a rote change, it should have been highlighted in the PR.)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original intention is for the reflexivity instance coming from here to be lower priority than the rest. This was broken some time when we removed the legacy :> syntax.

We have two choices: Either we remove the | 2s or we keep them the way they are. The secondary option seems better as I think I see the reason for choosing a lower priority. During typeclass search, you don't want to try the reflexivity proof from the preorder class of R rather than just choosing a direct reflexivity proof if one is available.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought that the original hint had a custom priority of 2. If there was no custom priority in the original hint than this is a mistake and I'll look at it again to see what happened. Maybe I mixed it up with another hint

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As Ali explained, I think historically it had a custom priority of 2, but when the old :> notation for an instance was replaced with an explicit Existing Instance line, that priority was lost (but the | 2 was still in the record field, doing nothing). Then your change caused the priority to go back to 2. Ali suggests that this is probably a good thing, so there is no need to change this PR. I was just pointing out that this is a semantic change, which should have been mentioned, but of course it was the kind of thing that would be easy to miss.

PreOrder_Transitive : Transitive R | 2 }.

Existing Instance PreOrder_Reflexive.
Existing Instance PreOrder_Transitive.
{ PreOrder_Reflexive :: Reflexive R | 2 ;
PreOrder_Transitive :: Transitive R | 2 }.

Arguments reflexivity {A R _} / _.
Arguments symmetry {A R _} / _ _ _.
Expand Down Expand Up @@ -488,13 +485,11 @@ Global Opaque eisadj.
(** A record that includes all the data of an adjoint equivalence. *)
Record Equiv A B := {
equiv_fun : A -> B ;
equiv_isequiv : IsEquiv equiv_fun
equiv_isequiv :: IsEquiv equiv_fun
}.

Coercion equiv_fun : Equiv >-> Funclass.

Existing Instance equiv_isequiv.

Arguments equiv_fun {A B} _ _.
Arguments equiv_isequiv {A B} _.

Expand Down Expand Up @@ -728,12 +723,10 @@ Arguments point A {_}.

Record pType :=
{ pointed_type : Type ;
ispointed_type : IsPointed pointed_type }.
ispointed_type :: IsPointed pointed_type }.

Coercion pointed_type : pType >-> Sortclass.

Existing Instance ispointed_type.

(** *** Homotopy fibers *)

(** Homotopy fibers are homotopical inverse images of points. *)
Expand Down
7 changes: 2 additions & 5 deletions theories/Basics/Trunc.v
Original file line number Diff line number Diff line change
Expand Up @@ -378,9 +378,7 @@ Definition istrunc_equiv_istrunc A {B} (f : A <~> B) `{IsTrunc n A}
(** ** Truncated morphisms *)

Class IsTruncMap (n : trunc_index) {X Y : Type} (f : X -> Y)
:= istruncmap_fiber : forall y:Y, IsTrunc n (hfiber f y).

Existing Instance istruncmap_fiber.
:= istruncmap_fiber :: forall y:Y, IsTrunc n (hfiber f y).

Notation IsEmbedding := (IsTruncMap (-1)).

Expand All @@ -390,15 +388,14 @@ Notation IsEmbedding := (IsTruncMap (-1)).

Record TruncType (n : trunc_index) := {
trunctype_type : Type ;
trunctype_istrunc : IsTrunc n trunctype_type
trunctype_istrunc :: IsTrunc n trunctype_type
}.

Arguments Build_TruncType _ _ {_}.
Arguments trunctype_type {_} _.
Arguments trunctype_istrunc [_] _.

Coercion trunctype_type : TruncType >-> Sortclass.
Existing Instance trunctype_istrunc.

Notation "n -Type" := (TruncType n) : type_scope.
Notation HProp := (-1)-Type.
Expand Down
4 changes: 1 addition & 3 deletions theories/Categories/Category/Core.v
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ Record PreCategory :=
(** Ask for the double-identity version so that [InitialTerminalCategory.Functors.from_terminal Cᵒᵖ X] and [(InitialTerminalCategory.Functors.from_terminal C X)ᵒᵖ] are convertible. *)
identity_identity : forall x, identity x o identity x = identity x;

trunc_morphism : forall s d, IsHSet (morphism s d)
trunc_morphism :: forall s d, IsHSet (morphism s d)
}.

Bind Scope category_scope with PreCategory.
Expand Down Expand Up @@ -106,8 +106,6 @@ Definition Build_PreCategory
right_identity
(fun _ => left_identity _ _ _).

Existing Instance trunc_morphism.

(** create a hint db for all category theory things *)
Create HintDb category discriminated.
(** create a hint db for morphisms in categories *)
Expand Down
Loading
Loading