Zulip Chat Archive
Stream: general
Topic: Universe Vars
Marcus Rossel (Nov 27 2024 at 09:45):
It seems I don't understand universe variables (universe parameters?) correctly. In the following example, everything works as expected:
variable (h : ∀ (α : Type _), True)
example : True := h Nat
Here, h
has type Type ?u.3477 → True
-- that is, the universe level is a level mvar.
Now if I try to replace the _
with a universe variable, things don't work:
universe u
variable (h : ∀ (α : Type u), True)
example : True := h Nat
-- ^^^
/-
application type mismatch
h Nat
argument
Nat
has type
Type : Type 1
but is expected to have type
Type u : Type (u + 1)
-/
Here, h
has type Type u → True
. I don't understand what that's supposed to mean, because I thought universe variables like u
only made sense wrt. to a definition.
Riccardo Brasca (Nov 27 2024 at 09:48):
u
is a fixed universe, it can be Type
but it can be anything else, while Nat : Type
, this is why Lean is complaining.
Riccardo Brasca (Nov 27 2024 at 09:48):
Note that you cannot quantify over universes, so you cannot say "for all u
blah blah"
Riccardo Brasca (Nov 27 2024 at 10:00):
What probably confuses you is that things like
universe u
axiom h (X : Type u) : True
example : True := h Nat
do work. This is because in this case Lean actually create a family of axioms h.{u}
, one for each universe u
, giving the impression that h
starts with ∀ u, ...
, but technically this is not the case.
Edward van de Meent (Nov 27 2024 at 10:03):
so: universes in the type of arguments are fixed (in the content of your def
/theorem
, that is), while universes in the type of declarations are variables.
Riccardo Brasca (Nov 27 2024 at 10:05):
This is my mental model (not sure if it is 100% correct)
Edward van de Meent (Nov 27 2024 at 10:05):
i'm pretty sure it's correct, that's why i summarised
Riccardo Brasca (Nov 27 2024 at 10:23):
Also, concerning your first example,
variable (h : ∀ (α : Type _), True)
example : True ∧ True := ⟨h Nat, h Type⟩
does not work, since _
is a metavariable, and Lean waits to give it a value. After the first h Nat
, _
is 0
and so you cannot write h Type
.
Riccardo Brasca (Nov 27 2024 at 10:24):
While
universe u
axiom h (X : Type u) : True
example : True ∧ True := ⟨h Nat, h Type⟩
is OK.
Filippo A. E. Nuccio (Nov 27 2024 at 10:47):
Riccardo Brasca said:
Also, concerning your first example,
variable (h : ∀ (α : Type _), True) example : True ∧ True := ⟨h Nat, h Type⟩
does not work, since
_
is a metavariable, and Lean waits to give it a value. After the firsth Nat
,_
is0
and so you cannot writeh Type
.
I am not 100% sure that this has to do with metavariables, because this works
def h (α : Type _) : True := True.intro
example : True ∧ True := ⟨h Nat, h Type⟩
(and _
is also a metavariable); I think this is again related to what @Edward van de Meent was saying about the role of universes in arguments vs. in declarations...
Edward van de Meent (Nov 27 2024 at 10:57):
variable
s aren't declarations? they are arguments.
Riccardo Brasca (Nov 27 2024 at 11:12):
@Filippo A. E. Nuccio I think your example works because Lean creates a family of def
, each one with a metavariable
Riccardo Brasca (Nov 27 2024 at 11:13):
But I can very well be wrong here
Filippo A. E. Nuccio (Nov 27 2024 at 11:17):
Edward van de Meent said:
variable
s aren't declarations? they are arguments.
Then I do not understand your answer above
so: universes in the type of arguments are fixed (in the content of your
def
/theorem
, that is), while universes in the type of declarations are variables.
Edward van de Meent (Nov 27 2024 at 11:19):
what i mean, is that if you have def foo : Type u
, you get foo.{u} : Type u
for any u
, so it is variable. however, in the content of def foo (x:Type u) : _ := bla
, at bla
you dont get to choose the level u
anymore.
Edward van de Meent (Nov 27 2024 at 11:22):
the argument (x:Type u)
has fixed universe u
, and so does variable (x:Type u)
(since they're both arguments)
Marcus Rossel (Nov 27 2024 at 11:48):
Riccardo Brasca said:
Filippo A. E. Nuccio I think your example works because Lean creates a family of
def
, each one with a metavariable
It seems that when you have a level wildcard in a def
, then Lean does not create a level mvar for it, but instead creates a universe parameter for it. That is, hovering over the definition of h
gives h.{u_1} (α : Type u_1) : True
.
I guess that makes sense, because it would feel kind of strange to have a definition with lingering mvars.
Riccardo Brasca (Nov 27 2024 at 12:17):
Ah yes, sure.
Kyle Miller (Nov 27 2024 at 23:06):
@Marcus Rossel The rules are basically (1) "each lingering level metavariable at the end of elaborating the "header" of a declaration (the binders and the resulting type) is replaced with a fresh level parameter" and (2) "when a constant is elaborated, its level parameters get instantiated with fresh level metavariables".
Rule 2 should be thought of as being like how implicit arguments work. Implicit parameters get instantiated with fresh expression metavariables when an application is being elaborated.
Last updated: May 02 2025 at 03:31 UTC