2013-10-21 49 views
0

我讀功能不斷:SML不斷執行力度

fun constantly k a = k 

但我不知道如何使用它。 我試過這樣:

val a = constantly 10; 
stdIn:32.5-32.28 Warning: type vars not generalized because of 
    value restriction are instantiated to dummy types (X1,X2,...) 
    val a = fn : ?.X1 -> int * int -> int 

它的工作原理是這樣:

val a = constantly 10(); 
    val a : int = 10 

但不是這樣的:

val a = constantly 10; 
a(); 
stdIn:36.1-36.5 Error: operator and operand don't agree [tycon mismatch] 
operator domain: ?.X1 
operand:   unit 
in expression: 
    a() 

任何人可以幫助我在功能understanting?

回答

0

的事情是,fun constantly k a = k具有類型'a -> 'b -> 'a

的部分功能調用等constantly 10將被認爲是一個擴展表達式,和SML將被期待能夠推斷實際類型的類型變量爲constantly在這一點上。也就是說,SML會期望它可以取代類型變量'a'b,此時具體的類型爲T

由於您的參數a未在您的constantly函數的主體中使用,因此SML無法推斷任何有關它的內容。

你可能會認爲像val a = constantly 10的表達產生一類像'b -> int,而是因爲SML發現它無法確定的'b然後它改變它的虛擬(混凝土)型?.X1的類型,這就是爲什麼你結束使用功能類型?.X1 -> int

這只是SML告訴你,它不能正確推斷'b,因爲你沒有在擴展表達式中爲它提供足夠的類型信息,所以它已經爲它分配了一個虛擬的具體類型,它基本上使你的函數無法使用。

因此,另一篇文章中提到的另一種解決方案是使用具體類型來限定結果函數。

舉例來說,這應該工作:

val a = constantly 10: (int -> int) 

有了明顯的缺點有合格的類型變量'bint,因此,咖喱功能a不再是多態的功能,但它確實是一個咖喱功能。爲了這個工作,我們需要知道'b的具體類型,我們正在創建咖喱函數。

但是,如果您仍然需要curried函數是多態的,因爲您不能假設'b在這一點的具體/具體類型,那麼,如其他答案所述,您將需要提供另一個參數來攜帶您的多態類型:

val a = fn x => constantly 10 x 

這在seanmcl的答案中基本上是一樣的。

這工作,因爲現在x將包裝函數內攜帶'b具體類型在調用到constantly 10 x。當你調用函數咖喱a(即val _ = a(15)在這種情況下'bint

+0

謝謝!最終我明白了! –

1

這是價值限制。瞭解瞭解ML中的部分應用很重要。由於存在多態性,可變性是必要的。

http://mlton.org/ValueRestriction http://users.cis.fiu.edu/~smithg/cop4555/valrestr.html

你看到這樣的警告任何時候,你可以通過ETA-擴大表達修復它。

fun a x = constantly 10 x; 
+0

謝謝你,有有用的信息,具體的類型將被定義,但我不知道它是如何工作的,功能不斷。 –

+0

「由於多態性的存在,這是必須的。」 OCaml怎麼沒有這個問題? OCaml具有相同的可變性和多態性。但是'不斷地讓k a = k ;;讓a =不斷10 ;; a();;'在OCaml中正確生成10。 – newacct

+0

看來OCaml的創造者已經[放寬了價值限制](http://caml.inria.fr/pub/papers/garrigue-value_restriction-fiwflp04.pdf)。 –