2010-07-09 15 views
12

Czy ktoś może wyjaśnić, dlaczego drugi przykład poniżej nie zostanie skompilowany?Dlaczego "Kodeks nie jest wystarczająco ogólny"?

"Test 2" daje "błąd FS0670: Ten kod nie jest wystarczająco ogólny, zmienna typu^a nie może zostać uogólniona, ponieważ wymknie się jej zakresowi.". Nie rozumiem tego komunikatu o błędzie.

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

Odpowiedz

5

Oto kolejny repro:

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 jest funkcją inline, który używa ograniczeń typu statyczny, a diagnostyka błędów dla tych funkcji są czasami słabe. Naprawdę nie rozumiem samej wiadomości diagnostycznej, ale chodzi o to, że na stronie wywołania nie znamy generycznego typu 'a, co oznacza, że ​​nie możemy wstawić właściwej wersji połączenia do string (lub f w moja repro). Na przykład w W przypadku, gdy upcast do obj, wiemy, że chcemy wstawić obj wersja string, więc jest w porządku.

0

sobie wyobrazić, że to dlatego, że łańcuch ma podpis (obj -> string) więc przy użyciu ciąg na własny zmusza a do być typu obj. (F # nie robić ukryte odlewane.)

+1

'string' [jest w rzeczywistości' 'T -> string'] (http://msdn.microsoft.com/en-gb/library/ee340491.aspx), więc powinno to działać w teorii. Nie mam jednak lepszego wyjaśnienia błędu. –

+0

O tak, po prostu utknąłem string ;; w F # interaktywny, aby uzyskać typ. Prawdopodobnie użycie ciągu znaków zmusza kompilację do wymuszenia typu na danych wejściowych, a wybór obiektu jest najniższym wspólnym mianownikiem? – Massif

Powiązane problemy