[Feature Request] Contravariant generics (if feasible, but maybe infeasible)
See original GitHub issueSo there I was, happily humming a tune while beartype slays the typing demons of type-tetris’ past… and, suddenly:
import beartype.door.TypeHint as th
import beartype.typing as bt
E_ID = bt.Union[int,str] # Entity ID's
DataType = bt.TypeVar('DataType', bound=bt.Optional[bt.Iterable], contravariant=True)
Entity = bt.Tuple[E_ID, DataType] # So (valid_id, (some_data1, some_data2, ...))
OK, now add some spice…
class Fake(bt.NamedTuple):
name:str
kind:str
velocity:float
MyFakeEntity = Entity[Fake]
and test them all:
(th(Entity).is_bearable(('hi',(2,3,4))), # this should work
th(Entity).is_bearable((1.20,(2,3,4))), # 1.2 is not an E_ID
th(Entity).is_bearable((0,None))) # Entity data is optional
th(MyFakeEntity).is_bearable((0,Fake('n1', 'bob',2.5))), # is a "fake"
th(MyFakeEntity).is_bearable((0,('n1', 'bob',2.5))) # technically not a "fake"
)
(True, False, True, False, False)
… wait a minute…?
Obviously without the contravariant=True
I get a True, False
, as expected. But in my case, entities are just consumers of their datatype, like “tagging protocols”. So if data iterable type B is a subclass of iterable type A, and I can tag arbitrary iterables with EntityA
, and only special Fake iterables with EntityB
, EntityA should be allowed anywhere EntityB is expected (EntityA is a subtype of EntityB).
All this is to say, I did a quick ctrl+F
on that glorious readme of yours, and lo-and-behold, contravariant is mentioned… in the table as “not supported”! 😅 And… I didn’t see any open issues for the feature request. If this isn’t a good place for that, let me know!
Issue Analytics
- State:
- Created 10 months ago
- Reactions:2
- Comments:13 (4 by maintainers)
Top GitHub Comments
Apologies, yes! Makes sense. I meant with the use of @beartype. My bad entirely.
It will work with
beartype.door.is_bearable
, though! If only static type checkers could useis_bearable
for narrowing, haha!I do think @leycec supports this currently.
No, no, I think it’s fair to say we’re all pretty deeply interested in this stuff! Thanks for the exposition! 😁
This is super helpful to know! I bet
@dataclass(frozen=True, eq=True)
is the most common line of code across all my projects, so I really ought to be usingNamedTuple
s. I can’t wait until @beartype can deeply check them in0.12.0
!Wow, this looks sweet! I’ll be trying this out soon.
Neat stuff! Yes I suppose I have become a Lark person, but under duress. I’d really rather be known as an attoparsec person, lol. I’ve been looking into trying to get a lot of what I’m missing from Haskell in Python. Unfortunately, I think something that compiles to python is just a bit too far away for me. I’ve been looking at using
fn.py
in my current project, though. I use so many damn lambdas andpartial()
calls that the underscore syntax and currying is starting to look really desirable.