@Alfonso: That seems like an interesting and feasible idea! Overall, I'd like to defer this for now since it would be fully backward-compatible. It probably belongs in the future type arithmetic PEP. We could use the `Length` operator from type arithmetic, where Length[Ts] resolves to a Literal. For example, if Ts = `Tuple[int, str]`, `Length[Ts] == Literal[2]`. Concrete example (translating your doc example to the PEP syntax): ```python def mean(t: Tensor[*Ts, T, *Ts2], dim: Length[Ts]) -> Tensor[*Ts, *Ts2]: ... L = Literal t: Tensor[L[3], L[4], L[5]] mean(t, dim=1) # => Tensor[L[3], L[5]] ``` We could also look at alternative syntax in the future, but would like to punt on this for now. @Matthew:
At the moment I'm leaning towards not allowing it - unless anyone has any suggestions of a concrete use case for `class C(Generic[*Ts1, *Ts2])`?
Yeah, I strongly prefer forbidding such a syntax since an explicit declaration `C[int, str]` is inherently ambiguous.
One significant change I've (tentatively) made is renaming `Expand` to `Unpack`, to reflect the terminology we use with regular tuples. I'm surprised no one else has suggested this, so I might be missing something - are there any arguments against calling what we're doing 'unpacking'?
I think that's reasonable. On Tue, Dec 29, 2020 at 7:26 AM Matthew Rahtz via Typing-sig < typing-sig@python.org> wrote:
I suggest allowing a concatenated type (Tuple[*Ts, *Ts2]) when the *length* of at least one is unambiguously implied by other arguments.
I think that's reasonable, if no one has any objections on the grounds that we make things too hard for static checkers. I've tentatively reworked the section in question to reflect this.
Regarding concatenation on classes, I do think there's a way to add extra contexts via method calls:
Oh, huh, interesting. But not being able to actually write down unambiguously exact what type it is seems like a major downside. Having to consult the constructor arguments to figure out the type also seems really complicated. At the moment I'm leaning towards not allowing it - unless anyone has any suggestions of a concrete use case for `class C(Generic[*Ts1, *Ts2])`?
The idea does not need any sort of dependent typing, just to take advantage of literal types.
Oh, super cool! Looking forward to seeing more of this :)
However, I might have missed something but: where is specified the constraints that a variadic can have (variance, bound...)?
Ah, yeah - variance and bound are currently not supported. I think figuring out how they should work is going to be tricky, so best left for a future PEP, once we have more experience with using variadic generics in practice. I've added a short section stating this explicitly.
And the subtyping rules for variadics?
Do you mean something like this?
```python DType = TypeVar('DType') Shape = TypeVarTuple('Shape')
class Array(Generic[DType, *Shape]): ...
class Float32Array(Array[np.float32, *Shape]): ... ```
If so, hopefully this should be clear from the new section on 'An Ideal Array Type'. If you mean something different, could you clarify?
---
Latest changes at https://github.com/python/peps/pull/1751. I think this incorporates most of the feedback, but let me know if I've missed anything.
One significant change I've (tentatively) made is renaming `Expand` to `Unpack`, to reflect the terminology we use with regular tuples. I'm surprised no one else has suggested this, so I might be missing something - are there any arguments against calling what we're doing 'unpacking'?
On Mon, 28 Dec 2020 at 19:27, Alfonso L. Castaño < alfonsoluis.castanom@um.es> wrote:
As Guido said, while working on type arithmetic I also explored some ideas about how to deal with the exact length of a variadic, as well as dimension specific operations. The idea does not need any sort of dependent typing, just to take advantage of literal types. I did not comment about this earlier since I thought that this PEP should be as minimal as possible. The main idea is that, since we may need a custom operator on variadics for each specific use case, it would be better to have something more abstract.
https://docs.google.com/document/d/1IlByrIjZPPxTa_1ZWHLZDaQrxdGrAbL71plzmXi0...
TLDR: def f(x : Tensor[Ts], y : |Ts|): ... or def f(x : Tensor[Ts[N]], y : N): ...
My initial motivation was to leverage the length operator on variadics (|_|) that I wanted to introduce to also constraint the length of the variadics, so that not more operators would be needed for that task (apart from that operator of course). However, nowadays I think that there is no need to rely on the length operator for that and we could use one of the alternative syntaxes.
Regarding the current PEP, congratulations for the progress so far! However, I might have missed something but: where is specified the constraints that a variadic can have (variance, bound...)? And the subtyping rules for variadics? _______________________________________________ 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: mrahtz@google.com
_______________________________________________ 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