我对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
类型?
我很难理解OCaml
的实现
let polymorphism
,如果有人能够简明扼要,我会非常感激
关于这个问题的描述。
答案 0 :(得分:3)
您的代码不必要地混淆,因为您在B中使用相同名称f
表示两个不同的内容,而在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
类型的函数数量非常有限。