Python mypy泛型子类导致不兼容的类型

Python mypy泛型子类导致不兼容的类型,python,generics,inheritance,mypy,invariance,Python,Generics,Inheritance,Mypy,Invariance,我在玩弄用类型暗示实现幺半群。为此,我写了: M = TypeVar('M') class Monoid(Generic[M]): ... def append(self, m: 'Monoid[M]') -> 'Monoid[M]': raise NotImplementedError() 在子类中使用时,例如 A = TypeVar('A') class List(Monoid[A], Generic[A]): def __init__(s

我在玩弄用类型暗示实现幺半群。为此,我写了:

M = TypeVar('M')

class Monoid(Generic[M]):
    ...
    def append(self, m: 'Monoid[M]') -> 'Monoid[M]':
        raise NotImplementedError()
在子类中使用时,例如

A = TypeVar('A')

class List(Monoid[A], Generic[A]):
    def __init__(self, *values: A) -> None:
        self._values = tuple(values)
    ...
    def append(self, m: 'List[A]') -> 'List[A]':
        return List(*(self.values + m.values))

我得到
错误:“append”的参数1与超类型“Monoid”不兼容
。由于
List
Monoid
的一个适当的子类,我希望它能够键入。我做错了什么?

好吧,你的
列表
类不是Monoid的适当子类型。毕竟,您说过所有的幺半群都必须有一个append方法,可以接受任意的幺半群或幺半群的子类——那么,为什么可以缩小列表,使其
append
只能接受特定的列表呢

这违反了法律

您可以使用以下方法解决此特定情况:


现在,您要表达的是
Monoid
的所有子类必须实现一个
append
方法,该方法专门接受子类类型。有了这个新版本的Monoid,您的List类现在是类型安全的。

您甚至可以给
T
一个
Monoid
的上限:
T=TypeVar('T',bound='Monoid')
M = TypeVar('M')
T = TypeVar('T')

class Monoid(Generic[M]):
    ...
    def append(self: T, m: T) -> T:
        raise NotImplementedError()