python 类型注释中的链式引用

Hul*_*ner 5 python types type-hinting higher-kinded-types python-3.x

假设我有一个函数接受一个值和任意数量的函数,让我们调用 chain_call 的函数。

如果没有类型,一个简单的实现将是:

def chain_call(input_value, *args):
    for function in args:
        input_value = function(input_value)
    return input_value
Run Code Online (Sandbox Code Playgroud)

如你想象,将input_value可以是任何东西真的,但它总是一样的第一的第一个也是唯一需要的参数Callable*args: List[Callable]

从这里开始,Callable第一个也是唯一必需的参数与前一项返回类型的类型相同。

到目前为止,我已经设法定义了一个非常通用的类型,但它太松散了。

def chain_call(input_value: Any, *args: List[Callable[Any], Any]) -> Any: ...
Run Code Online (Sandbox Code Playgroud)

我真正喜欢的是这样的

T = TypeVar('T')

def chain_call(input_value: T, *args: List[Callable[T, ...], tr]) -> tr: ...
Run Code Online (Sandbox Code Playgroud)

其中TforCallable n+1trof Callable n,最终返回类型是 tr of Callable n_max。我不确定如何用类型系统表达这一点,并且希望得到任何指导。

sob*_*evn 1

这个完全类型化的函数存在于dry-python/returns.

我们称之为flow

from returns.pipeline import flow

assert flow('1', int, float, str) == '1.0'
Run Code Online (Sandbox Code Playgroud)

问题是,它是通过我们的库附带的flow自定义插件完全键入的。mypy因此,它将捕获此错误情况(以及许多其他错误情况):

from returns.pipeline import flow

def convert(arg: str) -> float:
    ...

flow('1', int, convert)
# error: Argument 1 to "convert" has incompatible type "int"; expected "str"
Run Code Online (Sandbox Code Playgroud)

文档:https ://returns.readthedocs.io/en/latest/pages/pipeline.html

来源: https: //github.com/dry-python/returns/blob/0f7d02d0c491a7c65c74e6c0645f12fccc53fe18/returns/_internal/pipeline/flow.py

插件:https://github.com/dry-python/returns/blob/0f7d02d0c491a7c65c74e6c0645f12fccc53fe18/returns/contrib/mypy/_features/flow.py