Zulip Chat Archive
Stream: new members
Topic: Sort vs Type
Lars Ericson (Dec 24 2023 at 23:58):
In Theorem Proving in Lean 4 at the end of the section on Dependent Type Theory we see
#check @id -- {α : Type u_1} → α → α
A run of #check @id
in Lean 4 Web gives, instead of {α : Type u_1} → α → α
, the result
@id : {α : Sort u_1} → α → α
We can put in two versions of id
and get either Type u_1
or Sort u_1
:
def ident {α : Type u} (x : α) := x
#check ident -- ident.{u} {α : Type u} (x : α) : α
def ident1 {α : Sort u} (x : α) := x
#check ident1 -- ident1.{u} {α : Sort u} (x : α) : α
SoSort u
or Type u
are equivalent in the above example.
My understanding is that Prop
is a synonym for Sort 0
and Type
is a synonym for Type 0
and Type 0
is a synonym for Sort 1
making Type n
a synonym for Sort (n+1)
.
Does having both Sort
and Type
in Lean 4 add value? It seems like one or the other would be sufficient. What am I missing?
Kyle Miller (Dec 25 2023 at 00:08):
Type u
is exactly Sort (u + 1)
internally.
One reason for Type u
is that Prop
has some different rules for which universe a pi type lives in. If you work with Sort u
sometimes the universe level expressions can get more complicated than if you just used Type u
.
One reason for Sort u
is that then you can make definitions that work for Prop
too. Potentially Lean could just not have Sort
at all, leaving you to create separate definitions for Prop
and Type u
. It's nice being able to define a single definition that works for both when possible.
Lars Ericson (Dec 25 2023 at 16:35):
Thanks for the explanation! It would be nice to write this down in a record similar to Python PEPs. The explanation shows that it is a parsimonious choice.
I'm curious why the choice of abbreviation is sticky in the interpreter in the sense that it remembers whether I used Type
or Sort
in
def ident {α : Type u} (x : α) := x
#check ident -- ident.{u} {α : Type u} (x : α) : α
def ident1 {α : Sort u} (x : α) := x
#check ident1 -- ident1.{u} {α : Sort u} (x : α) : α
when under the hood they are equivalent (i.e. why doesn't this normalize to one canonical choice).
Yakov Pechersky (Dec 25 2023 at 17:35):
They are not equivalent. Type u will never be Prop. Sort u can be.
Eric Wieser (Dec 25 2023 at 17:41):
As you said yourself
Lars Ericson said:
Type n
a synonym forSort (n+1)
.
So of course Lean knows the difference between Type u
and Sort u
, because they are different
Eric Wieser (Dec 25 2023 at 17:42):
I suspect if you write Sort (u +1)
, Lean still prints it as Type u
, which would a way to disprove your "stickiness" claim.
Lars Ericson (Dec 25 2023 at 18:36):
@Eric Wieser consider this code
def ident {α : Type u} (x : α) := x
#check ident -- ident.{u} {α : Type u} (x : α) : α
#check ident True
def ident1 {α : Sort u} (x : α) := x
#check ident1 -- ident1.{u} {α : Sort u} (x : α) : α
#check ident1 True
This gives the following messages in Lean 4 Playground (Zulip provides a button to push on top right corner of the snippet, so you can reproduce):
LeanProject.lean:2:0
ident.{u} {α : Type u} (x : α) : α
LeanProject.lean:3:0
ident True : Prop
LeanProject.lean:6:0
ident1.{u} {α : Sort u} (x : α) : α
LeanProject.lean:7:0
ident1 True : Prop
The first version gives Type u
in the signature. The second version gives Sort u
in the signature. So Lean is remembering whether Type
or Sort
was used in the input definition. Also, ident
with Type u
works fine on a Prop
even though "Type u will never be Prop". I wouldn't call "stickiness" a "claim". It is just an observation of the behavior of the interpreter: Sort
in comes out as Sort
. Type
in comes out as Type
. And, in this case, Prop
unifies with Type
.
Junyan Xu (Dec 25 2023 at 18:40):
def ident {α : Sort (u + 1)} (x : α) := x
#check ident -- ident.{u} {α : Type u} (x : α) : α -- Not printed as Sort (u + 1)
#check ident True
is what Eric is telling you.
(As an aside, I've heard that Lean 4 normalizes universes aggressively.)
Sabrina Jewson (Dec 25 2023 at 19:27):
Clearly not that aggressively ;)
example : Sort (imax u (imax v w)) = Sort (imax (max u v) w) := rfl -- fails :(
Lars Ericson (Dec 25 2023 at 19:55):
OK so Sort u
stays as Sort u
because u
could be 0 but Sort (u+1)
normalizes to Type u
.
I'm still confused about this:
def ident {α : Type u} (x : α) := x
#check ident True
because per above Type u
should never match Prop
and True
is a Prop
.
To verify that True
is a Prop
I write:
def x : Prop := True
#check x -- gives back x : Prop
#eval x -- throws an error
The #eval x
gives error
failed to synthesize
Decidable x
This is above my head. Why can't it just give back True
?
Henrik Böving (Dec 25 2023 at 20:01):
I'm a bit surprised that this Type u with Prop thing works myself but regarding the eval question: Evaluation is not doing some type theoretic lambda calculus reduction stuff, it attempts to compile and (somewhat) efficiently execute your code in a VM.
If you want to do reduction in the lambda calculus style you'll have to use #reduce, note that #reduce is not expected to be very performant so if you wish to do actual computation you should prefer eval.
Matt Diamond (Dec 25 2023 at 20:06):
I don't see anything contradictory about this:
def ident {α : Type u} (x : α) := x
#check ident True
When you call ident
, you pass in True
as x
. Since the type of True
is Prop
and you declared that the type of x
is α
, α
equals Prop
. And since the type of Prop
is Type
(which you can verify with #check Prop
), {α : Type u}
checks just fine.
Eric Wieser (Dec 25 2023 at 20:33):
The failing test would be #check ident trivial
Eric Wieser (Dec 25 2023 at 20:34):
Lars Ericson said:
OK so
Sort u
stays asSort u
becauseu
could be 0 butSort (u+1)
normalizes toType u
.
There's not really any normalization going on here, it's just the pretty-printing rules
Lars Ericson (Dec 26 2023 at 03:30):
I understand: Prop
is a synonym for Sort 0
, and Sort 0
has type Sort 1
a/k/a Type 0
a/k/a Type
, and
def ident {α : Type u} (x : α) := x
#check ident trivial -- Fails
#check ident -- ident.{u} {α : Type u} (x : α) : α
#check id -- id.{u} {α : Sort u} (a : α) : α
#check id trivial -- Succeeds
Last updated: May 02 2025 at 03:31 UTC