Zulip Chat Archive
Stream: new members
Topic: Can't understand universes in inductives
Jakub Nowak (Dec 02 2025 at 15:55):
If I write:
inductive Foo : Type → Type where
| nil : {α : Type} → Foo α
then Lean accepts this without errors.
But when I add constructor like this:
inductive Foo : Type → Type where
| nil : {α : Type} → Foo α
| cons : {α β : Type} → (α → Foo β) → Foo β
then now I get error about universes in constructor nil which worked fine before.
What's going on?
Aaron Liu (Dec 02 2025 at 15:56):
that's because the index is not being promoted to a parameter anymore
Aaron Liu (Dec 02 2025 at 15:58):
Since you can rewrite the first Foo as
inductive Foo (α : Type) : Type where
| nil : Foo α
But you can't do the same kind of thing for the other Foo
Jakub Nowak (Dec 02 2025 at 16:00):
I see. That's kinda confusing, is there a reason why Lean does that automatic promotion of indexes to parameters?
Aaron Liu (Dec 02 2025 at 16:00):
it's so you don't get the error on a perfectly reasonable inductive
Jakub Nowak (Dec 02 2025 at 16:01):
Is it reasonable though? It seems like it's impossible to write inductive with signature Type → Type unless the argument is a parameter.
Aaron Liu (Dec 02 2025 at 16:03):
so it's fine if the argument is a parameter
Kenny Lau (Dec 02 2025 at 16:05):
@Jakub Nowak Foo β must contain cons f for any function f : α → Foo β for any α : Type!! Surely that is too big for something in Type
Jakub Nowak (Dec 02 2025 at 16:05):
Actually, I think that
inductive Foo (α : Type) : Type where
| nil : Foo α
and
inductive Foo : Type → Type where
| nil : (α : Type) → Foo α
aren't the same.
In first case α is a parameter of Foo, while in second, it's a parameter of Foo.nil.
Aaron Liu (Dec 02 2025 at 16:09):
comparison:
inductive Foo (α : Type) : Type where
| nil : Foo α
/--
info: inductive Foo : Type → Type
number of parameters: 1
constructors:
Foo.nil : {α : Type} → Foo α
-/
#guard_msgs in
#print Foo
and the other one
inductive Foo : Type → Type where
| nil : (α : Type) → Foo α
/--
info: inductive Foo : Type → Type
number of parameters: 1
constructors:
Foo.nil : (α : Type) → Foo α
-/
#guard_msgs in
#print Foo
Aaron Liu (Dec 02 2025 at 16:09):
so I think they're basically the same
Kenny Lau (Dec 02 2025 at 16:14):
@Jakub Nowak in both cases, each Foo α just contains .nil and nothing else
Last updated: Dec 20 2025 at 21:32 UTC