通过类型注释抽象Python中的类型构造函数

通过类型注释抽象Python中的类型构造函数,python,static-analysis,static-typing,mypy,higher-kinded-types,Python,Static Analysis,Static Typing,Mypy,Higher Kinded Types,我想静态地强制类的方法返回一个封装在某个抽象类型中的值,我对此一无所知: 例如,给定抽象类 F = ??? class ThingF(Generic[F]): @abstractmethod def action(self) -> F[Foo]: ... 我希望能够静态检查这是否无效: class ThingI(ThingF[List]): def action(self) -> Foo: ... 因为action

我想静态地强制类的方法返回一个封装在某个抽象类型中的值,我对此一无所知:

例如,给定抽象类

F = ???    

class ThingF(Generic[F]):
    @abstractmethod
    def action(self) -> F[Foo]:
        ...
我希望能够静态检查这是否无效:

class ThingI(ThingF[List]):
    def action(self) -> Foo:
        ...
因为
action
不会返回
List[Foo]

然而,上面对
ThingF
的声明甚至没有运行,因为
Generic
希望它的参数是类型变量,而我找不到一种方法使
F
成为“带孔”的类型变量

两者

不工作,因为
TypeVar
不可下标,或者
Generic[~T]
不能用作类型变量

基本上我想要的是一个“高级类型变量”,一个类型构造函数的抽象,如果你愿意的话。也就是说,上面写着“F可以是任何类型,它可以采用另一种类型来生成具体类型”


有没有办法用Python的类型注释来表达这一点,并用mypy静态检查它?

不幸的是,类型系统(如PEP 484所述)不支持更高级的类型——这里有一些相关的讨论:


mypy和其他类型检查工具可能在将来某个时候获得支持,但我不会屏息以待。这需要一些相当复杂的实现工作才能完成。

您可以将更高级的类型与
dry python/returns一起使用。
我们同时提供了原语和一个定制的
mypy
插件来让它工作

下面是一个使用
Mappable
aka
Functor
的示例:

输入import Callable,TypeVar
从returns.interfaces.mappable导入MappableN
从returns.primitives.hkt导入Kinded,KindN,Kinded
_FirstType=TypeVar(“FirstType”)
_SecondType=TypeVar(“SecondType”)
_第三种类型=类型变量(“第三种类型”)
_UpdatedType=TypeVar(“U UpdatedType”)
_MappableKind=TypeVar(“u MappableKind”,bound=MappableN)
@类
def映射_(
容器:KindN[\u MappableKind,\u FirstType,\u SecondType,\u ThirdType],
函数:可调用[[u FirstType],[u UpdatedType],
)->KindN[\u MappableKind,\u UpdatedType,\u SecondType,\u ThirdType]:
返回container.map(函数)
它适用于任何可映射的
,:

from returns.maybe导入maybe
def测试(arg:float)->int:
...
显示类型(map_uu(Maybe.from_uvalue(1.5),test))#N:显示类型为“returns.Maybe.Maybe[builtins.int]”
以及:

from returns.result导入结果
def测试(arg:float)->int:
...
x:结果[浮点,str]
显示类型(map(x,test))#N:显示类型为“returns.result.result[builtins.int,builtins.str]”
它当然有一些限制,比如:它只适用于直接的
种类
子类型,我们需要一个单独的别名
种类1
种类2
种类3
,等等,因为当时
mypy
不支持变量泛型

资料来源: 插件:

文件:


公告帖子:

出于好奇:如果您对利用类型系统感兴趣,为什么不使用更强类型的语言呢?看到人们对使用Python的HKTs如此感兴趣真是太酷了。:-)事实上,我只是好奇,我对用Python做这件事的兴趣相当学术化。这是我最熟悉的语言,但在深入到FP Scala和Haskell之后,我非常怀念强大的类型系统带来的舒适感。我知道大多数Python开发人员都不太熟悉这一点,甚至都不希望看到这一点。感谢您提供了指向该讨论的链接。不过,我真的希望会有办法。我预计,随着强类型FP最近越来越受欢迎,将来会有越来越多的人在寻找实现这一目标的方法。也许这会将该功能请求进一步推上议事日程。不过,现在我不得不承认这是不可能的。谢谢
F = TypeVar('F')
T = TypeVar('T')
F = Generic[T]