2014-01-09 35 views
2

我对OCaml中的let polymorphism感到困惑。OCaml的让多态实现

考虑下面的代码:

A: 
let f = (fun v -> v) in 
((f 3), (f true)) 

B: 
let f = (fun v -> v) in 
((fun g -> 
    let f = g in 
    f) f) 

C: 
let f = (fun v -> v) in 
((fun g -> 
    let f = g in 
    ((f 3), (f true))) f) 

对于A和B,不存在问题。但对于C,OCaml报告错误:

Error: This expression has type bool but an expression was expected of type 
     int 

因此,对于A,评估((f 3), (f true))时,f的类型是'a -> 'a, 为B,评估let f = g in f时,f的类型是'a -> 'a。 但对于C,在评估((f 3), (f true))时,f的类型为int -> int

为什么C的f没有类型'a -> 'a

我理解OCamllet polymorphism的实现难度,我就明白了很多,如果任何人都可以给它的简洁 描述关于问题。

回答

3

您的代码混淆不必要的,因为你使用相同的名称f您在B两个不同的东西,也两回事在C.

C内你有这样的功能:

fun g -> let f = g in (f 3, f true) 

这再次是不必要的复杂;这是一样的:

fun g -> (g 3, g true) 

这是不允许的原因是,如果g是一个多态函数,它才会起作用。这需要秩2多态性,即它需要定义具有多态性的功能参数的能力。

我不完全确定你想要做什么,但是你可以有一个记录类型,它的字段是一个多态函数。然后,您可以使用此记录类型来定义您的函数的东西:

# type r = { f : 'a . 'a -> 'a };; 
type r = { f : 'a. 'a -> 'a; } 
# (fun { f = g } -> (g 3, g true)) { f = fun x -> x };; 
- : int * bool = (3, true) 

# let myfun { f = g } = (g 3, g true);; 
val myfun : r -> int * bool = <fun> 

# myfun { f = fun x -> x };; 
- : int * bool = (3, true) 

的缺点是,你需要打包和解包的多态函数。

作为一个方面的评论,你的例子似乎并不令人信服,因为'a -> 'a类型的函数数量非常有限。