Can't use @dispatch on methods with types inheriting from Generic
Simple example:
from typing import TypeVar, Generic
from plum import dispatch
T = TypeVar('T')
class FooBar:
pass
class Foo(Generic[T]):
pass
class Bar:
def __init__(self):
pass
@dispatch
def some_method(self, foo: Foo[FooBar]):
pass
Bar().some_method(Foo())
This will fail with an error as follows:
line 420, in ptype
raise RuntimeError(f'Could not convert "{obj}" to a type.')
RuntimeError: Could not convert "__main__.Foo[__main__.FooBar]" to a type.
Is this functionality missing or do I need to add any more assistance in for plum to get this working?
Hey @rupert-madden-abbott,
Thanks for opening an issue!
The simple example that you give works for me:
from typing import TypeVar, Generic
from plum import dispatch
T = TypeVar('T')
class Bar(Generic[T]):
pass
class Foo:
@dispatch
def some_method(self, bar: Bar):
print("Let's go!")
>>> a = Foo()
>>> b = Bar()
>>> a.some_method(1)
NotFoundLookupError: For function "some_method" of __main__.Foo, signature Signature(__main__.Foo, builtins.int) could not be resolved.
>>> a.some_method(b)
Let's go!
Might you not be on the latest version, or perhaps running a subtly different example?
@wesselb my apologies, the example I gave was not right. I have updated with an example that does fail.
Crucially, my example was failing to supply a type parameter for Bar when it was specified as the type of the parameter.
I've tested the new snippet and verified that it does produce an error.
For information, this is on version 1.5.4
No problem at all! I figured that the example was missing something.
Unfortunately, this usage of typing is not (yet) supported by Plum. Plum, however, does offer a construct called parametric types, which you can use to achieve the same thing:
from plum import parametric, dispatch
class FooBar:
pass
@parametric
class Bar:
def __init__(self, x):
self.x = x
@classmethod
def __infer_type_parameter__(cls, x):
return type(x)
class Foo:
@dispatch
def some_method(self, bar: Bar[FooBar]):
print("Let's go!")
>>> Foo().some_method(Bar(FooBar()))
Let's go!
>>> Foo().some_method(Bar(1))
NotFoundLookupError: For function "some_method" of __main__.Foo, signature Signature(__main__.Foo, __main__.Bar[<class 'int'>]) could not be resolved.
I realise that it would be super convenient to fully support all features of typing, but that's a work in progress.