Zulip Chat Archive

Stream: lean4

Topic: Stuck at solving universe constraint


Marcus Rossel (Sep 14 2021 at 11:08):

I have a pretty contrived MWE, showing a case where Lean/I can't figure out a universe constraint:

inductive E
  | e₁
  | e₂

variable (α β) [ia : Inhabited α] [ib : Inhabited β]

def E.type : E  Type _
  | e₁ => α
  | e₂ => α × β

variable {α β}

def E.thing : (e : E)  (E.type α β e)
  | e₁ => @Inhabited.default α _
  | e₂ => (@Inhabited.default α _, @Inhabited.default β _)

def f (e : E) : Prop :=
  (@E.thing α β ia ib e) = (@E.thing α β ia ib e)

On the last line, Lean complains:

stuck at solving universe constraint
  max (?u.4095+1) (?u.4106+1) =?= max (?u.4096+1) (?u.4095+1)
while trying to unify
  Type (max ?u.4106 ?u.4095) : Type (max (?u.4106 + 1) (?u.4095 + 1))
with
  Type (max ?u.4096 ?u.4095) : Type (max (?u.4096 + 1) (?u.4095 + 1))

I think the problem arises in some way from the type signature of E.type:

E.type : Type (max u_1 u_2)  Type u_2  E  Type (max u_1 u_2)

The signature shows that Lean has to assume α to live in a universe at least as big as β's, so we get α : Type (max u_1 u_2).
Changing E.type to the following:

def E.type : E  Type _
  | e₁ => α × β
  | e₂ => α × β

... makes the type signature simpler (Type u_1 → Type u_2 → E → Type (max u_1 u_2)) and fixes the problem.
What is the underlying problem here?

Marcus Rossel (Sep 14 2021 at 11:11):

Here's a slight simplification of the MWE:

inductive E
  | e₁
  | e₂

def E.type (α β : Type _) : E  Type _
  | e₁ => α
  | e₂ => α × β

def make (α) : α := sorry

def E.thing : (e : E)  (E.type α β e) :=
  make (E.type α β e)

Reid Barton (Sep 14 2021 at 11:47):

Lean inferred the correct type for E.type, but it's kind of unusable (unless you write explicit universe variable arguments) because there is no way to infer u_1 at a use of it. I imagine you just want to assume that α and β live in the same universe.

Reid Barton (Sep 14 2021 at 11:52):

Also, I can't tell what you're doing from the MWE obviously, but you could consider forgetting about universes and just using Type everywhere.

Marcus Rossel (Sep 14 2021 at 12:07):

I'm never sure what I'd be "losing" by constraining type-parameters to certain universes, so I always go for Type _.
But having α and β live in the same universe seems like a good solution.

Mac (Sep 14 2021 at 15:27):

One thing that surprises me here is thatα and β are in the same binder, but don't they have the same type (and thus the same universe) . Apparently Type _ does some magic that assigns them different types none-the-less (which wouldn't be possible normally). Is that expected? It seems rather odd to me.

Reid Barton (Sep 14 2021 at 15:28):

I guess it gets syntactically expanded to two binders first, then the metavariables get filled in. Whether this is a good thing is perhaps debatable.

Marcus Rossel (Sep 14 2021 at 16:17):

FWIW, when I write def foo (α β) : ... I expect the semantics of def foo (α : Type u) (β : Type v) : ..., because it's the most general version.

Mac (Sep 14 2021 at 16:35):

@Marcus Rossel note that def foo (α β) : ... actually gives def foo (α : Sort u) (β : Sort v) : ... because that it is the most general version. :P

Marcus Rossel (Sep 14 2021 at 16:38):

Ahh of course :D


Last updated: Dec 20 2023 at 11:08 UTC