1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
|
.. _polymorphicuniverses:
Polymorphic Universes
======================
:Author: Matthieu Sozeau
General Presentation
---------------------
.. warning::
The status of Universe Polymorphism is experimental.
This section describes the universe polymorphic extension of Coq.
Universe polymorphism makes it possible to write generic definitions
making use of universes and reuse them at different and sometimes
incompatible universe levels.
A standard example of the difference between universe *polymorphic*
and *monomorphic* definitions is given by the identity function:
.. coqtop:: in
Definition identity {A : Type} (a : A) := a.
By default, :term:`constant` declarations are monomorphic, hence the identity
function declares a global universe (say ``Top.1``) for its domain.
Subsequently, if we try to self-apply the identity, we will get an
error:
.. coqtop:: all
Fail Definition selfid := identity (@identity).
Indeed, the global level ``Top.1`` would have to be strictly smaller than
itself for this self-application to type check, as the type of
:g:`(@identity)` is :g:`forall (A : Type@{Top.1}), A -> A` whose type is itself
:g:`Type@{Top.1+1}`.
A universe polymorphic identity function binds its domain universe
level at the definition level instead of making it global.
.. coqtop:: in
Polymorphic Definition pidentity {A : Type} (a : A) := a.
.. coqtop:: all
About pidentity.
It is then possible to reuse the constant at different levels, like
so:
.. coqtop:: in
Definition selfpid := pidentity (@pidentity).
Of course, the two instances of :g:`pidentity` in this definition are
different. This can be seen when the :flag:`Printing Universes` flag is on:
.. coqtop:: none
Set Printing Universes.
.. coqtop:: all
Print selfpid.
Now :g:`pidentity` is used at two different levels: at the head of the
application it is instantiated at ``Top.3`` while in the argument position
it is instantiated at ``Top.4``. This definition is only valid as long as
``Top.4`` is strictly smaller than ``Top.3``, as shown by the constraints. Note
that this definition is monomorphic (not universe polymorphic), so the
two universes (in this case ``Top.3`` and ``Top.4``) are actually global
levels.
When printing :g:`pidentity`, we can see the universes it binds in
the annotation :g:`@{Top.2}`. Additionally, when
:flag:`Printing Universes` is on we print the "universe context" of
:g:`pidentity` consisting of the bound universes and the
constraints they must verify (for :g:`pidentity` there are no constraints).
Inductive types can also be declared universes polymorphic on
universes appearing in their parameters or fields. A typical example
is given by monoids:
.. coqtop:: in
Polymorphic Record Monoid := { mon_car :> Type; mon_unit : mon_car;
mon_op : mon_car -> mon_car -> mon_car }.
.. coqtop:: in
Print Monoid.
The Monoid's carrier universe is polymorphic, hence it is possible to
instantiate it for example with :g:`Monoid` itself. First we build the
trivial unit monoid in :g:`Set`:
.. coqtop:: in
Definition unit_monoid : Monoid :=
{| mon_car := unit; mon_unit := tt; mon_op x y := tt |}.
From this we can build a definition for the monoid of :g:`Set`\-monoids
(where multiplication would be given by the product of monoids).
.. coqtop:: in
Polymorphic Definition monoid_monoid : Monoid.
refine (@Build_Monoid Monoid unit_monoid (fun x y => x)).
Defined.
.. coqtop:: all
Print monoid_monoid.
As one can see from the constraints, this monoid is “large”, it lives
in a universe strictly higher than :g:`Set`.
Polymorphic, Monomorphic
-------------------------
.. attr:: universes(polymorphic{? = {| yes | no } })
:name: universes(polymorphic); Polymorphic; Monomorphic
This :term:`boolean attribute` can be used to control whether universe
polymorphism is enabled in the definition of an inductive type.
There is also a legacy syntax using the ``Polymorphic`` prefix (see
:n:`@legacy_attr`) which, as shown in the examples, is more
commonly used.
When ``universes(polymorphic=no)`` is used, global universe constraints
are produced, even when the :flag:`Universe Polymorphism` flag is
on. There is also a legacy syntax using the ``Monomorphic`` prefix
(see :n:`@legacy_attr`).
.. attr:: universes(monomorphic)
.. deprecated:: 8.13
Use :attr:`universes(polymorphic=no) <universes(polymorphic)>`
instead.
.. flag:: Universe Polymorphism
This flag is off by default. When it is on, new declarations are
polymorphic unless the :attr:`universes(polymorphic=no) <universes(polymorphic)>`
attribute is used to override the default.
Many other commands can be used to declare universe polymorphic or
monomorphic :term:`constants <constant>` depending on whether the :flag:`Universe
Polymorphism` flag is on or the :attr:`universes(polymorphic)`
attribute is used:
- :cmd:`Lemma`, :cmd:`Axiom`, etc. can be used to declare universe
polymorphic constants.
- Using the :attr:`universes(polymorphic)` attribute with the
:cmd:`Section` command will locally set the polymorphism flag inside
the section.
- :cmd:`Variable`, :cmd:`Context`, :cmd:`Universe` and
:cmd:`Constraint` in a section support polymorphism. See
:ref:`universe-polymorphism-in-sections` for more details.
- Using the :attr:`universes(polymorphic)` attribute with the
:cmd:`Hint Resolve` or :cmd:`Hint Rewrite` commands will make
:tacn:`auto` / :tacn:`rewrite` use the hint polymorphically, not at
a single instance.
.. _cumulative:
Cumulative, NonCumulative
-------------------------
.. attr:: universes(cumulative{? = {| yes | no } })
:name: universes(cumulative); Cumulative; NonCumulative
Polymorphic inductive types, coinductive types, variants and
records can be declared cumulative using this :term:`boolean attribute`
or the legacy ``Cumulative`` prefix (see :n:`@legacy_attr`) which, as
shown in the examples, is more commonly used.
This means that two instances of the same inductive type (family)
are convertible based on the universe variances; they do not need
to be equal.
When the attribtue is off, the inductive type is non-cumulative
even if the :flag:`Polymorphic Inductive Cumulativity` flag is on.
There is also a legacy syntax using the ``NonCumulative`` prefix
(see :n:`@legacy_attr`).
This means that two instances of the same inductive type (family)
are convertible only if all the universes are equal.
.. exn:: The cumulative attribute can only be used in a polymorphic context.
Using this attribute requires being in a polymorphic context,
i.e. either having the :flag:`Universe Polymorphism` flag on, or
having used the :attr:`universes(polymorphic)` attribute as
well.
.. note::
:n:`#[ universes(polymorphic{? = yes }), universes(cumulative{? = {| yes | no } }) ]` can be
abbreviated into :n:`#[ universes(polymorphic{? = yes }, cumulative{? = {| yes | no } }) ]`.
.. attr:: universes(noncumulative)
.. deprecated:: 8.13
Use :attr:`universes(cumulative=no) <universes(cumulative)>` instead.
.. flag:: Polymorphic Inductive Cumulativity
When this flag is on (it is off by default), it makes all
subsequent *polymorphic* inductive definitions cumulative, unless
the :attr:`universes(cumulative=no) <universes(cumulative)>` attribute is
used to override the default. It has no effect on *monomorphic* inductive definitions.
Consider the examples below.
.. coqtop:: in
Polymorphic Cumulative Inductive list {A : Type} :=
| nil : list
| cons : A -> list -> list.
.. coqtop:: all
Print list.
When printing :g:`list`, the universe context indicates the subtyping
constraints by prefixing the level names with symbols.
Because inductive subtypings are only produced by comparing inductives
to themselves with universes changed, they amount to variance
information: each universe is either invariant, covariant or
irrelevant (there are no contravariant subtypings in Coq),
respectively represented by the symbols `=`, `+` and `*`.
Here we see that :g:`list` binds an irrelevant universe, so any two
instances of :g:`list` are convertible: :math:`E[Γ] ⊢ \mathsf{list}@\{i\}~A
=_{βδιζη} \mathsf{list}@\{j\}~B` whenever :math:`E[Γ] ⊢ A =_{βδιζη} B` and
this applies also to their corresponding constructors, when
they are comparable at the same type.
See :ref:`Conversion-rules` for more details on convertibility and subtyping.
The following is an example of a record with non-trivial subtyping relation:
.. coqtop:: all
Polymorphic Cumulative Record packType := {pk : Type}.
About packType.
:g:`packType` binds a covariant universe, i.e.
.. math::
E[Γ] ⊢ \mathsf{packType}@\{i\} =_{βδιζη}
\mathsf{packType}@\{j\}~\mbox{ whenever }~i ≤ j
Specifying cumulativity
~~~~~~~~~~~~~~~~~~~~~~~
The variance of the universe parameters for a cumulative inductive may be specified by the user.
For the following type, universe ``a`` has its variance automatically
inferred (it is irrelevant), ``b`` is required to be irrelevant,
``c`` is covariant and ``d`` is invariant. With these annotations
``c`` and ``d`` have less general variances than would be inferred.
.. coqtop:: all
Polymorphic Cumulative Inductive Dummy@{a *b +c =d} : Prop := dummy.
About Dummy.
Insufficiently restrictive variance annotations lead to errors:
.. coqtop:: all
Fail Polymorphic Cumulative Record bad@{*a} := {p : Type@{a}}.
An example of a proof using cumulativity
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. coqtop:: in reset
Set Universe Polymorphism.
Set Polymorphic Inductive Cumulativity.
Inductive eq@{i} {A : Type@{i}} (x : A) : A -> Type@{i} := eq_refl : eq x x.
Definition funext_type@{a b e} (A : Type@{a}) (B : A -> Type@{b})
:= forall f g : (forall a, B a),
(forall x, eq@{e} (f x) (g x))
-> eq@{e} f g.
Section down.
Universes a b e e'.
Constraint e' < e.
Lemma funext_down {A B}
(H : @funext_type@{a b e} A B) : @funext_type@{a b e'} A B.
Proof.
exact H.
Defined.
End down.
Cumulativity Weak Constraints
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. flag:: Cumulativity Weak Constraints
When set, which is the default, causes "weak" constraints to be produced
when comparing universes in an irrelevant position. Processing weak
constraints is delayed until minimization time. A weak constraint
between `u` and `v` when neither is smaller than the other and
one is flexible causes them to be unified. Otherwise the constraint is
silently discarded.
This heuristic is experimental and may change in future versions.
Disabling weak constraints is more predictable but may produce
arbitrary numbers of universes.
Global and local universes
---------------------------
Each universe is declared in a global or local context before it
can be used. To ensure compatibility, every *global* universe is set
to be strictly greater than :g:`Set` when it is introduced, while every
*local* (i.e. polymorphically quantified) universe is introduced as
greater or equal to :g:`Set`.
Conversion and unification
---------------------------
The semantics of conversion and unification have to be modified a
little to account for the new universe instance arguments to
polymorphic references. The semantics respect the fact that
definitions are transparent, so indistinguishable from their :term:`bodies <body>`
during conversion.
This is accomplished by changing one rule of unification, the first-
order approximation rule, which applies when two applicative terms
with the same head are compared. It tries to short-cut unfolding by
comparing the arguments directly. In case the :term:`constant` is universe
polymorphic, we allow this rule to fire only when unifying the
universes results in instantiating a so-called flexible universe
variables (not given by the user). Similarly for conversion, if such
an equation of applicative terms fail due to a universe comparison not
being satisfied, the terms are unfolded. This change implies that
conversion and unification can have different unfolding behaviors on
the same development with universe polymorphism switched on or off.
Minimization
-------------
Universe polymorphism with cumulativity tends to generate many useless
inclusion constraints in general. Typically at each application of a
polymorphic :term:`constant` :g:`f`, if an argument has expected type :g:`Type@{i}`
and is given a term of type :g:`Type@{j}`, a :math:`j ≤ i` constraint will be
generated. It is however often the case that an equation :math:`j = i` would
be more appropriate, when :g:`f`\'s universes are fresh for example.
Consider the following example:
.. coqtop:: none
Polymorphic Definition pidentity {A : Type} (a : A) := a.
Set Printing Universes.
.. coqtop:: in
Definition id0 := @pidentity nat 0.
.. coqtop:: all
Print id0.
This definition is elaborated by minimizing the universe of :g:`id0` to
level :g:`Set` while the more general definition would keep the fresh level
:g:`i` generated at the application of :g:`id` and a constraint that :g:`Set` :math:`≤ i`.
This minimization process is applied only to fresh universe variables.
It simply adds an equation between the variable and its lower bound if
it is an atomic universe (i.e. not an algebraic max() universe).
.. flag:: Universe Minimization ToSet
Turning this flag off (it is on by default) disallows minimization
to the sort :g:`Set` and only collapses floating universes between
themselves.
.. _explicit-universes:
Explicit Universes
-------------------
.. insertprodn universe_name univ_constraint
.. prodn::
universe_name ::= @qualid
| Set
| Prop
univ_annot ::= @%{ {* @universe_level } %}
universe_level ::= Set
| Prop
| Type
| _
| @qualid
univ_decl ::= @%{ {* @ident } {? + } {? %| {*, @univ_constraint } {? + } } %}
cumul_univ_decl ::= @%{ {* {? {| + | = | * } } @ident } {? + } {? %| {*, @univ_constraint } {? + } } %}
univ_constraint ::= @universe_name {| < | = | <= } @universe_name
The syntax has been extended to allow users to explicitly bind names
to universes and explicitly instantiate polymorphic definitions.
.. cmd:: Universe {+ @ident }
In the monomorphic case, declares new global universes
with the given names. Global universe names live in a separate namespace.
The command supports the :attr:`universes(polymorphic)` attribute (or
the ``Polymorphic`` legacy attribute) only in sections, meaning the universe
quantification will be discharged for each section definition
independently.
.. exn:: Polymorphic universes can only be declared inside sections, use Monomorphic Universe instead.
:undocumented:
.. cmd:: Constraint {+, @univ_constraint }
Declares new constraints between named universes.
If consistent, the constraints are then enforced in the global
environment. Like :cmd:`Universe`, it can be used with the
:attr:`universes(polymorphic)` attribute (or the ``Polymorphic``
legacy attribute) in sections only to declare constraints discharged at
section closing time. One cannot declare a global constraint on
polymorphic universes.
.. exn:: Undeclared universe @ident.
:undocumented:
.. exn:: Universe inconsistency.
:undocumented:
.. exn:: Polymorphic universe constraints can only be declared inside sections, use Monomorphic Constraint instead
:undocumented:
.. _printing-universes:
Printing universes
------------------
.. flag:: Printing Universes
Turn this flag on to activate the display of the actual level of each
occurrence of :g:`Type`. See :ref:`Sorts` for details. This wizard flag, in
combination with :flag:`Printing All` can help to diagnose failures to unify
terms apparently identical but internally different in the Calculus of Inductive
Constructions.
.. cmd:: Print {? Sorted } Universes {? Subgraph ( {* @qualid } ) } {? @string }
:name: Print Universes
This command can be used to print the constraints on the internal level
of the occurrences of :math:`\Type` (see :ref:`Sorts`).
The :n:`Subgraph` clause limits the printed graph to the requested names (adjusting
constraints to preserve the implied transitive constraints between
kept universes).
The :n:`Sorted` clause makes each universe
equivalent to a numbered label reflecting its level (with a linear
ordering) in the universe hierarchy.
:n:`@string` is an optional output filename.
If :n:`@string` ends in ``.dot`` or ``.gv``, the constraints are printed in the DOT
language, and can be processed by Graphviz tools. The format is
unspecified if `string` doesn’t end in ``.dot`` or ``.gv``.
Polymorphic definitions
~~~~~~~~~~~~~~~~~~~~~~~
For polymorphic definitions, the declaration of (all) universe levels
introduced by a definition uses the following syntax:
.. coqtop:: in
Polymorphic Definition le@{i j} (A : Type@{i}) : Type@{j} := A.
.. coqtop:: all
Print le.
During refinement we find that :g:`j` must be larger or equal than :g:`i`, as we
are using :g:`A : Type@{i} <= Type@{j}`, hence the generated constraint. At the
end of a definition or proof, we check that the only remaining
universes are the ones declared. In the term and in general in proof
mode, introduced universe names can be referred to in terms. Note that
local universe names shadow global universe names. During a proof, one
can use :cmd:`Show Universes` to display the current context of universes.
It is possible to provide only some universe levels and let Coq infer the others
by adding a :g:`+` in the list of bound universe levels:
.. coqtop:: all
Fail Definition foobar@{u} : Type@{u} := Type.
Definition foobar@{u +} : Type@{u} := Type.
Set Printing Universes.
Print foobar.
This can be used to find which universes need to be explicitly bound in a given
definition.
Definitions can also be instantiated explicitly, giving their full
instance:
.. coqtop:: all
Check (pidentity@{Set}).
Monomorphic Universes k l.
Check (le@{k l}).
User-named universes and the anonymous universe implicitly attached to
an explicit :g:`Type` are considered rigid for unification and are never
minimized. Flexible anonymous universes can be produced with an
underscore or by omitting the annotation to a polymorphic definition.
.. coqtop:: all
Check (fun x => x) : Type -> Type.
Check (fun x => x) : Type -> Type@{_}.
Check le@{k _}.
Check le.
.. flag:: Strict Universe Declaration
Turning this flag off allows one to freely use
identifiers for universes without declaring them first, with the
semantics that the first use declares it. In this mode, the universe
names are not associated with the definition or proof once it has been
defined. This is meant mainly for debugging purposes.
.. flag:: Private Polymorphic Universes
This flag, on by default, removes universes which appear only in
the :term:`body` of an opaque polymorphic definition from the definition's
universe arguments. As such, no value needs to be provided for
these universes when instantiating the definition. Universe
constraints are automatically adjusted.
Consider the following definition:
.. coqtop:: all
Lemma foo@{i} : Type@{i}.
Proof. exact Type. Qed.
Print foo.
The universe :g:`Top.xxx` for the :g:`Type` in the :term:`body` cannot be accessed, we
only care that one exists for any instantiation of the universes
appearing in the type of :g:`foo`. This is guaranteed when the
transitive constraint ``Set <= Top.xxx < i`` is verified. Then when
using the :term:`constant` we don't need to put a value for the inner
universe:
.. coqtop:: all
Check foo@{_}.
and when not looking at the :term:`body` we don't mention the private
universe:
.. coqtop:: all
About foo.
To recover the same behaviour with regard to universes as
:g:`Defined`, the :flag:`Private Polymorphic Universes` flag may
be unset:
.. coqtop:: all
Unset Private Polymorphic Universes.
Lemma bar : Type. Proof. exact Type. Qed.
About bar.
Fail Check bar@{_}.
Check bar@{_ _}.
Note that named universes are always public.
.. coqtop:: all
Set Private Polymorphic Universes.
Unset Strict Universe Declaration.
Lemma baz : Type@{outer}. Proof. exact Type@{inner}. Qed.
About baz.
.. _universe-polymorphism-in-sections:
Universe polymorphism and sections
----------------------------------
:cmd:`Variables`, :cmd:`Context`, :cmd:`Universe` and
:cmd:`Constraint` in a section support polymorphism. This means that
the universe variables and their associated constraints are discharged
polymorphically over definitions that use them. In other words, two
definitions in the section sharing a common variable will both get
parameterized by the universes produced by the variable declaration.
This is in contrast to a “mononorphic” variable which introduces
global universes and constraints, making the two definitions depend on
the *same* global universes associated with the variable.
It is possible to mix universe polymorphism and monomorphism in
sections, except in the following ways:
- no monomorphic constraint may refer to a polymorphic universe:
.. coqtop:: all reset
Section Foo.
Polymorphic Universe i.
Fail Constraint i = i.
This includes constraints implicitly declared by commands such as
:cmd:`Variable`, which may need to be used with universe
polymorphism activated (locally by attribute or globally by option):
.. coqtop:: all
Fail Variable A : (Type@{i} : Type).
Polymorphic Variable A : (Type@{i} : Type).
(in the above example the anonymous :g:`Type` constrains polymorphic
universe :g:`i` to be strictly smaller.)
- no monomorphic :term:`constant` or inductive may be declared if polymorphic
universes or universe constraints are present.
These restrictions are required in order to produce a sensible result
when closing the section (the requirement on :term:`constants <constant>` and inductive types
is stricter than the one on constraints, because constants and
inductives are abstracted by *all* the section's polymorphic universes
and constraints).
|