Zulip Chat Archive
Stream: mathlib4
Topic: Typeclasses for linear maps
Moritz Doll (Jan 19 2026 at 04:14):
I have a rather annoying problem with the typeclass system, which I have a hard time finding a solution for: we have a typeclass for special functions (the Fourier transform, directional derivatives) that are linear (on bundled functions). So the current design is to have a basic class just for the notation (for example docs#FourierTransform), and then one for addition and one for scalar multiplication. In principle that should be enough, but then you end up with the problem that you can't have a general simp lemma for negation or finite sums, because you have to choose a scalar field (and simp doesn't want to do that). The obvious solutions would be to introduce more parameters in the add class to prove all of the additional lemmas in that class, but it involves proving more lemmas that are a bit silly, the other option would be to have a class with addition and smul for a fixed field (probably the reals), but that seems rather clunky. Is there any better solution? I feel like this should have come up somewhere else before.
Martin Dvoลรกk (Jan 19 2026 at 09:44):
I don't understand what you say. Linear map is a structure, not a class. Are you suggesting it should be a class?
Moritz Doll (Jan 19 2026 at 10:05):
No, I am using classes for specific linear maps. The class FourierTransform E F says that there is a map E โ F called the Fourier transform (whatever that is) and we have notation ๐ f for f : E. Then there are additional type classes that state algebraic properties of ๐, which amount to it being a continuous linear map. These additional type classes are a bit of a pain.
Jireh Loreaux (Jan 19 2026 at 21:51):
Moritz Doll said:
you can't have a general
simplemma for negation or finite sums, because you have to choose a scalar field
This doesn't make sense to me. Can you show me the problem?
Moritz Doll (Jan 19 2026 at 23:20):
docs#FourierTransform.fourier_zero shows the problem: the theorem needs a ring, but obviously the ring does not play a role.
Kevin Buzzard (Jan 19 2026 at 23:29):
Can you make FourierTransform E F an instance of docs#ZeroHomClass ?
Moritz Doll (Jan 19 2026 at 23:48):
I don't know how that could work since FourierTransform E F is a class and FourierTransform.fourier is a function, not a type. I guess I would have to wrap it in a set type or something?
Kevin Buzzard (Jan 20 2026 at 00:03):
Hmm yes it doesn't quite fit does it :-/
Edward van de Meent (Jan 20 2026 at 00:10):
i guess this just suggests we need a FourierZero class (and FourierInvZero class)? or is this a silly suggestion?
Edward van de Meent (Jan 20 2026 at 00:11):
at the very least this would seem to be the way the current design around FourierTransform suggests to fix this issue...
Moritz Doll (Jan 20 2026 at 00:17):
Yeah, this would be a solution, but it feels like a lot of overhead when in the end you construct the Fourier transform as a (continuous) linear map or linear isometry. Especially, since it would end up declaring a lot of instances in each applications. I would love to have a solution with less boilerplate in each application.
Jireh Loreaux (Jan 20 2026 at 13:50):
@Moritz Doll why do you need the Semi veresions of everything in FourierTransform.fourier_zero? Are you ever working in settings where E or F is not and AddGroup? If not, then just switch to that and then:
import Mathlib.Analysis.Fourier.Notation
variable {E F : Type*} [AddGroup E] [AddGroup F] [FourierTransform E F] [FourierAdd E F]
open scoped FourierTransform
@[simp]
lemma fourier_zero : ๐ (0 : E) = 0 := by
apply add_left_cancel (a := ๐ (0 : E))
simp [โ FourierAdd.fourier_add]
@[simp]
lemma fourier_neg (x : E) : ๐ (-x) = -(๐ x) := by
apply add_left_cancel (a := ๐ x)
simp [โ FourierAdd.fourier_add]
Jireh Loreaux (Jan 20 2026 at 13:55):
I mean, really this is just saying that an AddHom between additive groups is an AddMonoidHom.
Jireh Loreaux (Jan 20 2026 at 14:12):
I've been wondering whether we should go back to having an IsAddMonoidHom type class that takes an individual morphism, but that we hardly ever / never instantiate it globally, except for โ f : F, IsAddMonoidHom f, where AddMonoidHomClass F _ _. But the point would be that we can have local or scoped instances like IsAddMonoidHom ๐ฃ.
Moritz Doll (Jan 20 2026 at 21:53):
Do we have the upgrade from AddHom to AddMonoidHom? That would be enough to have all of the lemmas as term one-liners, which I think is good enough for the moment.
Moritz Doll (Jan 20 2026 at 22:03):
Alternatively, we could add
import Mathlib.Algebra.Group.Hom.Defs
variable {G H F : Type*}
[FunLike F G H] [AddGroup G] [AddGroup H] [AddHomClass F G H] (f : F) (a : G)
@[simp]
theorem map_zero' (f : F) (a : G) : f 0 = 0 := by
apply add_left_cancel (a := f (a : G))
simp [โ map_add]
@[simp]
theorem map_neg' (f : F) (a : G) : f (-a) = -f a := by
apply add_left_cancel (a := f (a : G))
simp [โ map_add, map_zero' f a]
Moritz Doll (Jan 22 2026 at 02:33):
@Jireh Loreaux do you have a preference here? (just adding a few lemmas vs a definition for upgrading an AddHom to an AddMonoidHom?)
Moritz Doll (Jan 22 2026 at 22:50):
Eric Wieser (Jan 23 2026 at 00:03):
Moritz Doll (Jan 23 2026 at 00:08):
Perfect - that makes the PR obsolete :tada:
Jireh Loreaux (Jan 24 2026 at 03:06):
Sure, with Lean Together going on I missed this.
Moritz Doll (Jan 24 2026 at 22:19):
No worries. Also thank you (and of course also Patrick, Markus and Remy) so much for organizing the meeting
Last updated: Feb 28 2026 at 14:05 UTC