Zulip Chat Archive

Stream: mathlib4

Topic: Introducing all dependent variables


Kyle Miller (Mar 28 2023 at 18:34):

Picking back up some discussion from while ago, this morning I was looking at how to automatically introduce all the dependencies you need to introduce a typeclass, or really anything that depends on a typeclass.

Kyle Miller (Mar 28 2023 at 18:34):

I've just done a few tests, but it looks promising:

section
variable! [Module R M]
/-
R: Type ?u.18467
M: Type ?u.18470
inst✝²: Semiring R
inst✝¹: AddCommMonoid M
inst✝: Module R M
-/
end

section
variable! [Algebra R A]
/-
R: Type ?u.18767
A: Type ?u.18770
inst✝²: CommSemiring R
inst✝¹: Semiring A
inst✝: Algebra R A
-/
end

section
variable! [Module R M] [Module S M'] (σ : R →+* S) (f : M →ₛₗ[σ] M')
/-
R: Type ?u.20902
M: Type ?u.20905
S: Type ?u.20932
M': Type ?u.20935
inst✝⁵: Semiring R
inst✝⁴: AddCommMonoid M
inst✝³: Module R M
inst✝²: Semiring S
inst✝¹: AddCommMonoid M'
inst✝: Module S M'
σ: R →+* S
f: M →ₛₗ[σ] M'
-/
end

Kyle Miller (Mar 28 2023 at 18:34):

code

(v2 below)

Kevin Buzzard (Mar 28 2023 at 18:36):

Can it do unique factorization domains? :-) (I ask because I had no clue how to say "let R be a unique factorization domain" until a few weeks ago)

Kyle Miller (Mar 28 2023 at 18:38):

@Kevin Buzzard I think you'll have to give me a hint, since I'm at least a few weeks behind you there

Kevin Buzzard (Mar 28 2023 at 19:25):

My understanding is that right now you have to say variables (R : Type) [comm_ring R] [is_domain R] [unique_factorization_monoid R]

Kyle Miller (Mar 28 2023 at 19:56):

Ah, for that we could have a fake typeclass that implies those typeclasses and which doesn't itself appear in the final variables list.

section
-- Imagine this is marked in some way as being an alias for `variables!` purposes
class UniqueFactorizationDomain (R : Type _) [CommRing R] [IsDomain R] [UniqueFactorizationMonoid R]

variable! [UniqueFactorizationDomain R]
/-
R: Type ?u.26397
inst✝³: CommRing R
inst✝²: IsDomain R
inst✝¹: UniqueFactorizationMonoid R
inst✝: UniqueFactorizationDomain R -- imagine it doesn't include this
-/
end

Kyle Miller (Mar 28 2023 at 19:57):

Here's a version that seems to be more robust. I was having a hard time juggling the pending metavariables and getting into the right local contexts, so instead this keeps inserting missing variables and re-elaborating until there are no more failures.

code v2

(edit: v3 below)

Kyle Miller (Mar 28 2023 at 19:58):

There's a limitation with this approach, though, where it doesn't do any computations to see whether some typeclasses imply others

