2014-09-10 24 views
19

Aşağıdaki OCaml işlevi varsa: Bu Utop içinde çalışıyor ve Merlin derleme hatası olarak işaretlemek gelmezOCaml bazen neden eta genişletme gerektirir?

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

.

Hata: '- (._b CCVector.t bu ifadenin türünü (int,> int) ._a) CCVector.t' Bunu derlemeye çalıştığınızda, ancak, aşağıdaki hatayı alıyorum, ancak o zaman iyi derler

bunu eta-genişletirseniz

jeneralize olamaz değişkenleri yazın içerir:
let myFun foo = CCVector.map ((+) 1) foo;; 

bu yüzden eta-azaltılmış formda derleme değil neden merak oldu ve ayrıca eta-azaltılmış formu neden w görünüyor topleveleki ork (Utop) ama derlerken değil mi?

Oh ve CCVector belgeleri here'dur. '_a parçası, salt okunur veya değişebilir olup olmamasına bağlı olarak RO veya `RW olabilir.

+0

gibi arama bu. Her ne kadar Haskell, ilk görüşte Ocaml'ın değer kısıtlamasına benzer bir şekilde * vaguely * gibi davranan “korkulan monomorfizm kısıtlamasına” sahip olsa da, iki kısıtlamanın nedenleri * çok * farklıdır. Ocaml onu yan etkilere uydurmak için kullanır, ama Haskell saftır, bu yüzden buna gerek yoktur. Haskell'in kısıtlaması, değerlerin beklenmedik yeniden değerlendirilmesini önler ve kesinlikle zorunlu değildir - bazı kod türleri için, yardımcı olmaktan daha can sıkıcıdır ve onu kapatmak için popüler bir seçenek vardır. –

+2

İlk görüşte sandığınızdan daha benzerler. – augustss

cevap

23

Burada sahip olduğunuz, ML dil ailesinin değer polimorfizmi kısıtlamasıdır. Kısıtlamanın amacı, let-polimorfizm ve yan etkilerin birlikte yerleşmesidir. Örneğin, aşağıdaki tanımı:

let r = ref None 

r polimorfik tür 'a option ref sahip olamaz. Aksi halde:

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 ->() 

olduğu yanlış tip kontrol geçerli olarak değil, referans hücresi r bu iki uyumsuz türleri için kullanılır çünkü, çöküyor.

Bu sorunu düzeltmek için 80'lerde birçok araştırma yapılmış ve bunlardan bir tanesi de polimoprizmdir. Polimorfizmi, sadece tanım formu "genişlemeyen" olan bağların izin vermesi için kısıtlar. Eta genişlemiş form genişlemez, bu nedenle myFun'un eta genişletilmiş versiyonunun bir polimorfik türü vardır, ancak eta için bir azaltılmamıştır. (Daha net bir ifadeyle, OCaml bu değerin polimorfizminin rahat bir versiyonunu kullanır, fakat hikaye temelde aynıdır.)

Bağlanmanın tanımının genişlemesinin tanımı olduğunda, hiçbir polimorfizm tanıtılmamıştır, bu nedenle tip değişkenleri genelleştirilmeden bırakılır. . Bu tipler toplevel içinde '_a olarak basılır ve bunların sezgisel anlamı:

# 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. *) 

Biz tanımından sonra türünü '_a düzeltebilirim:

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

sonradan bazı somut tipine nesnelleştirilmesi gerekir Sabitlendikten sonra, yukarıdaki kilitlenmeyi önleyen türü değiştiremezsiniz.

Bu yazım gecikmesi, derleme biriminin yazılmasının sonuna kadar izin verilir. Üst seviye hiç bitmeyen bir birimdir ve bu nedenle oturumun herhangi bir yerinde '_a tip değişkenleri ile değerlere sahip olabilirsiniz.Ama ayrılan derleme, '_a değişkenler ml dosyanın sonuna kadar tip değişkenler olmadan bazı tip örneği olması gerekir: Bu derleyici ile myFun fonksiyonu ile oluyor ne

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

. AFAIK, polimorfizm ve yan etki sorununa mükemmel bir çözüm yoktur. Diğer çözümlerde olduğu gibi, değer polimorfizmi kısıtlamasının kendine ait dezavantajı vardır: Eğer bir polimorfik değere sahip olmak istiyorsanız, tanımı genişlemesiz olarak yapmanız gerekir: myFun'u eta-genişletmeniz gerekir. Bu biraz berbat ama kabul edilebilir kabul edilir.

Sen diğer bazı cevaplar okuyabilir: