jspahrsummers / adt

Algebraic data types for Python (experimental, not actively maintained)
MIT License
172 stars 14 forks source link

mypy plugin: Example for safe_integer in README does not type-check. #26

Closed wchresta closed 3 years ago

wchresta commented 4 years ago

When running mypy==0.711 against the following code taken from the README, mypy throws an error:

@adt
class ExampleADT:
    EMPTY: Case
    INTEGER: Case[int]
    STRING_PAIR: Case[str, str]

    @property
    def safe_integer(self) -> Optional[int]:
        return self.match(empty=lambda: None,
                          integer=lambda n: n,
                          string_pair=lambda a, b: None)
error: Incompatible return value type (got "None", expected "int")
error: Incompatible return value type (got "None", expected "int")
wchresta commented 4 years ago

Providing match with functions with explicit signatures type checks:

def _0ary_const_none() -> None:
    return None

def _1ary_id(a: int) -> int:
    return a

def _2ary_const_none(a: str, b: str) -> None:
    return None

@adt
class ExampleADT:
    EMPTY: Case
    INTEGER: Case[int]
    STRING_PAIR: Case[str, str]

    @property
    def explicit_safe_integer(self) -> Optional[int]:
        return self.match(empty=_0ary_const_none,
                          integer=_1ary_id,
                          string_pair=_2ary_const_none)

This might be a weakness in (or a misunderstanding on our part of) mypy's reasoning about of type variables.