2015-02-06 67 views
1

说,如果我有以下功能:为什么在Ocaml中函数参数不能是多态的?

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

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

回答

5

这是由于“让多态性”,又名“prenex多态性”,又名“ML型多态性”。搜索这些条款会给你一些关于这方面的信息。通俗地说,这就是类型推断是如何工作的,有些观点你需要停止泛化,并修正你的类型变量。在ML风格的多态中,这是在let级别完成的。结果,let绑定内部的函数应该统一使用,即使用相同的参数。如果这对您是个问题,那么您可以使用记录,对象或(也许)该语言的其他功能来克服它。这是从OCaml FAQ摘录:

如何写一个多态参数函数? 在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 
+0

两种方法可以做到这一点:一流的模块和(我想说的最优雅)GADTs。我会说对象是一个坏主意,因为它们在制作的组件上较重。 – PatJ 2015-02-06 02:22:01

+0

@PatJ,你能提供一个例子,说明如何用GADT来解决f g x y = g x,g y问题? – ivg 2015-09-30 17:05:47

+0

检查后发现我错了,我认为可以简单地在GADT定义中声明一阶多态。我仍然认为这很酷。 – PatJ 2015-10-01 08:25:15

相关问题