【问题标题】:SML: Generalizable vs. Non-Generalizable Type VariablesSML:可泛化与不可泛化类型变量
【发布时间】:2015-08-19 02:48:13
【问题描述】:

我刚在 Ch. Ullman 的 5 个ML 编程元素。他说:

“诸如'a这样的类型变量有两种不同的含义。它可以表示“对于每个类型T,都有一个类型为T的对象的实例代替'a。这种类型变量称为可泛化的。”

然后他说:

"'a 也可以表示我们选择的任何一种类型。但是,在选择了一种类型之后,即使我们重用其类型使用原始类型变量'a 描述的对象,该类型也无法更改。这种类型变量称为不可泛化。”

有人能举出每种类型的例子吗?很难理解这一点并理解其中的区别似乎很重要(他建立在这些定义之上)。

谢谢!

【问题讨论】:

    标签: functional-programming sml


    【解决方案1】:

    这是 SML 中 value restriction 的结果。

    当语言为您的程序推断类型时,它可以找到适用于 any 类型的表达式,它用类型变量表示。 map 函数就是一个很好的例子。 (我的语法可能有点不对劲,因为我从未使用过 SML。)

    fun map f nil     = nil
      | map f (x::xs) = f x :: map f xs
    

    由于此函数适用于 任何 类型的列表,因此它会获得一个类型变量:

    ('a -> 'b) -> 'a list -> 'b list
    

    我们可以对int liststring list 使用相同的map 函数——这是一个通用类型变量。值得注意的是nil 的情况:nil 可以很容易地成为int 的空列表作为string 的空列表。它的类型为'a list

    在一个完美的世界里,这就是我们所拥有的一切。但是有一个问题:可变引用。按照与上述相同的逻辑,以下ref 的类型中也会有一个类型变量:

    val x = ref nil
    

    我们希望x('a list) ref。就像nil 本身一样,它可以很容易地成为(int list) ref(string list) ref——或者可以吗?问题是我们可以设置引用。如果我们可以使用x 好像 它有更具体的类型(int list) ref,我们可以将它设置为[1,2,3]。然后,如果我们可以将它用作其他地方的(string list) ref,我们可以将[1,2,3] 读出到期望字符串列表的东西!这是个问题。

    为了克服这个问题,SML 有值限制。粗略地说,这意味着那些“看起来”不像函数的东西不能是完全多态的——它们不能有可泛化的类型变量。相反,x 的类型将基于我们使用它的第一个具体类型(即(int list) ref)。如果我们继续尝试将x 与不同的具体类型一起使用,我们将收到关于不可泛化类型变量的错误。

    在某种意义上,一个不可泛化的类型变量只是一个占位符,直到我们使用x 并给它一个具体的类型。这有点令人困惑,因为它看起来仍然像一个普通类型变量 ('a),但是如果我们以多种方式使用它,就会给我们一个错误。我认为 OCaml 在区分两者方面做得更好。 OCaml 会将x 的类型推断为'_a,这在语法上与普通类型变量不同,并清楚地表明它只是一个占位符,而不是普通的多态值。

    这在语言中有点小问题,但如果你想拥有这样的可变引用,这基本上是不可避免的。

    【讨论】:

    • 你确定这就是 Ullman 所指的吗?我没有读过他的书,所以我不知道上下文;但如果他 is 暗指值限制,那么我认为他做得很差,因为 'a 实际上 cannot 表示不能表示的类型变量因价值限制而泛化。 (ref nil) : 'a list ref 之类的东西不会进行类型检查。 (您说“OCaml 在区分两者方面做得更好”,但实际上说“OCaml 与标准 ML 不同,两者都有,并且对它们使用略有不同的表示法”会更正确。)跨度>
    • 我确实漂亮,虽然我没有书来检查上下文。这就是我之前看到的“不可泛化类型变量”这个短语的看法,我相信一些编译器实际上是这样表达他们的错误消息的。 (如“值限制”部分中的here 所示。)
    • @ruakh:另外,在 OCaml 中,'_a 仅作为类型推断的结果出现(即在错误消息中)。您也不能直接编写这样的类型签名。也许我在答案中的解释在这方面不是很好。
    • Re:术语“不可概括”:当然——这也是我使用它的方式。但如果这就是他的意思的话,厄尔曼的说法似乎很奇怪。回复:OCaml:啊,好的,谢谢你的澄清。 :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-11
    • 2017-10-04
    • 1970-01-01
    • 2022-09-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多