section
variable! (σ : R →+* S) [Module R M] [Module S M']
/-
R: Type ?u.24671
S: Type ?u.24674
M: Type ?u.24695
M': Type ?u.24727
inst✝⁷: NonAssocSemiring R
inst✝⁶: NonAssocSemiring S
σ: R →+* S
inst✝⁵: Semiring R
inst✝⁴: AddCommMonoid M
inst✝³: Module R M
inst✝²: Semiring S
inst✝¹: AddCommMonoid M'
inst✝: Module S M'
-/
end

Kevin Buzzard (Mar 28 2023 at 20:01):

oh man, I want to change the defaults to make everything a comm_ring. Would that be possible? Heh, maybe I'm just asking for variable :-)

Kyle Miller (Mar 28 2023 at 20:04):

Putting some CommRing instances first definitely fixes this last problem:

section
variable! [CommRing R] [CommRing S] (σ : R →+* S) [Module R M] [Module S M']
/-
R: Type ?u.30154
S: Type ?u.30157
M: Type ?u.30320
M': Type ?u.30490
inst✝⁵: CommRing R
inst✝⁴: CommRing S
σ: R →+* S
inst✝³: AddCommMonoid M
inst✝²: Module R M
inst✝¹: AddCommMonoid M'
inst✝: Module S M'
-/
end

Kyle Miller (Mar 28 2023 at 20:05):

I could imagine there being a configuration option where you can give rules like "if you need a NonAssocSemiring, add a CommRing instead"

Thomas Murrills (Mar 28 2023 at 20:07):

Really nice! For the syntax, I wonder: should it use [[]] (or whatever brackets we end up using for that) instead of variable!? E.g. variable [[Module R M]]? This would be consistent with doing the same thing inside defs and theorems. Or is that impractical for some reason?

Kyle Miller (Mar 28 2023 at 20:08):

This has wider scope than a [[...]] binder:

variable! (σ : R →+* S)
/-
R: Type ?u.30490
S: Type ?u.30493
inst✝¹: NonAssocSemiring R
inst✝: NonAssocSemiring S
σ: R →+* S
-/

Kyle Miller (Mar 28 2023 at 20:08):

Also, we can't define our own binders, unfortunately.

Thomas Murrills (Mar 28 2023 at 20:09):

Ah, it also introduces dependencies for non-typeclass variables, got it!

Thomas Murrills (Mar 28 2023 at 20:10):

Kyle Miller said:

Also, we can't define our own binders, unfortunately.

Oh, that is unfortunate…!

Kevin Buzzard (Mar 28 2023 at 20:11):

But I want AddCommGroups! This is why I realise that I should probably just stick to variable. How about analysis? Does [normed_space 𝕜 E] fill in the right gaps? What about [normed_space ℝ E]?

Kevin Buzzard (Mar 28 2023 at 20:13):

What about differential geometry? How much more do I have to give than [smooth_manifold_with_corners I M]?

Kyle Miller (Mar 28 2023 at 20:13):

It doesn't seem that NormedSpace is ported yet.

Kyle Miller (Mar 28 2023 at 20:14):

What's your objection about AddCommGroup?

Kevin Buzzard (Mar 28 2023 at 20:14):

your M was a monoid.

Kyle Miller (Mar 28 2023 at 20:15):

Then you can add that it's an additive commutative group:

variable! [AddCommGroup M] [Module R M]
/-
M: Type ?u.31767
R: Type ?u.31770
inst✝²: AddCommGroup M
inst✝¹: Semiring R
inst✝: Module R M
-/

Kevin Buzzard (Mar 28 2023 at 20:16):

But now R isn't a commutative ring -- what I'm saying is that I'm now understanding that actually I'd be better off with variable because tyipcally I do not want the minimal assumptions for which module makes sense (in fact I never want these assumptions)

Kevin Buzzard (Mar 28 2023 at 20:17):

Of course, others might.

Kyle Miller (Mar 28 2023 at 20:17):

Maybe we don't want variable! in mathlib code, but it at least shows you everything you need to address on your way to a complete variable line.

Kyle Miller (Mar 28 2023 at 20:17):

You can use variable! everywhere variable already works.

Thomas Murrills (Mar 28 2023 at 20:18):

But also R was explicitly given as a commutative ring in the first example but not the second.

Thomas Murrills (Mar 28 2023 at 20:19):

@Kevin Buzzard maybe you want that sort of abbreviation typeclass mentioned earlier to use in place of Module here (which would add all the assumptions you do want)?

Kyle Miller (Mar 28 2023 at 20:20):

There could be configuration options to help you deal with specific situations, like a commutative algebra setting where whenever there is a request for something CommRing implies then use CommRing, etc.

Kevin Buzzard (Mar 28 2023 at 20:21):

I don't really know what I want, I'm just wondering where these ideas are going. For me I always want R to be a commutative ring and M an R-module but I would imagine that the non-commutative guys always want R to be a ring. If semiring people actually exist (something I'm slightly skeptical about) then they'll want something else. I don't have a clear idea about how to support all these competing "canonical" assumptions.

Kevin Buzzard (Mar 28 2023 at 20:21):

Aah, yeah maybe switch on "commutative algebra mode" and then try it :-)

Kyle Miller (Mar 28 2023 at 20:21):

it could be variable! (config := commAlg) ... for you

Kyle Miller (Mar 28 2023 at 20:24):

Another example to show possible scope (introducing Decidable assumptions):

variable! (p : Nat  Prop) (h :  k, p k) (h : 0 < Nat.find h)
/-
p: ℕ → Prop
h✝: ∃ k, p k
inst✝: DecidablePred fun n => p n
h: 0 < Nat.find h✝
-/

Eric Wieser (Mar 28 2023 at 20:27):

Isn't the answer to Kevin's requrest just to adapt your

-- Imagine this is marked in some way as being an alias for `variables!` purposes
class UniqueFactorizationDomain (R : Type _) [CommRing R] [IsDomain R] [UniqueFactorizationMonoid R]

example above, but for VectorSpace?

Kevin Buzzard (Mar 28 2023 at 20:29):

Do we actually want to make this class?

Kevin Buzzard (Mar 28 2023 at 20:29):

I mean, it would be handy for maths undergraduates but would it clog up the system somehow? I remember trying to make vector space just to mean "module over a field" and then this was reverted later because it somehow caused trouble. (I have a poor understanding of these sorts of issues)

Kyle Miller (Mar 28 2023 at 20:35):

Kevin Buzzard said:

Do we actually want to make this class?

Imagine classes that are used only for variables! and which would otherwise show a warning if you try to use them, and where they don't actually appear after they get expanded.

Eric Wieser (Mar 28 2023 at 20:35):

I don't think we want to make a class, but I think we could make it a macro of some kind

Eric Wieser (Mar 28 2023 at 20:35):

I don't think we want to make a class, but I think we could make it a macro of some kind (edit: bad train internet)

Eric Wieser (Mar 28 2023 at 20:37):

Presumably we can override the parser for theorem in mathlib to handle [[foo X]] or [!foo X] or similar so that we're not limited to variables lines

Thomas Murrills (Mar 28 2023 at 20:41):

(Off topic, but I do like e.g. ![foo X] or [foo X]! better than [[foo X]]; all those square brackets are a bit busy imo :) )

Thomas Murrills (Mar 28 2023 at 20:43):

The other option is of course introducing an analogous theorem!

Eric Wieser (Mar 28 2023 at 20:44):

![foo X] might conflict with vector notation; if not to Lean, then perhaps still to the reader

Kyle Miller (Mar 28 2023 at 21:34):

Eric Wieser said:

Isn't the answer to Kevin's requrest just to adapt your [...]

That's one answer, but it might be nice to be able to write variable! (σ : R →+* S) and have it introduce CommRings instead of NonAssocSemirings, if things are in commutative algebraist mode. The class alias idea is just for packaging up some common notions, when it's not obvious what you're supposed to introduce.

One reason using class for this is convenient (rather than creating macros) is that you get things like documentation on mouseover for free, and it'd be easier for non-macro-ologists to write their own. You also can see that your alias is type correct, which you don't get with macros. Still, I wonder if there are examples where macros would be more flexible.

Adam Topaz (Mar 28 2023 at 21:38):

Eric Wieser said:

Presumably we can override the parser for theorem in mathlib to handle [[foo X]] or [!foo X] or similar so that we're not limited to variables lines

Ideally we would find some way to do this under binders as well... What if I want to write forall R S [[Module R S]], ...?

Kyle Miller (Mar 28 2023 at 21:40):

Maybe more generally forall (! σ : R →+* S), ... and forall R S [! Module R S], ...

Adam Topaz (Mar 28 2023 at 21:40):

Is that possible? I thought Mario said it was not on some other thread.

Kyle Miller (Mar 28 2023 at 21:41):

I mean, forall R S [[Module R S]], ... isn't possible either, right?

Adam Topaz (Mar 28 2023 at 21:41):

right

Adam Topaz (Mar 28 2023 at 21:41):

that's why I'm asking the expert :)

