2

我正在玩弄带有类型提示的幺半群。为此,我写了:

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))

我明白了error: Argument 1 of "append" incompatible with supertype "Monoid"。由于List是 的正确子类Monoid,我希望它能够输入。我究竟做错了什么?

4

1 回答 1

1

好吧,您的List不是Monoid 的正确子类型。毕竟,您说过所有 Monoid 都必须有一个 append 方法,该方法可以接受任意 Monoid 或 Monoid 的子类——那么,为什么可以缩小 List 以使其append只能接受特定的 List 呢?

这违反了里氏替换原则

您可以通过使用通用 self来解决此特定情况:

M = TypeVar('M')
T = TypeVar('T')

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

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

于 2017-10-28T17:23:08.187 回答