【问题标题】:Are function parameters not polymorphic in Algorithm W (or Haskell)?算法 W(或 Haskell)中的函数参数不是多态的吗?
【发布时间】:2021-07-22 07:55:10
【问题描述】:

我正在为一种玩具语言实现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 是多态的,但似乎不是。请注意,如果 id 使用 let 定义而不是作为参数传递,则此示例有效:

let id x = x in id id 'a'
'a'
:: Char

查看算法 W 的推理规则时,这是有道理的,因为它有一个 let 表达式的泛化规则。

但我想知道这是否有任何原因?不能把函数参数也泛化成多态使用吗?

【问题讨论】:

  • 不是(\x -> x) 是或不是多态的,而是id绑定let id = \x -> x in id id 1 有效。与\x -> x 相同,但let 绑定具有多态类型。它被称为“let 多态性”。
  • @WillNess 很好的澄清。在发布接受的答案之前,我没有意识到这一点。我会相应地更新问题。

标签: algorithm haskell type-systems hindley-milner


【解决方案1】:

泛化 lambda 绑定变量的问题在于它需要更高等级的多态性。举个例子:

(\id -> id id 'a')

如果这里id的类型是forall a. a -> a,那么整个lambda表达式的类型一定是(forall a. a -> a) -> Char,是等级2的类型。

除了这个技术点之外,还有一个论点是更高等级的类型非常罕见,因此与其推断非常罕见的类型,不如说用户犯了错误的可能性更大。

【讨论】:

  • 这是显式关于不可见参数变得很重要的地方,身份函数id id 'a' 应用于两种不同的类型id @(Char -> Char) (id @Char) 'a'@type 语法通过TypeApplications 启用,它允许覆盖类型参数的可见性。如果你想抽象出id,没有单态类型就足够了,因为它必须像(Char -> Char) -> (Char -> Char)Char -> Char 一样有效。解决方案是明确地给id一个更高级别的类型:\(id :: forall a. a -> a) -> id id 'a'就像Noughtmare所说的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-14
  • 2013-08-20
  • 1970-01-01
  • 2018-04-30
  • 2016-11-27
  • 2018-02-15
  • 1970-01-01
相关资源
最近更新 更多