为什么函数参数在 Ocaml 中不能是多态的?

Why function argument cannot be polymorphic in Ocaml?

假设我有以下功能:

let rejected f = (f 1, f "hi");;

它被类型检查器拒绝了,我真的不明白为什么类型检查器拒绝它。由于 f 可以是多态函数(例如 id),并且类型检查器应该允许它。有人可以解释一下吗?

这是由于 "let polymorphism",又名 "prenex polymorphism",又名 "ML-style polymorphism"。搜索此术语将为您提供一些相关信息。

通俗地说,这就是类型推断的工作原理,有些地方你需要停止泛化,并修复你的类型变量。在 ML 风格的多态性中,这是在 let 级别上完成的。因此,let 绑定中的函数应该统一使用,即使用相同的参数。如果这对你来说是个问题,那么你可以使用记录、对象或(也许)语言的其他一些特性来克服它。这是 OCaml FAQ:

的摘录

How to write a function with polymorphic arguments? In ML, an argument of a function cannot be polymorphic inside the body of the function; hence the following typing:

let f (g : 'a -> 'a) x y = g x, g y 
val f : ('a -> 'a) -> 'a -> 'a -> 'a * 'a = <fun> 

The function is not as polymorphic as we could have hoped. Nevertheless, in OCaml it is possible to use first-order polymorphism. For this, you can use either records or objects; in the case of records, you need to declare the type before using it in the function.

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