函数参数在算法 W(或 Haskell)中不是多态的吗?
Are function parameters not polymorphic in Algorithm W (or Haskell)?
我正在为一种玩具语言实现 Algorithm W。我遇到了一个我想象会进行类型检查的案例,但没有。我在 Haskell 中尝试了同样的方法,令我惊讶的是它在那里也不起作用。
> (\id -> id id 'a') (\x -> x)
Couldn't match type ‘Char -> t’ with ‘Char’
Expected type: Char -> t
Actual type: (Char -> t) -> Char -> t
我原以为 id
是多态的,但它似乎不是。请注意,如果使用 let 定义 id
而不是作为参数传递,则此示例有效:
let id x = x in id id 'a'
'a'
:: Char
在查看算法 W 的推理规则时,这很有意义,因为它具有 let 表达式的泛化规则。
但我想知道这是否有任何原因?难道函数参数也不能泛化所以它可以多态使用吗?
泛化 lambda 绑定变量的问题在于它需要更高阶的多态性。举个例子:
(\id -> id id 'a')
如果这里id
的类型是forall a. a -> a
,那么整个lambda表达式的类型一定是(forall a. a -> a) -> Char
,是rank 2的类型。
除了这个技术要点之外,还有一种说法是更高级别的类型非常不常见,因此与其推断非常不常见的类型,不如说更可能是用户犯了错误。
我正在为一种玩具语言实现 Algorithm W。我遇到了一个我想象会进行类型检查的案例,但没有。我在 Haskell 中尝试了同样的方法,令我惊讶的是它在那里也不起作用。
> (\id -> id id 'a') (\x -> x)
Couldn't match type ‘Char -> t’ with ‘Char’
Expected type: Char -> t
Actual type: (Char -> t) -> Char -> t
我原以为 id
是多态的,但它似乎不是。请注意,如果使用 let 定义 id
而不是作为参数传递,则此示例有效:
let id x = x in id id 'a'
'a'
:: Char
在查看算法 W 的推理规则时,这很有意义,因为它具有 let 表达式的泛化规则。
但我想知道这是否有任何原因?难道函数参数也不能泛化所以它可以多态使用吗?
泛化 lambda 绑定变量的问题在于它需要更高阶的多态性。举个例子:
(\id -> id id 'a')
如果这里id
的类型是forall a. a -> a
,那么整个lambda表达式的类型一定是(forall a. a -> a) -> Char
,是rank 2的类型。
除了这个技术要点之外,还有一种说法是更高级别的类型非常不常见,因此与其推断非常不常见的类型,不如说更可能是用户犯了错误。