I'm not a fan of `Tensor[T, ...]` because it has confusing semantics.
Tensors will usually be typed as:
```python
class Tensor(Generic[DType, *Shape]): ...
```
where `Tensor[np.float64, Literal[10], Literal[20]]` represents a 10x20
Tensor where each element has datatype `np.float64`. Let's say we want to
represent a Tensor that has arbitrary shape.
+ `Tensor[np.float64, ...]` looks like it represents a Tensor of datatype
np.float64 and arbitrary shape. But by analogy with the similar
`Tuple[float, ...]`, it would have to represent any Tensor where all the
*dimensions* are `np.float64`: `Tensor[np.float64, np.float64,
np.float64]`, etc. That's not what we would expect for a Tensor.
+ To counter that, we might change the semantics of `Tensor[T, ...]`, to
mean datatype T with arbitrary shape (i.e., `Tensor[T, Any, Any, Any]`,
etc.), but that will be ambiguous for a class that has multiple unary
generics like:
```
class Transformer(Generic[T_in, T_out, *Shape]): ...
# Is `T_out` int or Any?
x: Transformer[int, ...]
```
New syntax like Transformer[int, str, ...] seems even more confusing.
+ The only remaining use afaik would be `Tensor[Any, ...]` to represent a
Tensor where all parameters are Any. Given that `x: Tensor` already
represents this, it doesn't feel worth adding fresh syntax to express the
same.
In contrast, `Tensor[np.float64, *Tuple[Any, ...]]` expresses the fact that
the datatype is `np.float64` but the shape can be anything. `Transformer[A,
B, *Tuple[Any, ...]]` works for the other case. We can also state that the
dimension types have to be int: `Tensor[np.float64, *Tuple[int, ...]]` to
represent `Tensor[np.float64, int, int, int]`, etc.
I completely agree that the syntax is verbose and frankly not very pretty
:) (TypeScript has a nicer `Tensor[float, ...any[]]` syntax.) That seems
fine given that we don't really want to encourage this.
Overall, I see two options:
+ No explicit syntax for unbounded Tensors: We just have `x: Tensor` to
support gradual typing as of PEP 646 and we can add unbounded Tensors in
follow-up PEPs. Typecheckers would be free to treat `Float32Array =
Array[np.float32, *Shape]; x: Float32Array` as `x: Array`, thereby making
all parameters `Any`. This seems like the simplest option right now.
+ Explicit syntax where we substitute `Tuple[Any, ...]` for `Ts`: This
would complicate an already heavy PEP, but would allow us to precisely
express the fact that the shape can be anything.
On Sun, Feb 21, 2021 at 8:28 AM Eric Traut
Hmm, I'm not a fan of `Tensor[*Tuple[Any, ...]`. That's really verbose and inconsistent with existing standards. And it would require all type checkers to add support for open-ended non-homogenous tyes, which would be a heavy lift. Let's save that for another future PEP.
I was proposing that we simply extend the PEP 484 tensor convention to all variadic generic types. So this would be `Tensor[Any, ...]`.
-- Eric Traut Contributor to Pyright & Pylance Microsoft Corp. _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ Member address: gohanpra@gmail.com
-- S Pradeep Kumar