簡體   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