Haskell中为何更泛型的高阶rank类型函数无法通过类型检查?
Haskell高阶Rank类型中的类型兼容性问题
要理解为什么fun编译失败而fun2成功,核心在于多态类型的实例化方向限制:泛化的多态类型可以被窄化为更具体的类型,但反之不行。
为什么fun2能正常编译
fun2的类型签名是:
fun2 :: (forall a. a -> Bool) -> (forall b. [b] -> Bool)
forall a. a -> Bool是一个极度泛化的函数类型——它能接受任意类型的参数(包括所有列表类型),返回布尔值。当我们需要一个forall b. [b] -> Bool类型的函数时,只需要将泛化类型中的a实例化为[b]即可,这完全符合多态类型的实例化规则。因此fun2 arg = arg的定义是合法的:一个能处理任意类型参数的函数,自然能处理所有列表类型的参数。
为什么fun会被GHC拒绝
fun的类型签名是:
fun :: ((forall b. [b]) -> Bool) -> ((forall a. a) -> Bool)
(forall b. [b]) -> Bool是一个受限的函数类型——它的参数只能是适配所有列表类型的多态值(比如空列表[]),无法接受非列表类型的多态值(比如能被实例化为Int的undefined)。而(forall a. a) -> Bool要求函数能接受任意类型的多态值,显然前者无法满足这个要求:你不能把一个只能处理列表多态值的函数,强行当成能处理所有类型多态值的函数来用。
本质上,这不是简单的函数子类型逆变问题,而是Rank-2多态类型的实例化规则:泛化类型可以向下兼容具体类型,但具体类型无法向上扩展到泛化类型。
内容的提问来源于stack exchange,提问作者NisNis
相关产品推荐
相关产品推荐

