I want to express that the first parameter is a "list" of the second parameter, and that the result has the same type as the second parameter.
This mysum
(ie. not the standard lib sum
) should work equally well with int/float/str/list, and any other type that supports +=
.
Naively:
def mysum(lst: list[T], start: T) -> T:
x = start
for item in lst:
x += item
return x
which produces:
(dev311) go|c:\srv\tmp> mypy sumtype.py
sumtype.py:26: error: Unsupported left operand type for + ("T")
sumtype.py:35: error: Cannot infer type argument 1 of "mysum"
Found 2 errors in 1 file (checked 1 source file)
Second attempt:
from typing import Iterable, Protocol, TypeVar
T = TypeVar('T')
class Addable(Protocol[T]):
def __add__(self, other: T) -> T:
...
class RAddable(Protocol[T]):
def __radd__(self, other: T) -> T:
...
def mysum(lst: Iterable[Addable|RAddable], start: Addable) -> Addable:
x = start
for item in lst:
x += item
return x
however, this doesn't place any restrictions on the "list" items and start being the same type, so this typechecks:
class Foo:
def __radd__(self, other: int) -> int:
return other + 42
mysum([Foo()], []) # <=== should ideally fail since Foo() and [] are not the same type
and fails with a type-error at runtime:
(dev311) go|c:\srv\tmp> python sumtype.py
Traceback (most recent call last):
File "c:\srv\tmp\sumtype.py", line 27, in <module>
mysum([Foo()], [])
File "c:\srv\tmp\sumtype.py", line 18, in mysum
x += item
File "c:\srv\tmp\sumtype.py", line 24, in __radd__
return other + 42
~~~~~~^~~~
TypeError: can only concatenate list (not "int") to list
I'm assuming it can't be this difficult to type-annotate a generic function, so what am I missing..?