beartype / plum

Multiple dispatch in Python
https://beartype.github.io/plum
MIT License
539 stars 24 forks source link

`Iterable[T]` not being dispatched #131

Open ilan-gold opened 10 months ago

ilan-gold commented 10 months ago

From https://github.com/beartype/plum/issues/27#issuecomment-1927271932.

To reproduce:

from collections.abc import Iterable
import plum

@plum.dispatch
def f(x: Iterable[int]): print("int!")

@plum.dispatch
def f(x: Iterable[str]): print("str!")

f(['first', 'second']) # AmbiguousLookupError: `f(['first', 'second'])` is ambiguous.

Version 2.3.2 and python 3.10.13

PhilipVinc commented 10 months ago

I had the doubt that this was caused by my recent refactoring and it is not. It's a bug that has existed for a while now.

I think it's because bear type does not really support parametric types...

PhilipVinc commented 10 months ago

This is the bug, cc @leycec , who probably knows already

In [1]: from beartype.door import is_bearable

In [2]: from collections.abc import Iterable

In [3]: is_bearable(['ci', 'ao'], Iterable[int])
Out[3]: True
leycec commented 9 months ago

Gah! Deep type-checking, huh? Yeah. @beartype mostly doesn't do that yet. I'm still nailing down the seemingly last remaining PEP 563 (i.e., from __future__ import annotations) bug for our upcoming @beartype 0.17.1 patch release. PEP 563: it is a special Hell.

Deep type-checking is what @beartype is all about in 2024, though. Let's optimistically choose to believe that @beartype will deeply type-check Iterable[...] type hints sometime this year. Obviously, that's not great. Later this year is better than nothing, but... if anyone has volunteer time to spare and would like to lend a helping PR hand over at @beartype, I would :heart_eyes: to gently guide you through the exact work needed to make this happen.

Until then, the pudgy bear cries tears of sadness for Plum.

wesselb commented 9 months ago

@ilan-gold Although Iterable[T] isn't currently supported (though hopefully later this year 🚀!), you can get the desired behaviour by typing with list:

import plum

@plum.dispatch
def f(x: list[int]): print("int!")

@plum.dispatch
def f(x: list[str]): print("str!")

f(['first', 'second'])  # str!

Clearly this is not optimal, but it might provide a workable temporary solution. :)

leycec commented 9 months ago

Totally. Excellent workaround, @wesselb. For even more generality, consider collections.abc.Sequence[int] and collections.abc.MutableSequence[str] as well; @beartype deeply type-checks both similarly to tuple[str, ...] and list[int].

Indeed, this is awful. To help this happen sooner, I'm accelerating deep type-checking on the @beartype roadmap. My top priorities are now:

I also didn't realize that Plum depended on deep type-checking for disambiguation. In hindsight... it makes sense. I like to think I would have prioritized all of this sooner if I'd known. Now, I can only say: "Woopsie." :woozy_face:

wesselb commented 9 months ago

@ilan-gold, @leycec, aha, of course Sequence is a much better workaround! In fact, that’s nearly as good as Iterable. :) Awesome.

@leycec Obviously there’s no need for any form of apology! Beartype is already providing an awesome feature set that’s more than sufficient. :) These are just cherries 🍒 on top of the already delicious cake 🎂.

ilan-gold commented 9 months ago

Hi all! Yup, I did Sequence right after opening the issue, and it probably more faithfully captures my use-case :). Thanks!