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

Types 为什么函数参数在Ocaml中不能是多态的?,types,polymorphism,ocaml,parametric-polymorphism,Types,Polymorphism,Ocaml,Parametric Polymorphism,假设我有以下功能: let rejected f = (f 1, f "hi");; 它被类型检查器拒绝了,我真的不明白为什么类型检查器拒绝它。因为f可以是多态函数(比如说id),类型检查器应该允许它。有人能解释一下吗?这是由于“let多态性”,又名“prenex多态性”,又名“ML型多态性”。搜索此术语将为您提供有关此术语的一些信息 用外行的话说,这就是类型推断的工作方式,在某些情况下,您需要停止泛化,并修复类型变量。在ML样式的多态性中,这是在let级别上完成的。因此,let绑定中的函数应

假设我有以下功能:

let rejected f = (f 1, f "hi");;
它被类型检查器拒绝了,我真的不明白为什么类型检查器拒绝它。因为f可以是多态函数(比如说
id
),类型检查器应该允许它。有人能解释一下吗?

这是由于“let多态性”,又名“prenex多态性”,又名“ML型多态性”。搜索此术语将为您提供有关此术语的一些信息

用外行的话说,这就是类型推断的工作方式,在某些情况下,您需要停止泛化,并修复类型变量。在ML样式的多态性中,这是在
let
级别上完成的。因此,let绑定中的函数应该统一使用,即使用相同的参数。如果这对您来说是一个问题,那么您可以使用记录、对象或(可能)语言的其他一些功能来克服它。以下是OCaml的摘录:

如何编写具有多态参数的函数? 在ML中,参数 函数的内部不能是多态的; 因此,需要进行以下键入:

设f(g:'a->'a)xy=gx,gy
val f:('a->'a)->'a->'a->'a*'a=
该功能不尽相同 正如我们所希望的那样是多态的。然而,在OCaml中,它是 可以使用一阶多态性。为此,您可以使用 记录或物品;对于记录,您需要声明 在函数中使用前键入

设f(o:'a>)xy=o#gx,o#gy
类型id={g:'a.'a->'a;}
设f r x y=r.g x,r.g y
这是由于“let多态性”,又名“prenex多态性”,又名“ML型多态性”。搜索此术语将为您提供有关此术语的一些信息

用外行的话说,这就是类型推断的工作方式,在某些情况下,您需要停止泛化,并修复类型变量。在ML样式的多态性中,这是在
let
级别上完成的。因此,let绑定中的函数应该统一使用,即使用相同的参数。如果这对您来说是一个问题,那么您可以使用记录、对象或(可能)语言的其他一些功能来克服它。以下是OCaml的摘录:

如何编写具有多态参数的函数? 在ML中,参数 函数的内部不能是多态的; 因此,需要进行以下键入:

设f(g:'a->'a)xy=gx,gy
val f:('a->'a)->'a->'a->'a*'a=
该功能不尽相同 正如我们所希望的那样是多态的。然而,在OCaml中,它是 可以使用一阶多态性。为此,您可以使用 记录或物品;对于记录,您需要声明 在函数中使用前键入

设f(o:'a>)xy=o#gx,o#gy
类型id={g:'a.'a->'a;}
设f r x y=r.g x,r.g y

还有两种方法可以做到这一点:一流的模块和(我想说是最优雅的)GADT。我认为对象是个坏主意,因为它们在生成的程序集上更重。@PatJ,你能提供一个例子,说明如何用GADT解决问题吗?经过检查,结果证明我错了,我认为可以在GADT定义中简单地声明一阶多态性。我仍然认为这会很酷。还有两种方法可以做到这一点:一流的模块和(我想说是最优雅的)GADT。我认为对象是个坏主意,因为它们在生成的程序集上更重。@PatJ,你能提供一个例子,说明如何用GADT解决问题吗?经过检查,结果证明我错了,我认为可以在GADT定义中简单地声明一阶多态性。不过我还是觉得那会很酷。
let f (g : 'a -> 'a) x y = g x, g y 
val f : ('a -> 'a) -> 'a -> 'a -> 'a * 'a = <fun> 
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