Kyle Miller (Mar 28 2023 at 21:42):

I'm just dreaming. Maybe one day Lean 4 devs will create hooks for our own binder types.

Eric Wieser (Mar 28 2023 at 22:39):

Adam Topaz said:

Ideally we would find some way to do this under binders as well... What if I want to write forall R S [[Module R S]], ...?

That feels like a very niche case where it probably pays to be explicit

Adam Topaz (Mar 28 2023 at 22:40):

But this is a general idea... somehow [[Module R S]] should expand to [Semiring R] [AddMonoid S] [Module R S] in all places where this can apply.

Adam Topaz (Mar 28 2023 at 22:41):

And it's not too niche. For example it's certainly reasonable to imagine something like this being used in the definition of some universal property or something.

Adam Topaz (Mar 28 2023 at 22:41):

I suppose if we had such a general feature, we would end up using a lot more mixins, making it even more common.

Eric Wieser (Mar 28 2023 at 22:44):

For example it's certainly reasonable to imagine something like this being used in the definition of some universal property or something.

I would claim this probably happens no more than 10 times in mathlib, but maybe I'm not familiar with the parts that do this

Adam Topaz (Mar 28 2023 at 22:47):

maybe it happens so few times because it's not convenient to do (yet)?

Adam Topaz (Mar 28 2023 at 22:49):

