✨ towards a broadcasting-aware rank-typing framwork #538
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This adds several new type-check-only types to
_numtype
, which can be divided into two categories: Rank-types, and broadcast type-aliases.The rank-types subclass and wrap the integer tuples that are currently used as shape-types. This makes them backwards-compatible (after modifying
ndarray.shape
), while making it possible to embed static-typing information, such as the broadcasting rules, into these types, as type-check-only methods or attributes.Rank0 <: ()
Rank1 <: (int,)
Rank2 <: (int, int)
Rank3 <: (int, int, int)
Rank4 <: (int, int, int, int)
Rank0ToN <: (int, ...)
Rank1ToN <: (int, *(int, ...))
Rank2ToN <: (int, int, *(int, ...))
Rank3ToN <: (int, int, int, *(int, ...))
Rank4ToN <: (int, int, int, int, *(int, ...))
Another advantage (usually), is that these types don't have a mutual subtyping relation, unlike their
tuple
base types. So e.g.Rank0
is not assignable toRank0ToN
. This makes a lot easier, since there's no need to worry about overlapping overloads, complex constraint-set solvers.The most important usecases is broadcasting. For rank-typing purposes, broadcasting two ranks is equivalent to taking the maximum of the two. Most of the this static-typing machinery is basically an implementation such a maximum (and a minimum) function, disguised as a type-alias called
Broadcastable
(andBroadcaster
for the minimum). For example,r: Broadcastable[tuple[int]]
acceptsRank0
,Rank1
,Rank0ToN
, andRank1ToN
, but rejects all other rank types. It does not accept bare integer tuples, and instead has to be used "the other way around", i.e. by passing the bare integer tuples to theBroadcastable
type, or its mirror image, theBroadcaster
type.The plan is to gradually start integrating these types, and iterate on them whenever it turns out to be necessary. I also plan to embedding the shaped array-like types in the rank-types, so that it's statically known that arrays of
Rank2
acceptSequence[Sequence[T]]
, which could help make things more readable, maintainable, DRY, and pretty.I may also add some more rank-types later on, as I expect that e.g.
Rank1To2
is going to be useful to have (unions are smelly after all).towards #539