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 <eric@traut.com> wrote:
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