typing
typing copied to clipboard
Consider adding a "TopLevel" keyword that stands in for the top level bound of a corresponding type variable
Summary
Please consider a new typing keyword that stands in for the top level type of a corresponding type variable.
Motivation
Consider a test here and the corresponding definition of DistributionInfo here. The test loses all typing information because I used DistributionInfo[Any, Any, Any]. So if I want typing information, I have to use:
def test_flatten(generator: Generator,
distribution_info: DistributionInfo[NaturalParametrization[ExpectationParmetrization, JaxComplexArray],
ExpectationParametrization[NaturalParmetrization],
NumpyComplexArray]) -> None:
I would much rather just do
def test_flatten(generator: Generator,
distribution_info: DistributionInfo[TopLevel, TopLevel, TopLevel]) -> None:
It's not just shorter, but it reduces churn if the type definitions change. Note that TopLevel is recursive (it chooses the top level of the nested types too).
Isn't this redundant with defaults from PEP-696?
Isn't this redundant with defaults from PEP-696?
It's really similar, yeah. But even if I were to specify defaults, one would still have to follow the recursive definitions of nested type variables. So the default of the DistributionInfo variables would have to incorporate the top level types of NaturalParametrization's type variables, and the top level types of their nested type variables, etc.
And not all classes are going to want to specify defaults. If dict were annotated class dict[T: Hashable, U: Any](..., and without defaults, then it might be nice to type dict[TopLevel, TopLevel] as shorthand for dict[Hashable, Any]?
In other words, whereas Any does as little type checking as possible, TopLevel preserves as much as possible without specifying anything new.
In your example, the DistributionInfo has three type parameters, and all of them are invariant. If you supply a concrete type argument (whether explicitly, implicitly with a default type a'la PEP 696, or through a mechanism like the proposed TopLevel shorthand), callers of test_flatten would not be able to pass an argument whose type arguments are not exact matches. That's the nature of invariance. This restriction doesn't apply to DistributionInfo[Any, Any, Any] because Any is exempt from invariance checks.
Your example would make more sense if the three type parameters for DistributionInfo (and all of the other generic classes in your example) were covariant. The TopLevel mechanism would then work, but it would add no new value other than brevity. Since this isn't a pattern that occurs often (especially if it's applicable only for covariant type parameters), I think it would be hard to motivate the introduction of a new addition to the type system.
Your example would make more sense if the three type parameters for DistributionInfo (and all of the other generic classes in your example) were covariant.
Thanks for explaining, but that's not going to work because of the definition of DistirbutionInfo. I'm just curious why can't type checkers figure out here that p has type ExpectationParametrization[Any]? I realize that EP is bound to Any, but given that EP has an upper bound of ExpectationParametrization[Any], is there no way to deduce such an upper bound for p?
Related? https://github.com/python/typing/issues/912
@parched Yes, related! I wish that hadn't been closed. It would be nice to contribute to that thread.