说如果我有以下功能:
let rejected f = (f 1, f "hi");;
它被类型检查器拒绝,我真的不明白为什么类型检查会拒绝它。因为 f 可以是一个多态函数(比如id
),并且类型检查器应该允许它。有人可以解释一下吗?
说如果我有以下功能:
let rejected f = (f 1, f "hi");;
它被类型检查器拒绝,我真的不明白为什么类型检查会拒绝它。因为 f 可以是一个多态函数(比如id
),并且类型检查器应该允许它。有人可以解释一下吗?
这是由于“let 多态性”,又名“prenex 多态性”,又名“ML 风格的多态性”。搜索这些术语将为您提供一些有关此的信息。
通俗地说,这就是类型推断的工作原理,在某些时候你需要停止泛化,并修复你的类型变量。在 ML 风格的多态中,这是在一个let
级别上完成的。因此,let 绑定中的函数应该统一使用,即使用相同的参数。如果这对您来说是个问题,那么您可以使用记录、对象或(也许)该语言的一些其他功能来克服它。以下是 OCaml常见问题解答的摘录:
如何编写具有多态参数的函数?在 ML 中,函数的参数在函数体内不能是多态的;因此输入以下内容:
let f (g : 'a -> 'a) x y = g x, g y
val f : ('a -> 'a) -> 'a -> 'a -> 'a * 'a = <fun>
该函数并不像我们希望的那样多态。然而,在 OCaml 中,可以使用一阶多态性。为此,您可以使用记录或对象;在记录的情况下,您需要在函数中使用它之前声明类型。
let f (o : <g : 'a. 'a -> 'a>) x y = o#g x, o#g y
type id = { g : 'a. 'a -> 'a; }
let f r x y = r.g x, r.g y