Skip to content

Commit a7f0bfc

Browse files
qvermandeTragicus
qvermande
authored andcommitted
declared sort and Pack_ as coercions in HB/structures.v
1 parent 8b1725c commit a7f0bfc

File tree

6 files changed

+175
-25
lines changed

6 files changed

+175
-25
lines changed

Changelog.md

+11
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,17 @@
22

33
## Unreleased
44

5+
### General
6+
7+
- **Change** For a structure `S` on a subject of type `T`, declares `S.sort` as
8+
an Elpi coercion from `S.type` to `T` and `S.pack` as an Epli coercion from
9+
`T` to `S.type` whenever `T` is not a global type (e.g. a variable). Note
10+
that `S.pack` can cast a `t : T` to `S.type` only if an instance of the
11+
class `S` on `t` is found by type class inference
12+
- **Change** `HB.structure` declares the class of a structure (`axioms_`) as a
13+
type class on the subject with all arguments in output mode but for the
14+
subject that is in input mode.
15+
516
## [1.7.0] - 2024-01-10
617

718
Compatible with

HB/common/synthesis.elpi

+1-1
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ infer-coercion-tgt (w-params.cons ID Ty F) CoeClass :-
154154
@pi-parameter ID Ty x\ infer-coercion-tgt (F x) CoeClass.
155155
infer-coercion-tgt (w-params.nil _ {{ Type }} _) sortclass.
156156
infer-coercion-tgt (w-params.nil _ {{ _ -> _ }} _) funclass.
157-
infer-coercion-tgt (w-params.nil _ T _) (grefclass GR) :- coq.term->gref T GR.
157+
infer-coercion-tgt (w-params.nil _ T _) (grefclass GR) :- coq.term-is-gref? T GR.
158158

159159
pred w-args.check-key i:list term, i:term, i:list (w-args A), o:prop.
160160
w-args.check-key _PS _T [] true :- !.

HB/structure.elpi

+93-22
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,14 @@ declare Module BSkel Sort :- std.do! [
105105
%]),
106106

107107
if-verbose (coq.say {header} "making coercion from type to target"),
108-
synthesis.infer-coercion-tgt MLwP CoeClass,
109-
if-arg-sort (private.declare-sort-coercion CoeClass Structure
110-
(global (const ArgSortCst))),
111-
private.declare-sort-coercion CoeClass Structure SortProjection,
108+
if (synthesis.infer-coercion-tgt MLwP CoeClass)
109+
(if-arg-sort (private.declare-sort-coercion CoeClass Structure
110+
(global (const ArgSortCst))),
111+
private.declare-sort-coercion CoeClass Structure SortProjection)
112+
(if-arg-sort (private.declare-sort-coercion-elpi (global Structure) (global (const ArgSortCst))),
113+
private.declare-sort-coercion-elpi (global Structure) SortProjection),
114+
115+
private.declare-reverse-coercion-elpi Structure,
112116

