繁体   English   中英

为什么OCaml有时需要进行eta扩展?

[英]Why does OCaml sometimes require eta expansion?

如果我有以下OCaml功能:

let myFun = CCVector.map ((+) 1);;

它在Utop中运行良好,Merlin不会将其标记为编译错误。 但是,当我尝试编译它时,我收到以下错误:

错误:此表达式的类型, (int,'_ a)CCVector.t - >(int,'_ b)CCVector.t ,包含无法泛化的类型变量

如果我eta-expand它然后它编译好:

let myFun foo = CCVector.map ((+) 1) foo;;

所以我想知道为什么它不能以eta-reduced形式编译,以及为什么eta-reduced表单似乎在顶层(Utop)中工作但在编译时不起作用?

哦,CCVector的文档就在这里 '_a部分可以是`RO或`RW,具体取决于它是只读还是可变。

你在这里得到的是ML语言家族的价值多态性限制。

限制的目的是将let-polymorphism和副作用结合起来。 例如,在以下定义中:

let r = ref None

r不能有多态类型'a option ref 除此以外:

let () =
  r := Some 1;       (* use r as int option ref *)
  match !r with
  | Some s -> print_string s  (* this time, use r as a different type, string option ref *)
  | None -> ()

错误地类型检查为有效,但它崩溃了,因为参考单元r用于这两种不兼容的类型。

为了解决这个问题,在80年代进行了许多研究,价值多态性就是其中之一。 它将多态性限制为只允许定义形式为“非扩展”的绑定。 Eta扩展形式是非扩展的,因此你的eta扩展版本的myFun具有多态类型,但不是eta减少一个。 (更确切地说,OCaml使用这个值多态的宽松版本,但故事基本相同。)

当let绑定的定义是扩展的时,没有引入多态,因此类型变量是非泛化的。 这些类型在顶层打印为'_a ,它们的直观含义是:它们必须在以后实例化为某种具体类型:

# let r = ref None                           (* expansive *)
val r : '_a option ref = {contents = None}   (* no polymorphism is allowed *)
                                             (* type checker does not reject this,
                                                hoping '_a is instantiated later. *)

我们可以在定义后修复类型'_a

# r := Some 1;;                              (* fixing '_a to int *)
- : unit = ()
# r;;
- : int option ref = {contents = Some 1}     (* Now '_a is unified with int *)

修复后,您无法更改类型,从而防止上面的崩溃。

允许此输入延迟,直到编译单元的输入结束。 toplevel是一个永不结束的单元,因此你可以在会话的任何地方使用'_a类型变量。 但是在分离的编译中, '_a变量必须在没有类型变量的情况下实例化为某种类型,直到ml文件结束:

(* test.ml *)
let r = ref None (* r : '_a option ref *)
(* end of test.ml. Typing fails due to the non generalizable type variable remains. *)

这是你的myFun函数与编译器一起发生的事情。

AFAIK,对于多态性和副作用的问题没有完美的解决方案。 与其他解决方案一样,值多态限制也有其自身的缺点:如果您想要具有多态值,则必须以非扩展方式进行定义:您必须eta-expand myFun 这有点糟糕但被认为是可以接受的。

你可以阅读其他一些答案:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM