Zulip Chat Archive
Stream: general
Topic: rfc: tensor product notation
Johan Commelin (Sep 10 2021 at 18:37):
Tl;dr: I think the in will be used an order of magnitude more often than the one in . Hence I would like to swap the subscript ₜ
from the former to the latter.
Longer story:
I'm planning a refactor of tensor products. Roughly speaking, I want to use a characteristic predicate instead of the explicit construction. This will allow us to treat as , or to treat as , etc...
As part of this, I'm proposing a has_tmul
class, that will enable tensor product notation.
With this post, I want to ask whether people are happy with the following notation change.
Current situation:
-- tensor product of elements (terms)
x ⊗ₜ y
x ⊗ₜ[R] y
-- tensor product of modules (types)
M ⊗ N
M ⊗[R] N
My proposal:
-- tensor product of elements (terms)
x ⊗ y
x ⊗[R] y
-- tensor product of modules (types)
M ⊗ₜ N
M ⊗ₜ[R] N
I think that currently the subscript ₜ
stands for terms
, but it could just as well stand for types
(or tmul
or tensor
). So as a mnemonic, it doesn't matter too much where it sits.
The reason I would like to change this, is that if we switch to the characteristic predicate, we will be talking a lot about tensor products of terms , but not so much about the explicit construction of tensor products of modules. Instead, we will usually introduce an auxiliary module that satisfies the characteristic predicate, and hence is canonically isomorphic to .
Kevin Buzzard (Sep 10 2021 at 18:49):
Is it definitely not possible to overload the notation like we do in regular maths? (one works on types, one on terms...)
Mario Carneiro (Sep 10 2021 at 18:50):
those aren't exactly disjoint classes
Mario Carneiro (Sep 10 2021 at 18:50):
strictly speaking you could have a module whose elements are types
Kevin Buzzard (Sep 10 2021 at 18:51):
only in your crazed computer science theoretical model of how things might be
Kevin Buzzard (Sep 10 2021 at 18:51):
but I take your point
Mario Carneiro (Sep 10 2021 at 18:52):
The best you can say is that there are two functions and if you pick the wrong one a typeclass search will fail
Mario Carneiro (Sep 10 2021 at 18:52):
I don't know whether / to what extent typeclass search can be used for overload resolution
Kevin Buzzard (Sep 10 2021 at 18:52):
The way we dealt with |
vs \|
was to use two extremely similar unicode characters with different shortcuts. Can we pull this off here?
Mario Carneiro (Sep 10 2021 at 18:53):
sure, just smuggle a zero width space in somewhere
Kevin Buzzard (Sep 10 2021 at 18:54):
Basically the less it looks like normal maths, the less good it is, so in some sense this change is fine by me because it didn't look quite like normal maths before and it won't quite look like it afterwards, but if we could come up with a better idea where it looked like normal maths and people who are confused can get unconfused by hovering then this would be a solution which would be nicer as far as I'm concerned.
Kevin Buzzard (Sep 10 2021 at 18:55):
Is the zero width space suggestion a serious one? Can we make it so that \otimes
gives the type one and \otimest
gives the term one, for example?
Kevin Buzzard (Sep 10 2021 at 18:55):
wooah https://www.fileformat.info/info/unicode/char/26d2/index.htm
Mario Carneiro (Sep 10 2021 at 18:55):
I know it will be considered seriously by crazed mathematicians, I haven't decided how to feel about it yet
Kevin Buzzard (Sep 10 2021 at 18:55):
"road closed"
Mario Carneiro (Sep 10 2021 at 18:56):
lolol
Mario Carneiro (Sep 10 2021 at 18:56):
I'm pretty sure lean-liquid uses zero width spaces somewhere
Mario Carneiro (Sep 10 2021 at 18:56):
The zero-width space option (the unicode confusable option is similar) has the drawback that it is hostile to authors since they can't see the effect of a typo
Kevin Buzzard (Sep 10 2021 at 18:57):
wait there really are two unicode chars? https://www.fileformat.info/info/unicode/char/2a02/index.htm and https://www.fileformat.info/info/unicode/char/2297/index.htm ?
Kevin Buzzard (Sep 10 2021 at 18:58):
there's even https://www.fileformat.info/info/unicode/char/2b59/index.htm
Kevin Buzzard (Sep 10 2021 at 19:00):
The unicode confusable option is strictly better than the zero width space option, right? Because I can't make \otimest
produce \otimes
+ zero_width_space presumably?
Mario Carneiro (Sep 10 2021 at 19:00):
you can
Kevin Buzzard (Sep 10 2021 at 19:01):
For me this is no less hostile than the issues we have with |
vs \|
(which I see when doing number theory with undergrads asking me why 2 divides 4 doesn't typecheck)
Mario Carneiro (Sep 10 2021 at 19:02):
I am very conflicted about the idea of using symbols that are documented to cause confusion for related but different purposes
Mario Carneiro (Sep 10 2021 at 19:03):
You are right that |
vs \|
is the same sort of thing
Kyle Miller (Sep 10 2021 at 19:03):
I'll add another proposal:
-- tensor product of elements (terms)
x ⊗ y
x ⊗[R] y
-- tensor product of modules (types)
M ⊠ N
M ⊠[R] N
(I know ⊠
can have some other meaning, though, as the tensor product over the tensor product of rings.)
Kevin Buzzard (Sep 10 2021 at 19:04):
Isn't this worse than using a different \otimes? Because now this is actually wrong, that symbol is some sort of external tensor product thing which I've never properly understood.
Kyle Miller (Sep 10 2021 at 19:05):
I've seen it used to mean normal tensor product (occasionally), so I'm not sure there's a standard meaning.
Kevin Buzzard (Sep 10 2021 at 19:05):
https://ncatlab.org/nlab/show/external%20tensor%20product
Mario Carneiro (Sep 10 2021 at 19:06):
is there a circled comma? That would be great
Mario Carneiro (Sep 10 2021 at 19:07):
❟
anyone?
Kevin Buzzard (Sep 10 2021 at 19:07):
maybe we should add it to the proposal for the unicode guys together with those missing subscript letters
Mario Carneiro (Sep 10 2021 at 19:09):
I think a comma-like operator makes a lot more sense for the tensor product of elements than an \otimes
given the notational conventions elsewhere in lean
Kyle Miller (Sep 10 2021 at 19:10):
I wish there were a TRIANGLED TIMES to complement SQUARED TIMES, since it'd be a mnemonic that it's a tensor product with a diagonal action.
Kevin Buzzard (Sep 10 2021 at 19:13):
Could we use \Ox
for types and \ox
for terms? These are two of the characters I mentioned earlier. We have
/- This enables the notation `⨂[R] i : ι, s i` for the pi tensor product, given `s : ι → Type*`. -/
localized "notation `⨂[`:100 R `] ` binders `, ` r:(scoped:67 f, pi_tensor_product R f) := r"
in tensor_product
and does that stop us also using it for M ⨂[R] N
? Alternatively ⭙
is unused in mathlib and looks exactly the same as \ox
in my font unless you zoom in super-close
Yaël Dillies (Sep 10 2021 at 19:15):
I like ⛒ because it looks quite enough like the tensor product, but is also a bit different if you look close enough.
Kevin Buzzard (Sep 10 2021 at 19:15):
I agree that (a,b)
has type A \times B
but unfortunately mathematicians are just going to get confused by specialised notation which is unrecognisable to them. I think the Johan's original "switch the _t" idea is better than a comma thing, even though I do understand the logic -- I think we should aim for readability for mathematicians above all else
Kevin Buzzard (Sep 10 2021 at 19:16):
Is it OK to use road closed symbols for uses other than their intended purpose?
Mario Carneiro (Sep 10 2021 at 19:16):
I don't think we intend to close any roads in mathlib
Mario Carneiro (Sep 10 2021 at 19:16):
so it's probably fine
Mario Carneiro (Sep 10 2021 at 19:17):
I'm pretty sure we are abusing tons of unicode symbols already
Kyle Miller (Sep 10 2021 at 19:17):
Ok, one more proposal:
-- tensor product of elements (terms)
x ⊠ y
x ⊠[R] y
-- tensor product of modules (types)
M ⊗ N
M ⊗[R] N
The justification is that (I think) there's a sense in which the external tensor product of terms is the usual tensor product of terms. If M
is a module, you can think of it as a 0-category whose objects are the terms of M
, and the exterior tensor product of a term of M
and a term of N
is a term of the tensor product of these two 0-categories.
Kevin Buzzard (Sep 10 2021 at 19:18):
If Johan is correct then this would mean that the weird-to-mathematicians symbol would be the prevalent one, which is not ideal.
Kyle Miller (Sep 10 2021 at 19:28):
I think using similar-looking (or invisible) unicode characters as a design is a sketchy hack -- it's important to be able to look at some Lean code and know what it means. Otherwise, how can we know that we've proved the theorems we intended to prove without going through with an editor checking each characters' Unicode codepoints?
|
vs ∣
and ∑
vs Σ
are bad enough, and I'm not looking forward to having more of it...
Kyle Miller (Sep 10 2021 at 19:30):
(My biases: "a little notation is nice for algebraic reasoning, but I'm a fan of Lisp and Scheme.")
Kevin Buzzard (Sep 10 2021 at 19:42):
On the one hand we have the very remote but I guess pretty serious possibility that someone tensors two types together using term-tensor by accident and there happened to be a module structure on Type u
so it compiled and gave a super-super-hard to find bug or even worse a misleading result, and on the other hand we have the issue of making our theorem statements readable to mathematicians with no training.
Kyle Miller (Sep 10 2021 at 19:44):
It might be worth considering how any changes might interact with the monoidal product notation for monoidal categories: https://github.com/leanprover-community/mathlib/blob/6d2cbf9df602a9bd62cf82e7d8ed76b34f4b1e6e/src/category_theory/monoidal/category.lean#L127
Reid Barton (Sep 10 2021 at 21:04):
Yeah I'm not sure I would agree with the original claim. I think I'd say that in some contexts you exclusively use the tensor product of modules and in other contexts you mostly use the tensor product of elements.
Reid Barton (Sep 10 2021 at 21:04):
Unicode Character 'N-ARY CIRCLED TIMES OPERATOR' (U+2A02) should probably be used for the n-ary tensor product
Reid Barton (Sep 10 2021 at 21:06):
Nowadays it's become fashionable to write for the smash product of spectra, where there aren't really elements at all.
Reid Barton (Sep 10 2021 at 21:08):
By the way, don't forget about ꕕ U+A555 VAI SYLLABLE KPAN or ⛒ U+26D2 CIRCLED CROSSING LANES.
Eric Wieser (Sep 11 2021 at 00:02):
Yes, note we have docs#pi_tensor_product which uses the n-ary symbol
Johan Commelin (Sep 11 2021 at 04:11):
Reid Barton said:
Yeah I'm not sure I would agree with the original claim. I think I'd say that in some contexts you exclusively use the tensor product of modules and in other contexts you mostly use the tensor product of elements.
My goal with the refactor is that in an unbundled situation, you should almost never mention the explicit construction. But if you are working in some bundled setup where you have a monoidal category, sure, then you'll take tensor products of objects.
Do you think that makes sense? Or do you think that also in the unbundled situation, the construction should be used a good number of times, instead of some module satisfying the characteristic "predicate".
Kevin Buzzard (Sep 11 2021 at 08:52):
If you prove things for is_tensor_product
then you'll of course be able to deduce them for the concrete tensor product, and if schemes/localisation are anything to go by, there will be plenty of instances where mathematicians use a noncanonical tensor product (possibly without noticing) so I totally agree that you'll need it. Like you I feel like the terms will be more prevalent than the types, although actually of course the terms will be taking values now in the is_tensor_product
type now I guess, which might cause some confusion...
Scott Morrison (Sep 11 2021 at 22:30):
I would be pretty unhappy about any zero-width spaces in mathlib.
Scott Morrison (Sep 11 2021 at 22:31):
I would love to just use the same symbol in both situations, if Lean can cope. (In the monoidal category development, there seems to have been no problem using the same symbol for tensor products of objects and of morphisms.)
Scott Morrison (Sep 11 2021 at 22:33):
Much as I appreciate the existence of symbols from Vai, Canadian Syllabics, etc, I wouldn't like using near-indistinguishable symbols. Primes or subscripts are not terrible.
Mario Carneiro (Sep 11 2021 at 22:34):
One way to make the same symbol work would be a notation typeclass
Mario Carneiro (Sep 11 2021 at 22:56):
import linear_algebra.tensor_product
class {u} has_tensor {α β} (a : α) (b : β) (γ : out_param (Type u)) : Type u :=
(val : γ)
def tensor {α β} (a : α) (b : β) {γ : Type*} [has_tensor a b γ] : γ := has_tensor.val a b
infix ` ⊗ `:100 := tensor
universes u v
variables (R : Type u) [comm_semiring R] (M N : Type v)
[add_comm_monoid M] [add_comm_monoid N] [module R M] [module R N]
instance : has_tensor M N (Type v) := ⟨tensor_product R M N⟩
instance (x : M) (y : N) : has_tensor x y (M ⊗ N) := ⟨tensor_product.tmul R x y⟩
variables (x : M) (y : N)
#check M ⊗ N -- M ⊗ N : Type v
#check x ⊗ y -- x ⊗ y : M ⊗ N
Kevin Buzzard (Sep 11 2021 at 23:03):
Ooh
Kevin Buzzard (Sep 11 2021 at 23:05):
Would we also then be able to use x ⊗ y
as a term of type T
if is_tensor_product R M N T
?
Mario Carneiro (Sep 11 2021 at 23:13):
The limitation of this approach is in the decision for γ
to be an out_param or not. Either way there are going to be some pains because you can't use unification to infer R
, like you would if you are literally using tensor_product
or tensor_product.tmul
. If the output type is some generic T
, then it seems even harder to have it be an out_param, although it might work if there is something preventing the construction from coming up first
Mario Carneiro (Sep 11 2021 at 23:15):
Lean 4 would allow more flexibility to decouple the notation from the elaboration method and use domain specific tricks to distinguish the cases
Kevin Buzzard (Sep 11 2021 at 23:20):
I guess x ⊗[R] y
and M ⊗[R] N
would be acceptable to mathematicians
Mario Carneiro (Sep 11 2021 at 23:21):
Right now the [R]
is optional
Mario Carneiro (Sep 11 2021 at 23:21):
actually in the version I just posted there is no support for the R
Mario Carneiro (Sep 11 2021 at 23:22):
class is_tensor_product (T : Type*) :=
(e : tensor_product R M N ≃ T) -- or something
instance foo (T) [is_tensor_product R M N T] : has_tensor M N Type* := ⟨T⟩
instance bla (T) [is_tensor_product R M N T] (x : M) (y : N) : has_tensor x y T :=
⟨is_tensor_product.e.1 (tensor_product.tmul R x y)⟩
universe w
variables (T : Type w) [is_tensor_product R M N T]
#check M ⊗ N -- M ⊗ N : Type w
#check (rfl : M ⊗ N = T)
#check x ⊗ y -- x ⊗ y : T
Mario Carneiro (Sep 11 2021 at 23:23):
TBF I don't think this is a good idea
Johan Commelin (Sep 12 2021 at 00:42):
Interesting idea!
Johan Commelin (Sep 12 2021 at 00:43):
We certainly need support for [R]
. Because we want to be able to consider and . (Similarly for the termy versions.)
Eric Wieser (Sep 12 2021 at 06:49):
This seems similar to how we have A × B
vs (a, b)
. I've seen comments in the past saying that Haskell uses the same notation for both but it is confusing.
Eric Wieser (Sep 12 2021 at 06:55):
How about (a, b)ₗ[R]
since tensor_product
is like a linear version of prod
?
Johan Commelin (Sep 12 2021 at 06:59):
I think is better, because it has so much more resemblance with current usage in informal maths.
Eric Wieser (Sep 12 2021 at 07:03):
Here's a circled comma, @Mario Carneiro: ⃝,
Kevin Buzzard (Sep 12 2021 at 07:09):
We can't do commas. This is not acceptable. Mathematicians will find the code unreadable, their first question will be why we're not using the standard symbol, and any answer of the form "we can't" will be met with a response of "ok I'll come back when you've figured it out"
Kevin Buzzard (Sep 12 2021 at 07:10):
One reason lean caught on in the maths community is its liberal use of the correct unicode symbols for many things
Kevin Buzzard (Sep 12 2021 at 07:11):
My impression is that the CS people really can't see what the fuss is about here but to mathematicians it seems to make a huge difference
Eric Wieser (Sep 12 2021 at 07:17):
Would mathematicians prefer a non-comma symbol for (a, b) : A × B
too?
Kevin Buzzard (Sep 12 2021 at 07:17):
No, we use commas for that
Kevin Buzzard (Sep 12 2021 at 07:17):
What you write there is perfect
Eric Wieser (Sep 12 2021 at 07:18):
Ah, I'm misremembering, it's A × B
that I've seen often written A ⊕ B
in maths, not (a, b)
. (See the Wikipedia page on direct sums for instance)
Johan Commelin (Sep 12 2021 at 07:23):
Sure, and are used a lot, and quite often they are interchangeable.
Eric Wieser (Sep 12 2021 at 07:27):
Which is a shame because A ⊕ B
is very different in Lean
Kevin Buzzard (Sep 12 2021 at 07:28):
Yes, and I'm sure you can guess which one I'd like to nuke
Kevin Buzzard (Sep 12 2021 at 07:29):
We have A ⨿ B
for that
Eric Wieser (Sep 12 2021 at 07:36):
I hope you mean A ⊔ B
Kevin Buzzard (Sep 12 2021 at 07:37):
Sure, they look the same to me
Kevin Buzzard (Sep 12 2021 at 07:37):
With my mathematician's glasses on
Eric Wieser (Sep 12 2021 at 07:38):
I guess mathlib lost its "intended semantics of unicode characters" glasses long ago...
Kevin Buzzard (Sep 12 2021 at 10:15):
In human maths papers in this particular case I'm pretty sure that nobody would be particularly fussed about which disjoint union character to use, it's actually surprisingly rare as a construction (at least in number theory)
Kyle Miller (Sep 12 2021 at 16:03):
Eric Wieser said:
This seems similar to how we have
A × B
vs(a, b)
. I've seen comments in the past saying that Haskell uses the same notation for both but it is confusing.
(Haskell does the same with [A]
for a list of things of type A
.)
I guess it's not so hard to get Lean to have this same notation for cartesian products:
instance pair_to_cart : has_coe_to_sort (Type u × Type v) := ⟨_, λ p, p.1 × p.2⟩
example : (ℕ, ℕ) := (1, 2)
def swap {α β : Type*} (p : (α, β)) : (β, α) := (p.2, p.1)
Could this be a way to support for terms and types? Have a coercion from the term tensor product of types to the tensor product?
Mario Carneiro (Sep 12 2021 at 16:38):
Note that haskell has the luxury of being able to do that because terms and types are different syntactic classes. This doesn't work in dependent type theories because they are completely different operators that both validly apply to types
Kyle Miller (Sep 12 2021 at 16:48):
That just means Haskell has the luxury of having (ℕ, ℕ)
immediately be a type, rather than needing an additional rule for when such a term is used as a type. I think it's similar to how in Automath pi types are represented by lambda expressions, though that rule is built-in rather than needing a Lean-style coercion.
(It's unclear how you'd make [A]
be the type of lists, but I just brought it up to illustrate that they like this sort of notation in Haskell.)
Mario Carneiro (Sep 12 2021 at 16:51):
Well in DTT the product type constructor is not necessarily injective, so making them the same is at least an additional axiomatic commitment
Mario Carneiro (Sep 12 2021 at 16:51):
and as you say this doesn't work at all for lists
David Wärn (Sep 12 2021 at 16:54):
def list_to_type : list Type → Type
| [] := fin 37
| [A] := list A
| (A::B::_) := fin 37
instance : has_coe_to_sort (list Type) := ⟨_, list_to_type⟩
example : list ℕ = [ℕ] := rfl
Mario Carneiro (Sep 12 2021 at 16:55):
Clearly the other lists should be tuple types ;)
Kyle Miller (Sep 12 2021 at 16:56):
Mario Carneiro said:
and as you say this doesn't work at all for lists
I regret bringing up lists, since it has nothing to do with what I was suggesting. (Though thanks for finding a solution to this puzzle, @David Wärn.)
I find it puzzling that you're saying it doesn't work when I gave some working code. Why does it matter if the product type constructor is injective? There are obviously some problems with needing coercions, but it seems to be significantly better than relying on CIRCLED CROSSING LANES or VAI SYLLABLE KPAN.
Mario Carneiro (Sep 12 2021 at 16:57):
If there is a coercion, then I can see some more possibilities; I was talking about the case where there is no coercion and the two constructors are identified
Last updated: Dec 20 2023 at 11:08 UTC