Use typing and pytypes for type checking and multiple dispatch #434
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.
Addresses #351, #355.
This is a more ambitious version of the changes in #433 that uses the
typing
-compatible runtime type checking library pytypes for type checking and inference (viapytypes.is_subtype
, atyping
-compatible version ofissubclass
) and for pattern matching (via a pytypes-based fork of multipledispatch that usespytypes.is_subtype
in place ofissubclass
).After these changes, it should be possible to use all of
typing
directly when describing funsor input and output types or when writing patterns, e.g. we could simply replaceProduct
from #430 withtyping.Tuple
:...or use
typing.Tuple
, including variadic cases, in patterns like the ones needed forFinitary
in #423:As suggested in #355, we could even replace many of the assertions in our
Funsor.__init__
methods with runtime type checking in interpreters, eliminating lots of boilerplate code and potentially boosting performance (by making many assertions optional):I have also taken the opportunity to remove some of the uglier code in
FunsorMeta
and domains made obsolete by the use ofpytypes
andtyping
, including the custom introspection and subtype checking logic inFunsorMeta
.In #355 I had originally suggested going even further toward integrating
typing
with Funsor interpretations than the changes here by making parametricFunsor
subtypes usetyping.Generic
. I am somewhat skeptical about taking that additional step because of how difficult it is to interact withtyping.Generic
at runtime, and have chosen in this PR to retain a simplified version of theGenericTypeMeta
class as a substrate forFunsor
andFunsorMeta
.One critical question for this approach is how well the
multipledispatch
fork holds up in terms of correctness and performance and how much additional maintenance effort it would entail. In an ideal world, someone else would implement a performant, fullytyping
-compatiblemultipledispatch
completely independent of Funsor and we could just use their solution, since that's clearly a useful and interesting direction in its own right and there are a number of new runtime type checkers (1, 2) that could be repurposed to support it.However, since that is unlikely (AFAIK) in the near term and the developers of
multipledispatch
are not interested in merging thepytypes
-based version (which I took and lightly modified from an old pull request there), we'd have to maintain the fork ourselves. The core functionality seems to be largely complete - almost all of the multipledispatch and Funsor tests pass locally, and pytypes itself is extensively tested. We might need to add a dedicatedtyping
-compatibleDispatcher
upon which to basefunsor.ops.Op
andfunsor.registry.KeyedRegistry
that makes sure signatures usetyping
syntax, e.g. converting tuples totyping.Union
s orobject
totyping.Any
. As for performance, running tests locally shows there is definitely a slowdown relative to the currentmultipledispatch
, although it's much less severe than the discussion in thatmultipledispatch
PR would suggest.Another practical issue is the compatibility of
pytypes
with various Python versions, especially 3.7-3.9. It seems like that's been addressed to a large extent in theirmaster
branch, at least for the subset oftyping
we would use in Funsor, but I'm not entirely sure what its status is or when any outstanding issues might be resolved.I am cautiously optimistic about these questions, but it's too early to say right now whether they'd end up being show-stoppers relative to the status quo or the simpler approach in #433.