如何在Python中用mypy实现Haskell的RankN类型等价写法?
在Python中结合mypy实现Haskell风格的Rank-N类型
可以实现,你需要调整TypeVar的使用方式,让mypy识别到传入的函数是多态的(即能接受任意符合数值约束的类型并返回同类型),而不是被特化为单一类型。
原代码的问题
你之前用TypeVar("I", int, float)是联合类型绑定的TypeVar,mypy会自动把它特化为范围最宽的类型(这里是float,因为float兼容int),导致f被推断成Callable[[float], float]——所以传入int类型的1会报错,返回值也全是float,不符合预期。
正确实现方式
使用TypeVar的bound参数限定类型范围,并让函数参数的Callable标注体现多态性,对应Haskell里的forall语义:
from typing import Callable, TypeVar import numbers # 限定T为所有numbers.Real的子类(int、float都满足) T = TypeVar('T', bound=numbers.Real) def rankN(f: Callable[[T], T]) -> tuple[int, float]: return (f(1), f(1.0))
代码解释
bound=numbers.Real相当于Haskell中Num n的约束,限定T必须是支持数值操作的类型;Callable[[T], T]表示f是一个多态函数:它可以接受任何符合numbers.Real的类型T,返回相同类型的T。mypy会识别到f既能处理int也能处理float,因此返回的元组类型会被正确推断为tuple[int, float]。
测试验证
你可以用以下代码测试,mypy会正确识别返回类型:
# 测试多态函数 result = rankN(lambda x: x * 2) reveal_type(result) # mypy输出:Revealed type is "tuple[int, float]"
内容的提问来源于stack exchange,提问作者petrucci4prez
相关产品推荐
相关产品推荐

