2010-07-09 40 views
12

任何人都可以解釋爲什麼下面的第二個例子不會編譯?爲什麼'代碼不夠通用'?

'測試2'給出了「錯誤FS0670:該代碼不夠通用,類型變量^ a不能泛化,因爲它會逃避它的範圍。」我無法理解此錯誤消息。

// Test 1 
type test1<'a> = | A of 'a 
    with 
    override t.ToString() = 
     match t with 
     | A a -> a.ToString() 

// Test 2 
type test2<'a> = | A of 'a 
    with 
    override t.ToString() = 
     match t with 
     | A a -> string a 

// Test 3 
type test3<'a> = | A of 'a 
    with 
    override t.ToString() = 
     match t with 
     | A a -> string (a :> obj) 

回答

5

這裏的另一個攝製:

let inline f< ^T>(x:^T) = box x 

type test4<'a> = | A of 'a 
    with 
    member t.M() = 
     match t with 
     | A a -> f a 

string是使用靜態類型約束的內聯函數,以及這種功能的錯誤診斷有時很差。我不太瞭解診斷消息本身,但重要的是,在呼叫站點,我們不知道通用類型'a,這意味着我們無法將呼叫的正確版本內嵌到string(或f我的repro)。在例如如果您轉播到obj,我們知道我們想要嵌入obj版本的string,這樣就可以。

0

我想這是因爲字符串有(OBJ - >串)的簽名,以便利用其自己的字符串迫使一個是類型obj的。 (F#不做隱式轉換。)

+1

'string' [事實上是'T - > string'](http://msdn.microsoft.com/en-gb/library/ee340491.aspx),所以這應該在理論上工作。儘管我沒有更好的解釋。 – 2010-07-09 09:22:41

+0

哦,是的,我只是卡住了字符串;;到F#交互式來獲取類型。 推測實際上使用字符串是強制編譯強制輸入類型,它選擇obj作爲最低公分母? – Massif 2010-07-09 09:56:48