It certainly was not convenient in lean3 not just because of the topic of this thread, but also because the instances didn't register (without using introsI and friends). But now that's been fixed in lean4, and I can imagine it becoming more commonplace.

Kyle Miller (Mar 28 2023 at 22:50):

What's the argument here Eric? I'm not sure why it matters if it's a niche use -- if we had the ability to make our own binders that seems like the right way to implement this feature everywhere.

Eric Wieser (Mar 28 2023 at 22:52):

Mainly just that custom binders in theorem/def/variable is probably possible to do without core changes, and that the benefit of supporting forall on top of that is pretty marginal.

Eric Rodriguez (Mar 28 2023 at 22:55):

Kyle Miller said:

it could be variable! (config := commAlg) ... for you

i wonder if this should be file-wide

Kyle Miller (Mar 28 2023 at 22:55):

Ok, I think saying forall is a niche use is completely independent of whether in the short term (i.e., before the hypothetical time when Lean supports custom binders) we might have custom theorem/def/variables for mathlib that support additional binder types. The only reason why it would matter is if someone were to suggest making a custom forall too.

Kyle Miller (Mar 28 2023 at 23:00):

Here's a v3, now with "Try this" and hopefully more robust binder insertion. Example:

variable!? [Algebra R A]
-- Try this: variable [CommSemiring R] [Semiring A] [Algebra R A]

code v3

Kyle Miller (Mar 28 2023 at 23:03):

I spent a while trying to track down a bug in what I thought was my own code, but I guess variable has the same bug.

This doesn't report any errors:

variable [Semiring R] [AddCommMonoid M] [Module R M] [Semiring S]
   [AddCommMonoid M'] [Module S M'] (f : M →ₛₗ[σ] M')

This does:

variable [Semiring R] [AddCommMonoid M] [Module R M] [Semiring S]
   [AddCommMonoid M'] [Module S M'] (f : M →ₛₗ[σ] M')
#check 1
/-
Error on f's type:
typeclass instance problem is stuck, it is often due to metavariables
  Module ?m.34167 M'
-/

Mario Carneiro (Mar 29 2023 at 00:40):

Kyle Miller said:

Ok, I think saying forall is a niche use is completely independent of whether in the short term (i.e., before the hypothetical time when Lean supports custom binders) we might have custom theorem/def/variables for mathlib that support additional binder types. The only reason why it would matter is if someone were to suggest making a custom forall too.

I am generally dubious of approaches that require replacing theorem/def etc. I think there will be a lot of unintended side effects of doing that across mathlib, e.g. some stuff hard coded in the server looking for a certain syntax kind, syntax kinds being referred to in mathport (or choice nodes!)

Johan Commelin (Mar 29 2023 at 02:49):

@Kyle Miller Is the problem that you didn't specify σ, and Lean is telling you this in a somewhat opaque way?

Kyle Miller (Mar 29 2023 at 03:06):

Yeah, that's why there's an error (when it decides to actually report it). The autoimplicit feature adds σ : ?R1 ->*+ ?R2 to the context, and then it tries to infer Module ?R1 M and Module ?R2 M', but it can't make any progress on these (and they definitely don't follow from Module R M or Module S M').

Arthur Paulino (Mar 29 2023 at 03:57):

Can we have this in core? :pray:


Last updated: Dec 20 2023 at 11:08 UTC