2016-06-18 96 views
9

stavo cercando di definire un caso più generale per l'operatore (!) Come segue,F # la funzione di chiamata in linea con le variabili di tipo

let inline (!) (cell : ^a) = 
    (^a : (member Value : ^b) cell) 

in modo che funzioni non solo per ref tipo, ma qualsiasi tipo con un Value membro.

> !(ref 10) ;; 
val it : int = 10 

> !(lazy 5) ;; 
val it : int = 5 

Ma problema sorge quando si tenta di applicarlo a un tipo con le variabili di tipo,

> let getValue (c : 'a ref) = !c ;; 

    let getValue (c : 'a ref) = !c ;; 
    ------------------^^ 

C:\Users\User\AppData\Local\Temp\stdin(6,19): warning FS0064: This construct causes code to be less generic than indicated by the type annotations. The type variable 'a has been constrained to be type 'obj'. 

val getValue : c:obj ref -> obj 

mentre funziona bene se espando la funzione inline.

> let getValue (c : 'a ref) = c.Value ;; 

val getValue : c:'a ref -> 'a 

Qualcuno sa perché questo accade? Grazie.

risposta

5

Poiché la funzione non è in linea, i vincoli non funzioneranno.

Il problema è che il sistema di tipo .NET non può memorizzare il tipo di vincoli che F # può utilizzare in inline.

Di conseguenza, quando si dispone di una funzione non inline che utilizza una funzione inline in questo modo, si ottiene un errore.

+0

L'ultima versione di 'getValue' è solo un'espansione manuale della precedente versione, anche se, so che potrei mancare qualcosa qui, ma non riesco ancora a vedere come il primo introduce più vincoli di tipo rispetto a quest'ultimo che .NET può catturare – Doaz

+0

Penso che i vincoli su 'getValue' siano un superset dei vincoli su'! '. Dato che i vincoli su 'getValue' richiedono un vincolo in linea, non può essere una funzione non in linea –