Skip to content

generic methods/generic self don't seem to play with parameterized generics #4395

@bwo

Description

@bwo

(There are a couple of other issues that I think might be the same thing as this question, but I'm not sure, because they're posed at a lower level—apologies if this is actually a duplicate. #3153, maybe?)

The generic methods and generic self docs show how write a class with methods that accept/return arguments of the most precise type, so things like this work as intended:

from typing import Generic, TypeVar

T = TypeVar('T', bound='Modular')


### this works! yay!
class Modular(object):
    modulus = 0  # type: int

    def __init__(self, i):
        # type: (int) -> None
        self.i = i % self.modulus

    def __add__(self, other):
        # type: (T, T) -> T
        return self.__class__((self.i + other.i) % self.modulus)


class Mod5(Modular):
    modulus = 5


class Mod6(Modular):
    modulus = 6


Mod5(3) + Mod6(3)  # statically "disallowed"

mypy won't let me add Mod5s to Mod6s, hooray. But what if the relevant class is itself generic? This doesn't work:

In = TypeVar('In', contravariant=True)
Out = TypeVar('Out', covariant=True)
A = TypeVar('A')
B = TypeVar('B')

F = TypeVar('F', bound='FunctionLike') 

class FunctionLike(Generic[In, Out]):
    def call(self, arg):
        # type: (In) -> Out
        raise NotImplementedError

    def compose(self, other):
        # type: (F[In, Out], F[Out, B]) -> F[In, B]  # can't index `F`, so this doesn't work
        raise NotImplementedError

The type of compose shouldn't be (FunctionLike[In, Out], FunctionLike[Out, B]) -> FunctionLike[In, B], because then any two instances of any two subclasses could be composed together. It can't be (F, F) -> F because then all the type parameters are the same.

Is there a way to express this?

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions