Zulip Chat Archive
Stream: Is there code for X?
Topic: Base change for modules over an algebra
Stepan Nesterov (Dec 16 2025 at 02:08):
If is a -algebra, and is an -module, I would like to consider, for a -algebra , the -module as a module via $(\lambda \otimes a) (\mu \otimes m) = \lambda \mu \otimes a m$. Is there an easy way to do this?
import mathlib
open scoped TensorProduct
variable (k A M : Type*) [CommRing k] [Ring A] [Algebra k A] [AddCommMonoid M]
[Module A M] [Module k M] [IsScalarTower k A M]
variable (k' : Type*) [CommRing k'] [Algebra k k']
#synth Module (k' ⊗[k] A) (k' ⊗[k] M) -- fails
Kevin Buzzard (Dec 16 2025 at 06:02):
(typo -algebra )
Kevin Buzzard (Dec 16 2025 at 06:11):
Do we already have an -action on ? If so then you're in trouble with the mathlib diamond mafia because is allowed in your setup. Conversely if we don't then your construction will make it never to be allowed if yours makes it into mathlib. This sort of nonsense needs a robust solution because it's blocking progress.
Kevin Buzzard (Dec 16 2025 at 06:15):
In FLT I've been taking the opposite approach and just making actions when I need them and disabling them otherwise and this has simultaneously enabled me to prove theorems and confuse other users
Andrew Yang (Dec 16 2025 at 07:21):
docs#TensorProduct.Algebra.module should be useful here.
Kevin Buzzard (Dec 16 2025 at 08:45):
Well yes if you want to define it locally, but not if you want this in mathlib, because given an -action on , mathlib will not allow an -action on because what if as well?
It's these objections which I think are creating a barrier to growth in algebra which I think is becoming more and more unsustainable. I found it impossible to stick to Mathlib's rules about what can and can't be made an instance when I wanted to develop enough theory to write down the isomorphism in a way which is both -linear and -linear and also a topological isomorphism for the -module topologies, which is why I just gave up in FLT and allowed instances which would not be allowed in mathlib; it didn't matter because we put them in a scope, ultimately things compiled, we used them to deduce finiteness results and then you can use the finiteness results without opening the scope (the entire theory was developed just so I could prove results about by reducing them to results about where explicit computations were much easier; we then turn the instances off again). I know it's a hack but I don't know of a mathlib-certified way to proceed with these kinds of questions.
Kevin Buzzard (Dec 16 2025 at 08:51):
@Stepan Nesterov the answer to your question is "is there an easy way to do this" is "it depends on where your work is going". If you are just making it locally, then make the instance if it's not there using Andrew's hint. If you want it in FLT then it's a bit easier: just import FLT.Hacks.RightActionInstances and open scoped TensorProduct.RightActions to get the action of on and then use Andrew's suggestion. If you want to get it into mathlib then you either have to battle the diamond mafia, solve a hard problem (analogous to https://github.com/leanprover-community/mathlib4/issues/7152) or do something completely different like e.g. making a new kind of action map or something (again probably not feasible without solving a hard problem) or completely rethinking how actions work in mathlib. I am very unclear about how to proceed.
Kevin Buzzard (Dec 16 2025 at 09:06):
I think one way of making progress is asking the simplest form of the question. If is a commutative -algebra then admits two natural left actions of and they are different. We cannot close our eyes to the fact that mathematicians want both (and want to talk about maps which are linear wrt to one or the other of the actions etc). In a paper where both are used, different notations would be used. But we only have one way of saying "X acts on Y". What do we do? A type synonym def ActingOnTheRightOfTensorProducts (R : Type*) [CommRing R] := R?
Sébastien Gouëzel (Dec 16 2025 at 09:29):
You can have two different scopes with the two different actions, none of them active by default. I think that in general it's the right thing to do for instances that could create diamonds like the other one you mention above: have them only in scopes, and activate them locally when it's useful.
Kevin Buzzard (Dec 16 2025 at 09:31):
Well is already a -algebra in mathlib in no scope, it's docs#Algebra.TensorProduct.leftAlgebra
Artie Khovanov (Dec 16 2025 at 10:28):
(Thinking out loud)
To robustly solve the problem Kevin is describing of having too many actions, we need some way of having multiple smul instances without them clashing. Perhaps we could dynamically register a list of syntactically distinct smuls? Like, copy the way it's done in informal maths and allow defining "clashing" smul instances with different notation but the same API (within a scope). Then we can write common instances of this pattern (eg tensor product) in more generic scopes. So we would end up with •ₗ and •ᵣ available and it would all elaborate/deliberate nicely to/from the more generic smul instances. I do not know how technically difficult this would be to do.
Aaron Liu (Dec 16 2025 at 11:04):
Kevin Buzzard said:
I think one way of making progress is asking the simplest form of the question. If is a commutative -algebra then admits two natural left actions of and they are different.
Objection: one of them is a right action
Michael Stoll (Dec 16 2025 at 11:42):
This reminds me of (see also , where it turned out that some diamonds are more equal than others...)
Kevin Buzzard (Dec 16 2025 at 14:35):
Aaron Liu said:
Kevin Buzzard said:
I think one way of making progress is asking the simplest form of the question. If is a commutative -algebra then admits two natural left actions of and they are different.
Objection: one of them is a right action
No good. I definitely want to allow linear maps where is a left -module and has the right action of . Why? Because if we can't do arbitrary things then mathematicians are going to say "it's broken". And what about etc?
I do not believe that we can just attempt to solve this general problem by left actions by R^{op} or right actions. I like the idea of scoping all decisions and seeing how far this gets us; the problem is that a lot of our actions are not in a scope.
Stepan Nesterov (Dec 16 2025 at 16:14):
Kevin Buzzard said:
Stepan Nesterov the answer to your question is "is there an easy way to do this" is "it depends on where your work is going". If you are just making it locally, then make the instance if it's not there using Andrew's hint. If you want it in FLT then it's a bit easier: just
import FLT.Hacks.RightActionInstancesandopen scoped TensorProduct.RightActionsto get the action of on and then use Andrew's suggestion. If you want to get it into mathlib then you either have to battle the diamond mafia, solve a hard problem (analogous to https://github.com/leanprover-community/mathlib4/issues/7152) or do something completely different like e.g. making a new kind of action map or something (again probably not feasible without solving a hard problem) or completely rethinking how actions work in mathlib. I am very unclear about how to proceed.
What I wanted to do is to prove that an absolutely irreducible representation of an abelian group is 1-dimensional. Then I thought then the right generality for this is you take a commutative k-algebra A, and say that an absolutely simple module (not sure if this is the standard terminology) is 1-dimensional. But then I ran into an issue that I don't know how to define this action of a base changed algebra on a base changed module.
Kevin Buzzard (Dec 16 2025 at 16:16):
Just do the base change on the other side?
Stepan Nesterov (Dec 16 2025 at 16:17):
Like this?
import mathlib
open scoped TensorProduct
variable {k A M : Type*} [CommRing k] [Ring A] [Algebra k A] [AddCommMonoid M]
[Module A M] [Module k M] [IsScalarTower k A M]
variable {k' : Type*} [CommRing k'] [Algebra k k']
#synth Module (A ⊗[k] k') (M ⊗[k] k')
It still fails
Stepan Nesterov (Dec 16 2025 at 16:21):
But it's true that we do need this result (absolutely irreducible representation of an abelian group is 1-dimensional) in FLT, for example, for proving the main theorem in ModThree.lean. If someone were to try and PR this result into FLT, would you prefer that they do the 'module over the commutative algebra' version, which we don't need for FLT but it's morally correct, or just the group version?
Stepan Nesterov (Dec 16 2025 at 16:22):
Or if mathlib doesn't have a way of base changing modules, does it mean that I should just PR the group version in mathlib, and not worry about the generalization?
Andrew Yang (Dec 16 2025 at 16:28):
You could also do Module (A ⊗[k] k') ((A ⊗[k] k') ⊗[A] M) if you want to delay the problem to later but again I don't think it is unreasonable to add this as a local instance to mathlib via docs#TensorProduct.Algebra.module
Kevin Buzzard (Dec 16 2025 at 16:29):
It causes a diamond if right? (even if it's this way around)
Andrew Yang (Dec 16 2025 at 16:30):
Module (A ⊗[k] k') ((A ⊗[k] k') ⊗[A] M) should be unambiguous.
But Module (A ⊗[k] k') (M ⊗[k] k') indeed clashes with other instances so it should be scoped/local.
Kevin Buzzard (Dec 16 2025 at 16:47):
I feel like we have a big problem to solve here but for FLT if you can get away with the group version then that'll do for now!
Aaron Liu (Dec 16 2025 at 20:09):
Kevin Buzzard said:
I definitely want to allow linear maps where is a left -module and has the right action of . Why? Because if we can't do arbitrary things then mathematicians are going to say "it's broken".
We also don't have a way to directly do a group homomorphism from a multiplicative group to an additive group, you have to make the multiplicative group additive or make the additive group multiplicative. I think we can try a similar thing.
Aaron Liu (Dec 16 2025 at 20:16):
Kevin Buzzard said:
And what about etc?
What about it?
Kevin Buzzard (Dec 16 2025 at 21:51):
Aaron Liu said:
I think we can try a similar thing.
Kevin Buzzard said:
def ActingOnTheRightOfTensorProducts (R : Type*) [CommRing R] := R?
:point_up: ?
Aaron Liu (Dec 16 2025 at 21:53):
no, I mean add a thing that swaps the left and right actions in general
Aaron Liu (Dec 16 2025 at 21:53):
not just specifically for tensor products
Aaron Liu (Dec 16 2025 at 21:54):
but I guess if you only need it on tensor products for now then that's fine too
Antoine Chambert-Loir (Dec 17 2025 at 07:45):
Note that one might genuinely wish to compare actions of the same object A on the same object B. The proof of the Skolem-Noether theorem works like this.
Eric Wieser (Dec 17 2025 at 21:31):
I don't think in those cases it is important that the objects are type-theoretically the same: you can always compare how fooAct A acts on B with how A acts on B, especially when fooAct is an isomorphism to a type synonym
Eric Wieser (Dec 17 2025 at 21:32):
With the scoping approach you can also write something like (open scoped Act1 in A • B) = (open scoped Act2 in A • B)
Eric Wieser (Dec 17 2025 at 21:33):
Note that scopes only go so far; when it comes to inheriting actions, scopes are like saying "you can follow every edge of this color in my graph", not "you must follow this precise path"
Kevin Buzzard (Dec 17 2025 at 21:51):
The elephant in the room here is that there is already an action of on and it's not in a scope.
Andrew Yang (Dec 17 2025 at 22:06):
I don't think this is solvable at all (nor do I really think this is an issue). You already need to choose how acts on , via or , which are not defeq. By choosing one you also choose which action on should be.
Kevin Buzzard (Dec 17 2025 at 22:12):
Sure, but one could scope both choices rather than forcing everyone to have to deal with (or sometimes avoid) one of them.
Andrew Yang (Dec 17 2025 at 22:14):
Are you proposing that should not be an -module globally?
Stepan Nesterov (Dec 17 2025 at 22:18):
Kevin Buzzard said:
The elephant in the room here is that there is already an action of on and it's not in a scope.
For commutative or in general?
Stepan Nesterov (Dec 17 2025 at 22:18):
If for general , then I would agree that this seems undesirable
Eric Wieser (Dec 17 2025 at 22:26):
The extreme outcome here is also that is not an -module globally
Stepan Nesterov (Dec 17 2025 at 22:29):
Is is possible to create a situation, where, e.g. is not an -module golbally, but something like is an -module globally? So you can talk about as an -module, but you'd have to write like a few extra symbols.
Eric Wieser said:
The extreme outcome here is also that is not an -module globally
Stepan Nesterov (Dec 17 2025 at 22:32):
Or in my original situation, can you create a separate notation like M.BaseChange k' which is defeq to the tensor product, and then have M.BaseChange k' be an A.BaseChange k'-module, but not have all the other instances for this particular notation? Or does Lean see through defeqs?
Andrew Yang (Dec 17 2025 at 22:33):
I still don't understand why can't you just make the instance and turn it on locally.
Stepan Nesterov (Dec 17 2025 at 22:38):
Because as far as I understood, Kevin thinks it's not mathlib-approved (?)
Stepan Nesterov (Dec 17 2025 at 22:39):
It's possible I am misinterpreting how serious this all is
Stepan Nesterov (Dec 17 2025 at 22:41):
Well and also there's way too much 'failed to synthesize errors' when I try to just apply TensorProduct.Algebra.module and maybe it's all fixable with some hacks from the FLT project but I gave up after a few tries
Andrew Yang (Dec 17 2025 at 22:46):
Something like
open TensorProduct
abbrev baseChangeModule : Module (k' ⊗[k] A) (k' ⊗[k] M) :=
let : Module A (k' ⊗[k] M) := (TensorProduct.comm _ _ _).toAddEquiv.module _
have : IsScalarTower k A (k' ⊗[k] M) := .of_algebraMap_smul fun _ x ↦ by
induction x <;> simp_all [this, ← tmul_smul, ← @IsScalarTower.algebraMap_smul k A M,
-algebraMap_smul]; rfl
have : SMulCommClass k' A (k' ⊗[k] M) :=
⟨fun _ _ x ↦ by induction x; exacts [by simp, rfl, by simp_all]⟩
TensorProduct.Algebra.module
attribute [local instance] baseChangeModule
But those lets and haves should be their own scoped instances, generalizing what Kevin has in the hacks file.
Aaron Liu (Dec 17 2025 at 22:51):
Andrew Yang said:
Are you proposing that should not be an -module globally?
I don't see how is always an R-module, unless one of M or N is an R-bimodule, which happens for example when R is commutative.
Andrew Yang (Dec 17 2025 at 22:53):
in this context means that is commutative because of how docs#TensorProduct is defined. If you need tensor products over non-commutative rings this is another can of worms which is tangential to this discussion.
Andrew Yang (Dec 17 2025 at 23:08):
I think the only thing in this thread that cannot be solved with scoped instances is when you want to be an -algebras in two ways at once, e.g. when you want to talk about the -linear map (where the act on different sides on the two tensor products).
The only way to do this is that I am aware of is to use @SemilinearMap and fill in the instances manually, which is very bad.
Aaron Liu (Dec 17 2025 at 23:10):
Andrew Yang said:
If you need tensor products over non-commutative rings this is another can of worms which is tangential to this discussion.
I feel like distinguishing the left and right actions would solve many problems here though...
Andrew Yang (Dec 17 2025 at 23:11):
I feel like there are lots of problems you need to solve first before you get to solve the problems listed here.
Andrew Yang (Dec 17 2025 at 23:22):
And in the end you don't get two algebra instances of on ; you get none.
Aaron Liu (Dec 17 2025 at 23:33):
you at least get two A-modules I think
Aaron Liu (Dec 17 2025 at 23:34):
so you can talk about left- and right- A-linear maps
Kevin Buzzard (Dec 17 2025 at 23:43):
Yes, the point is that is an -module (and an -algebra) in two different ways, and right now one of them is being forced on us, and I'm saying that this is quite inconvenient when you want the other one.
Andrew Yang (Dec 17 2025 at 23:54):
Do you want "the other one" or do you want both of them at once?
For the former, does attribute [local instance] TensorProduct.rightAlgebra solve the problem?
For the latter I have no solution and perhaps this is a fundamental limitation of typeclasses?
You can introduce typeclass synonyms that partially solves the problem (e.g. if you can allow "different" then you do a typeclass synonym on tensor product that always does right action; if you can allow "different" acting on the same tensor product then you could do def Copy := R and work with A ⊗ Copy A), but nothing satisfactory.
Kevin Buzzard (Dec 18 2025 at 01:05):
It's not really what I want -- it's what it would not be unreasonable for a mathematician to want, in general. Obviously it's becoming clear that there are these random reasons why one can't have certain instances because of some exotic special case causing a diamond, and I think that this might become complicated to deal with in the future. Observations like Eric's "Oh SMul X Y -> SMul (F X) (F Y) is a bad idea" might be some theoretically true statement about how mathlib has got algebra set up, but this has concrete consequences such as "if K and L are number fields and L is a K-algebra then is not allowed to be an -algebra in mathlib unless you switch it on locally and then be super-wary about the case K=L because it will cause time-outs". Similarly here we're basically saying that is only allowed to be an -algebra in one way and whilst we've worked around this so far, this is not something which a mathematician is going to expect to be hearing.
Kevin Buzzard (Dec 18 2025 at 01:08):
But to get back to the point, the answer to Stepan's question is "yes you can make this module instance (thanks Andrew for doing it), there might be technical reasons why it's not allowed to be a global instance but if you just switch it on locally and cross your fingers you'll probably be OK".
Kevin Buzzard (Dec 18 2025 at 01:10):
I'll remark that allowing to be an -module if is an -module has not caused me any problems yet; what has caused me problems is being an -algebra and also letting be a -algebra because then you get two -actions on . So there are some design patterns I'm learning to avoid and perhaps this is how things will go in the future; you carefully switch things on and hope for the best.
Stepan Nesterov (Dec 18 2025 at 04:15):
Can you do something like bundled modules in mathlib? Like saying “Let WithRightAction A be an A-module with carrier A otimes A and action on the right” without making an instance?
Yaël Dillies (Dec 18 2025 at 05:28):
Kevin Buzzard said:
what has caused me problems is being an -algebra and also letting be a -algebra because then you get two -actions on .
I thought I had solved this specific problem?
Yaël Dillies (Dec 18 2025 at 05:30):
IIRC it was due to there being a special -algebra instance on on top of the generic -algebra instance on for a -algebra.
Yaël Dillies (Dec 18 2025 at 05:31):
... but your description of the situation doesn't contain the first instance, so either your description is wrong or it is incomplete or the problem does not exist anymore.
Yaël Dillies (Dec 18 2025 at 05:36):
I will remark that the main alternative to typeclasses that we know of is locales, ans turning on and off instances is more or less what a locale is. The two differences I can see are
- It's possible (and easy!) to turn on and off a locale for specific types, while instances can only be turned on and off for all types at once (unless you redeclare them one by one for the specific types you want them to be on on, which is NOT easy).
- It's possible to change the notation of a locale to use two conflicting locales on the same type. Meanwhile, conflicting instances are a no-go, except in a few places like measure theory where we have spent a lot of time making the API usable for non-canonical instances.
Yaël Dillies (Dec 18 2025 at 05:40):
I personally believe that locales are a more accurate representation of mathematician thinking than typeclasses, and this thread is screaming "Please someone implement locales in Lean" to me. I foresee a few issues though:
- Although locales have been successfully used in other libraries, such as Isabelle/HOL, said libraries are nowhere close to where mathlib is in terms of eg commutative algebra, and therefore it is unclear whether the success of locales will continue when the harder parts of commutative algebra are reached.
- The typeclass system is unlikely to change again in Lean.
Yaël Dillies (Dec 18 2025 at 05:42):
To me, this means a potential implementation of locales would need to be a lightweight system over the existing instance system, and would need to first be tried out in the advanced commutative algebra projects like FLT.
Yaël Dillies (Dec 18 2025 at 05:46):
A potential implementation I envision is the combination of:
- an attribute putting instances in a locale
- a tactic to turn on the instances tagged with a locale's attribute on a given type locally to a proof
- a command to turn on the instances tagged with a locale's attribute on a given type locally to a file
Yaël Dillies (Dec 18 2025 at 05:47):
Note that open scoped fits the bill, except for the "on a given type" constraint
Yaël Dillies (Dec 18 2025 at 05:51):
I would love to be involved in implementing such a design, because I have Thoughts, but I am too busy to do it by myself.
Last updated: Dec 20 2025 at 21:32 UTC