Any和Forall a.a是一样的吗?
Python 有一个叫做 Any
的类型,它可以和任何类型都兼容。那是不是可以用 Haskell 语言中的 forall a.a
来表示 Any
,而不是再添加一个新类型呢?
1 个回答
1
不,它们是不同的。
forall a. a
是一种没有实例的类型。(一个通用类型应该是所有其他类型的并集;而这更像是所有其他类型的交集。)你只能把底层值赋给这种类型的变量:
-- With the ExplicitForAll option set in GHC
x, y :: forall a.a
x = undefined -- OK
y = 'c' -- Not OK
因此,它是最常用来表示一个函数永远不会返回的类型,这可能是因为它发散(进入无限循环)
> :t let f = f in f
let f = f in f :: t -- forall t. t
或者因为它抛出了一个异常。
> :t error
error :: [Char] -> t -- forall t. [Char] -> t
Any
是一种伪类型,它与所有其他类型一致,但并不是任何其他类型的子类型或超类型。
x: Any = 1 # OK
y: Any = 'c' # OK
既然1
也不是Any
的实例,但根据一致性的定义,这样的赋值是被允许的。
在某种意义上,Python 至少在类型检查方面有两个与forall a. a
等效的类型,分别是typing.NoReturn
和typing.Never
。后者在 Python 3.11 中被引入,作为前者的更清晰替代,但它们在其他方面是等效的。(NoReturn
主要用作返回类型注解,而 Never
明确表示一个空类型,这种类型除了作为不返回函数的返回类型外还有其他用途。NoReturn
似乎已经非正式地被弃用了。)
一致性是将子类型扩展到一个“宇宙”,在这个宇宙中,Any
被添加为一种特殊类型。正如在PEP 483(在渐进类型总结)中所述,
- 如果类型
t1
是类型t2
的子类型,那么这两个类型是一致的。(但反过来不成立。)Any
与每种类型都是一致的。(但Any
不是每种类型的子类型。)- 每种类型与
Any
都是一致的。(但每种类型也不是Any
的子类型。)