bcl*_*man 5 functional-programming sml
我刚刚在Ch中遇到过这些.Ullman的ML编程元素中的 5个.他说:
"一个类型变量,例如'a有两个不同的含义.它可以表示"对于每个类型T,这个对象的实例用类型T代替'a.这种类型变量称为可推广的."
然后他说:
" 'a也可以表示我们选择的任何一种类型.但是,在选择了一种类型之后,即使我们重复使用原始类型变量描述其类型的对象,类型也不能改变'a.这种类型变量称为非泛化. "
有人能给出每种类型的例子吗?我很难绕过这个并理解这种区别似乎很重要(他建立在这些定义的基础上).
谢谢!
这是SML 中值限制的结果。
\n\n当语言推断程序的类型时,它可以找到适用于任何类型的表达式,它用类型变量表示。该map函数就是一个很好的例子。(我的语法可能有点偏差,因为我从未使用过 SML。)
fun map f nil = nil\n | map f (x::xs) = f x :: map f xs\nRun Code Online (Sandbox Code Playgroud)\n\n由于此函数适用于任何类型的列表,因此它获取一个类型变量:
\n\n(\'a -> \'b) -> \'a list -> \'b list\nRun Code Online (Sandbox Code Playgroud)\n\n我们可以对map两者使用相同的函数,int list并且string list\xe2\x80\x94 这是一个可泛化的类型变量。值得注意的一件事是这种nil情况:nil可以很容易地成为 的空列表int和 的空列表string。它有类型\'a list.
在一个完美的世界里,这就是我们所拥有的一切。然而有一个问题:可变引用。遵循与上面相同的逻辑,以下ref内容的类型中也将有一个类型变量:
val x = ref nil\nRun Code Online (Sandbox Code Playgroud)\n\n我们期望x成为一个(\'a list) ref. 就像nil它本身一样,它可以很容易地成为 a(int list) ref或(string list) ref\xe2\x80\x94 或者可以吗?问题是我们可以设置引用。如果我们可以使用它x ,就好像它具有更具体的类型,(int list) ref我们可以将其设置为[1,2,3]. 然后,如果我们可以将它用作(string list) ref其他地方,我们可以读出[1,2,3]需要字符串列表的内容!那是个问题。
为了克服这个问题,SML有值限制。粗略地说,这意味着那些“看起来”不像函数的东西不能是完全多态的\xe2\x80\x94,它们不能具有可泛化的类型变量。相反, 的类型x将基于我们使用它的第一个具体类型(即(int list) ref)。如果我们继续尝试使用x不同的具体类型,我们将收到有关不可泛化类型变量的错误。
从某种意义上说,不可泛化类型变量只是一个占位符,直到我们使用x它并赋予它具体类型为止。这有点令人困惑,因为它看起来仍然像普通类型变量 ( \'a),但如果我们以多种方式使用它,就会出现错误。我认为 OCaml 在区分两者方面做得更好。xOCaml 会推断as的类型\'_a,它在语法上与普通类型变量不同,并明确表示它只是一个占位符,而不是普通的多态值。
这是语言中的一个小问题,但如果你想拥有这样的可变引用,这基本上是不可避免的。
\n