Zulip Chat Archive
Stream: general
Topic: crazy universe
Patrick Massot (Aug 13 2021 at 22:10):
Does anyone understands why Lean gets crazy with universes in docs#topological_add_group.of_comm_of_nhds_zero? I can fix this by replacing G : Type*
by G : Type u
but it would be nice to understand when this happens because it really causes a lot of confusion when it strikes.
Eric Wieser (Aug 13 2021 at 22:12):
You can also fix it by moving G
to a variables statement
Patrick Massot (Aug 13 2021 at 22:16):
Could we have a linter for this? I can't imagine a situation where a parameter can have such a universe annotation.
Kyle Miller (Aug 13 2021 at 22:27):
It seems to not realize that once it's solved for the universe variables it can generalize max u_1 u_2
(or, rather, it found too specialized of a solution through whatever algorithm it uses). Here's the pp.universes
output at the beginning of that lemma's proof:
G : Type (max u_1 u_2),
_inst_5 : comm_group.{(max u_1 u_2)} G,
_inst_6 : topological_space.{(max u_1 u_2)} G,
hmul :
tendsto.{(max u_1 u_2) (max u_1 u_2)}
(uncurry.{(max u_1 u_2) (max u_1 u_2) (max u_1 u_2)} has_mul.mul.{(max u_1 u_2)})
(๐ 1 รแถ ๐ 1)
(๐ 1),
hinv : tendsto.{(max u_1 u_2) (max u_1 u_2)} (ฮป (x : G), xโปยน) (๐ 1) (๐ 1),
hleft : โ (xโ : G), ๐ xโ = map.{(max u_1 u_2) (max u_1 u_2)} (ฮป (x : G), xโ * x) (๐ 1)
โข topological_group.{(max u_1 u_2)} G
Kyle Miller (Aug 13 2021 at 22:42):
In case it's helpful in figuring out what's going on, it's something to do with the hinv
argument.
lemma crazy_universe {G : Type*} [topological_space G]
(f : G โ G โ G) (a : G)
(hinv : tendsto (uncurry f) ((๐ a) รแถ ๐ a) (๐ a)) :
true :=
sorry -- can see that G : Type (max u_1 u_2)
Kyle Miller (Aug 13 2021 at 22:49):
This reproduces it, too:
def crazy_universe {G : Type*} (F : filter G)
(h : F รแถ F = F รแถ F) : true :=
sorry -- can see G : Type (max u_1 u_2)
Strangely, replacing filter
with set
doesn't show this behavior:
import order.filter.basic
def crazy_universe {G : Type*} (s : filter G)
(h : s.prod s = s.prod s) : true :=
sorry -- can see G : Type (max u_1 u_2)
def ok_universe {G : Type*} (s : set G)
(h : s.prod s = s.prod s) : true :=
sorry -- can see G : Type u_1
Kyle Miller (Aug 13 2021 at 23:03):
Changing the transparency of set
to irreducible
changes the inferred universe:
attribute [irreducible] set
def crazy_universe' {G : Type*} (s : set G)
(h : s.prod s = s.prod s) : true :=
sorry -- can see G : Type (max u_1 u_2)
Kevin Buzzard (Aug 14 2021 at 07:12):
I've seen a few of these recently and I've always just figured that it's the fact that lean universe arithmetic is hardly its strong point and it's just easier to do it yourself sometimes
Kevin Buzzard (Aug 14 2021 at 07:13):
I agree with Patrick that it's confusing. It can often manifest itself in things taking much longer to typecheck than they should
Reid Barton (Aug 14 2021 at 10:27):
This sort of thing is why I largely stopped using Type*
outside of variables
.
Floris van Doorn (Aug 14 2021 at 17:58):
Yeah, we can definitely have a linter that catches this kind of behavior.
We can probably just check for an argument of the form Type (max _ _)
or Sort (max _ _)
(ignoring the conclusion). I think that doesn't give many false positives.
Floris van Doorn (Aug 15 2021 at 03:59):
I opened #8677, where I fix a bunch of current bad universes in the library.
The linter has a bunch of false positives in declarations, such as src#module.projective, where Type (max u v)
is used as an arbitrary type larger than Type u
.
There were also still a bunch of bad declarations that weren't caught by my linter, like src#algebraic_geometry.Spec.SheafedSpace_map, where CommRing
means CommRing.{max u v}
. In this case I was lucky, since an auxiliary declaration part of this one was caught by the linter.
I think we should make a linter where we properly test for declarations whether it has two universe variables u
and v
that only occur as max u v
. This is a little trickier to test than my previous suggestion, but I'll take another stab.
Mario Carneiro (Aug 15 2021 at 04:03):
I don't think false positives are a problem here, since the few cases where they are used legitimately could use a small acknowledgment in the form of a @[nolint]
and/or comment
Floris van Doorn (Aug 15 2021 at 04:17):
That's true, but note that we also need to apply nolint
to all lemmas that use module.projective
. But the current version doesn't catch much more false positives (there are ~5 rarely used declarations, for example src#uliftable.adapt_up in control/uliftable
).
I hope that the proper version of the linter catches more declarations that are ignored by the current linter.
Floris van Doorn (Aug 15 2021 at 06:16):
@Simon Hudon Can you tell me how to fix the universe levels of src#uliftable.down_map?
Currently the universes uโ
and vโ
only occur in the declaration as max uโ vโ
. I suspect that G : Type โ Type vโ
should be replaced by G : Type uโ โ Type vโ
?
Simon Hudon (Aug 15 2021 at 06:43):
@Floris van Doorn you're right, that's what it should be. That's a simple fix
Floris van Doorn (Aug 15 2021 at 06:53):
Ok, I've added it to #8677
Simon Hudon (Aug 15 2021 at 06:54):
Oh you're a bit faster than me: #8684
Floris van Doorn (Aug 15 2021 at 06:59):
I've PR'd the linter in #8685. This version catches a lot more problematic declarations than the earlier version, and I don't think it gives any false positives.
Patrick Massot (Aug 15 2021 at 09:19):
Great! Thank you very much Floris!
Last updated: Dec 20 2023 at 11:08 UTC