113117
if-verbose (coq.say {header} "exporting unification hints"),
114118
ClassAlias => Factories => GRDepsClauses =>
@@ -137,24 +141,26 @@ declare Module BSkel Sort :- std.do! [
137141

138142
log.coq.env.import-module "Exports" Exports,
139143

140-
if-verbose (coq.say {header} "declaring on_ abbreviation"),
144+
if (var CoeClass)
145+
(if-verbose (coq.say {header} "could not declare the `on_`, `copy` and `on` abbreviations because the target of sort is not a coercion class"))
146+
(if-verbose (coq.say {header} "declaring on_ abbreviation"),
141147

142-
private.mk-infer-key CoeClass ClassProjection NilwP (global Structure) PhClass,
148+
private.mk-infer-key CoeClass ClassProjection NilwP (global Structure) PhClass,
143149

144-
phant.add-abbreviation "on_" PhClass _ ClassOfAbbrev,
145-
(pi c\ coq.notation.abbreviation ClassOfAbbrev [c] (ClassOfAbbrev_ c)),
150+
phant.add-abbreviation "on_" PhClass _ ClassOfAbbrev,
151+
(pi c\ coq.notation.abbreviation ClassOfAbbrev [c] (ClassOfAbbrev_ c)),
146152

147-
if-verbose (coq.say {header} "declaring `copy` abbreviation"),
153+
if-verbose (coq.say {header} "declaring `copy` abbreviation"),
148154

149-
coq.mk-app (global ClassName) {params->holes NilwP} AppClassHoles,
150-
@global! => log.coq.notation.add-abbreviation "copy" 2
151-
{{fun T C => (lp:(ClassOfAbbrev_ C) : (lp:AppClassHoles T)) }} tt _,
155+
coq.mk-app (global ClassName) {params->holes NilwP} AppClassHoles,
156+
@global! => log.coq.notation.add-abbreviation "copy" 2
157+
{{fun T C => (lp:(ClassOfAbbrev_ C) : (lp:AppClassHoles T)) }} tt _,
152158

153-
if-verbose (coq.say {header} "declaring on abbreviation"),
159+
if-verbose (coq.say {header} "declaring on abbreviation"),
154160

155-
@global! => log.coq.notation.add-abbreviation "on" 1
156-
{{fun T => (lp:{{ ClassOfAbbrev_ {{_}} }} : (lp:AppClassHoles T)) }} tt
157-
_OnAbbrev,
161+
@global! => log.coq.notation.add-abbreviation "on" 1
162+
{{fun T => (lp:{{ ClassOfAbbrev_ {{_}} }} : (lp:AppClassHoles T)) }} tt
163+
_OnAbbrev),
158164

159165
log.coq.env.end-module-name Module ModulePath,
160166

@@ -276,6 +282,45 @@ export-operations Structure ProjSort ProjClass MLwP EX1 EX2 MLToExport :- std.do
276282
std.map LMwPToExport w-params_1 MLToExport,
277283
].
278284

