Closed
Description
While trying to implement a typesafe @curry
decorator which would enable partial application without writing any additional function-specific wrapper-code or other syntactic noise, I came across the problem of representing function-transformers using the python type system.
E.g.
Given two typed functions:
id(x) -> x
transform(f) -> f
I expect transform(id)
to be typed and typesafe as well.
The problem arises with Generics and can be reproduced by typechecking the following snippet:
from typing import Callable, TypeVar
X = TypeVar("X")
def id_int(x: int) -> int:
return x
def id_generic(x: X) -> X:
return x
def id_f(x: Callable[[X], X]) -> Callable[[X], X]:
return x
a: Callable[[int], int] = id_int
b: int = id_int(1)
# c: Callable[[X], X] = id_generic
d: int = id_generic(2)
# e: Callable[[Callable[[X], X]], Callable[[X], X]] = id_f
bound_id_int = id_f(id_int)
f: Callable[[int], int] = bound_id_int
g: int = bound_id_int(3)
bound_id_generic = id_f(id_generic)
# h: Callable[[X], X] = bound_id_generic
i: int = bound_id_generic(4) # ERROR HERE
Same as mypy
, pyright
cannot infer the type of X@id_generic
to be int
or Literal[4]
.
>>> pyright --version
pyright 1.1.126
>>> pyright callable_return_type.py
No configuration file found.
stubPath /[REDACTED] is not a valid directory.
Assuming Python platform Linux
Searching for source files
Found 1 source file
/[REDACTED]/callable_return_type.py
/[REDACTED]/callable_return_type.py:32:27 - error: Argument of type "Literal[4]" cannot be assigned to parameter of type "X@id_generic"
Type "Literal[4]" cannot be assigned to type "X@id_generic" (reportGeneralTypeIssues)
/[REDACTED]/callable_return_type.py:32:10 - error: Expression of type "X@id_generic" cannot be assigned to declared type "int"
"object" is incompatible with "int" (reportGeneralTypeIssues)
2 errors, 0 warnings, 0 infos
Completed in 0.523sec
>>> mypy --version
mypy 0.812
>>> mypy callable_return_type.py
callable_return_type.py:32: error: Incompatible types in assignment (expression has type "X", variable has type "int")
callable_return_type.py:32: error: Argument 1 has incompatible type "int"; expected "X"
Found 2 errors in 1 file (checked 1 source file)
This issue might be related to #1639, with the exception that here we have a transformer that produces a generic function, like python/mypy#1317.