285+
pred mk-sort-coercion-aux i:term, i:term, i:term, i:list term, o:prop.
286+
mk-sort-coercion-aux (prod _N _T Body) Structure P Args Clause :-
287+
Clause = (pi x\ C x),
288+
pi x\ mk-sort-coercion-aux (Body x) Structure P [x | Args] (C x).
289+
290+
mk-sort-coercion-aux _ Structure P Args Clause :-
291+
std.rev Args ArgsRev,
292+
Clause =
293+
(pi ctx v t e r argsAll w\ (coercion ctx v (app [Structure | ArgsRev]) e r :-
294+
std.append ArgsRev [v] argsAll,
295+
coq.mk-app P argsAll w,
296+
coq.elaborate-skeleton w e r ok,
297+
coq.ltac.collect-goals r [] [])).
298+
299+
pred mk-sort-coercion i:term, i:term, o:prop.
300+
mk-sort-coercion Structure P Clause :-
301+
coq.typecheck Structure T ok,
302+
mk-sort-coercion-aux T Structure P [] Clause.
303+
304+
pred mk-reverse-coercion-aux i:term, i:term, i:term, i:list term, o:prop.
305+
mk-reverse-coercion-aux (prod _N _T Body) Structure G Args Clause :-
306+
Clause = (pi x\ C x),
307+
pi x\ mk-reverse-coercion-aux (Body x) Structure G [x | Args] (C x).
308+
309+
mk-reverse-coercion-aux _ Structure G Args Clause :-
310+
std.rev Args ArgsRev,
311+
Clause =
312+
(pi ctx v t e r c argsAll w\ (coercion ctx v t (app [Structure | ArgsRev]) r :-
313+
std.append ArgsRev [v, c] argsAll,
314+
coq.mk-app G argsAll w,
315+
coq.elaborate-skeleton w e r ok,
316+
coq.ltac.collect-goals r [] [])).
317+
318+
pred mk-reverse-coercion i:gref, o:prop.
319+
mk-reverse-coercion Structure Clause :-
320+
coq.typecheck (global Structure) T ok,
321+
get-constructor Structure G,
322+
mk-reverse-coercion-aux T (global Structure) (global G) [] Clause.
323+
279324
pred mk-coe-class-body
280325
i:factoryname, % From class
281326
i:factoryname, % To class
@@ -428,18 +473,23 @@ declare-unification-hints SortProj ClassProj CurrentClass NewJoins :- std.do! [
428473

429474
% For each mixin we declare a field and apply the mixin to its dependencies
430475
% (that are previously declared fields recorded via field-for-mixin)
431-
pred synthesize-fields i:term, i:list (w-args mixinname), o:record-decl.
432-
synthesize-fields _T [] end-record.
433-
synthesize-fields T [triple M Args _|ML] (field _ Name MTy Fields) :- std.do! [
476+
% Keeps track of whether every field is in Prop
477+
pred synthesize-fields i:term, i:list (w-args mixinname), o:record-decl, o:bool.
478+
synthesize-fields _T [] end-record tt.
479+
synthesize-fields T [triple M Args V|ML] (field _ Name MTy Fields) B :- std.do! [
480+
if (coq.typecheck {mk-app (global M) {std.append Args [V]} } {{ Prop }} ok)
481+
(B = B2)
482+
(B = ff),
434483
Name is {gref->modname M 2 "_"} ^ "_mixin",
435484
if-verbose (coq.say {header} "typing class field" M),
436485
std.assert! (synthesis.infer-all-gref-deps Args T M MTy) "anomaly: a field type cannot be solved",
437-
@pi-decl `m` MTy m\ mixin-src T M m => synthesize-fields T ML (Fields m)
486+
@pi-decl `m` MTy m\ mixin-src T M m => synthesize-fields T ML (Fields m) B2
438487
].
439488

440489
pred synthesize-fields.body i:list term, i:term, i:list (w-args mixinname), o:indt-decl.
441-
synthesize-fields.body _Params T ML (record "axioms_" {{ Type }} "Class" FS) :-
442-
synthesize-fields T ML FS.
490+
synthesize-fields.body _Params T ML (record "axioms_" Ty "Class" FS) :-
491+
synthesize-fields T ML FS B,
492+
if (B = tt) (Ty = {{ Prop }}) (Ty = {{ Type }}).
443493

444494
pred mk-record+sort-field i:sort, i:name, i:term, i:(term -> record-decl), o:indt-decl.
445495
pred mk-record+sort-field i:universe, i:name, i:term, i:(term -> record-decl), o:indt-decl.
@@ -495,6 +545,27 @@ declare-sort-coercion CoeClass StructureName (global Proj) :-
495545

496546
log.coq.coercion.declare (coercion Proj 0 StructureName CoeClass).
497547

548+
% Declares "sort" as a Coercion in elpi's coercion db Proj : Structurename >-> CoeClass.
549+
pred declare-sort-coercion-elpi i:term, i:term.
550+
declare-sort-coercion-elpi Structure Proj :-
551+
552+
if-verbose (coq.say {header} "declare sort coercion in elpi"),
553+
554+
%TODO: log.coq.coercion-elpi.declare
555+
mk-sort-coercion Structure Proj Clause,
556+
coq.elpi.accumulate _ "coercion.db" (clause _ _ Clause).
557+
558+
% Declares a reverse coercion for the sort projection in elpi's coercion db
559+
pred declare-reverse-coercion-elpi i:gref.
560+
declare-reverse-coercion-elpi Structure :-
561+
562+
if-verbose (coq.say {header} "declare reverse coercion in elpi"),
563+
564+
%TODO: log.coq.coercion-elpi.declare
565+
mk-reverse-coercion Structure Clause,
566+
coq.elpi.accumulate _ "coercion.db" (clause _ _ Clause).
567+
568+
498569
pred if-class-already-exists-error i:id, i:list class, i:list mixinname.
499570
if-class-already-exists-error _ [] _.
500571
if-class-already-exists-error N [class _ S ML1wP|CS] ML2 :-

_CoqProject.test-suite

+3-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,9 @@ tests/unit/close_hole_term.v
9595
tests/unit/struct.v
9696
tests/factory_when_notation.v
9797

98+
tests/coercion.v
99+
98100
-R tests HB.tests
99101
-R examples HB.examples
100102

101-
-Q . HB
103+
-Q . HB

structures.v

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Definition ignore {T} (x: T) := x.
1515
Definition ignore_disabled {T T'} (x : T) (x' : T') := x'.
1616

1717
(* ********************* structures ****************************** *)
18-
From elpi Require Import elpi.
18+
From elpi Require Import elpi coercion.
1919

2020
Register unify as hb.unify.
2121
Register id_phant as hb.id.
@@ -619,6 +619,7 @@ HB.structure Definition StructureName params :=
619619
*)
620620

621621
#[arguments(raw)] Elpi Command HB.structure.
622+
Elpi Accumulate Db coercion.db.
622623
Elpi Accumulate Db hb.db.
623624
Elpi Accumulate File "HB/common/stdpp.elpi".
624625
Elpi Accumulate File "HB/common/database.elpi".

tests/coercion.v

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
From Coq Require Import ssreflect.
2+
From HB Require Import structures.
3+
4+
HB.mixin Record isSigma (T : Type) (P : T -> Prop) (x : T) := {
5+
_ : P x
6+
}.
7+
8+
#[short(type="sigType"), verbose]
9+
HB.structure Definition Sig (T : Type) (P : T -> Prop) := {x of isSigma T P x}.
10+
11+
Section Sigma.
12+
13+
Check fun (T : Type) (P : T -> Prop) (x : sigType T P) => x : T.
14+
Check fun (T : Type) (P : T -> Prop) (x : T) (Px : Sig T P x) => x : sigType T P.
15+
Fail Check fun (T : Type) (P : T -> Prop) (x : T) => x : sigType T P.
16+
17+
Axioms (A B B' C : Type) (AtoB : A -> B) (BtoB' : B -> B').
18+
Axioms (P : A -> Prop) (CtoAP : C -> sigType A P).
19+
Coercion AtoB : A >-> B.
20+
Coercion BtoB' : B >-> B'.
21+
(* does postcompose automatically with Coq coercions*)
22+
Check fun (x : sigType A P) => x : B.
23+
Check fun (x : sigType A P) => x : B'.
24+
25+
(* testing a Coq coercion to sigType *)
26+
Coercion CtoAP : C >-> sigType.
27+
Check fun (x : C) => x : sigType A P.
28+
29+
(* does not precompose automatically with Coq coercions *)
30+
Fail Check fun (x : C) => x : A.
31+
Check fun (x : C) => (x : sigType A P) : A.
32+
Check fun (x : C) => (x : sigType A P) : B.
33+
34+
Axioms (x : A) (Px : Sig A P x).
35+
36+
(* should not work indeed *)
37+
Fail Check (x : sigType A P).
38+
39+
(* this works though ...*)
40+
Succeed Check (let Px' := Px in x : sigType A P).
41+
42+
HB.instance Definition _ := Px.
43+
Fail Check x : sigType A P.
44+
45+
End Sigma.
46+
47+
HB.mixin Record isSigmaT (P : Type -> Prop) (x : Type) := { _ : P x }.
48+
#[short(type="sigTType"), verbose]
49+
HB.structure Definition SigT (P : Type -> Prop) := {x of isSigmaT P x}.
50+
51+
Section SigmaT.
52+
53+
Axioms (X : Type) (PT : Type -> Prop) (PX : SigT PT X).
54+
55+
(* should not work indeed *)
56+
Fail Check (X : sigTType PT).
57+
58+
(* this works though now ... cf my next point*)
59+
Succeed Check (let PX' := PX in X : sigTType PT).
60+
61+
(* Now this works *)
62+
HB.instance Definition _ := PX.
63+
Succeed Check X : sigTType PT.
64+
65+
End SigmaT.

0 commit comments

Comments
 (0)