2009-06-03 15 views
9

Perché i tipi di opzione come "opzione int" non sono compatibili con i tipi nullable come "Nullable"?F #: perché i tipi di opzione non sono compatibili con i tipi nullable?

Suppongo che ci sia qualche motivo semantico per la differenza, ma non riesco a capire di cosa si tratta.

Un'opzione in F # viene utilizzata quando un valore può o non può esistere. Un'opzione ha un tipo sottostante e può contenere un valore di quel tipo o potrebbe non avere un valore.

http://msdn.microsoft.com/en-us/library/dd233245%28VS.100%29.aspx

che suona certo, come la struttura Nullable.

risposta

1

La differenza fondamentale è che deve verificare il tipo di opzione per vedere se ha un valore. Vedi questa domanda per una buona descrizione della sua semantica: How does the option type work in F#

+0

E allora? È possibile soddisfare tale requisito con il livello di sintassi languge e utilizzare ancora Nullable a livello di runtime. –

+0

A livello di runtime sono rappresentati utilizzando valori null. – Robert

+2

Sfortunatamente ti sbagli. Non è necessario controllare i tipi di opzioni per vedere se hanno un valore, puoi semplicemente chiamare l'opzione . Valore direttamente e spero che tu non ottenga un'eccezione. Non c'è nemmeno un avviso del compilatore se non si utilizza la corrispondenza del modello. –

0

Ancora una volta, questo è dalla mia comprensione limitata, ma il problema risiede probabilmente nel modo in cui ciascuno viene visualizzato nell'IL. La struttura "nullable" probabilmente viene gestita in modo leggermente diverso dal tipo di opzione.

Troverete che le interazioni tra vari linguaggi .Net si riducono davvero a come viene reso l'IL. La maggior parte delle volte funziona, ma a volte causa problemi. (check out this). Proprio quando pensavi che fosse sicuro fidarsi del livello di astrazione. :)

+1

Dei, quello spettatore è orribile. Bello articolo però ... – flatline

6

I due hanno semantica diversa. Solo per citarne uno, Nullable è un costruttore di dati idempotente che funziona solo sui tipi di valore, mentre l'opzione è un tipo generico normale. Quindi non si può avere un

Nullable<Nullable<int>> 

ma è possibile avere un

option<option<int>> 

In generale, anche se ci sono alcuni scenari che si sovrappongono, ci sono anche cose che si possono fare con una sola, ma non l'altro.

+0

Questo spiega perché non è possibile utilizzare Nullable > come rappresentazione runtime dell'opzione >. Ciò non spiega il motivo per cui non è possibile compatire l'opzione speciale con Nullable . –

+3

Questo caso speciale non mi sembra desiderabile. Perché vuoi che determinate istanze dell'opzione <'a> siano rappresentate da Nullable e non da altre? – Robert

+1

F # è già pieno di strani casi speciali. Ad esempio, qual è la differenza tra una "stringa" che prende un valore o null e una "opzione di stringa" che accetta un valore o un nessuno? –

14

A causa della scelta della rappresentazione runtime per System.Nullable<'T>.

Nullable tenta di rappresentare l'assenza di valori dal puntatore nullo e presenta i valori in base a tali valori.

(new System.Nullable<int>() :> obj) = null 
|> printfn "%b" // true 

(new System.Nullable<int>(1) :> obj).GetType().Name 
|> printfn "%s" // Int32 

Considerare ora le stringhe. Sfortunatamente, le stringhe sono annullabili. Quindi questo è valido:

null : string 

Ma ora un valore di null runtime è ambiguo - può riferirsi sia l'assenza di un valore o una presenza di un valore null. Per questo motivo, .NET non consente di costruire un System.Nullable<string>.

Contrasto questo con:

(Some (null : string) :> obj).GetType().Name 
|> printfn "%s" // Option`1 

Detto, si può definire una biiezione:

let optionOfNullable (a : System.Nullable<'T>) = 
    if a.HasValue then 
     Some a.Value 
    else 
     None 

let nullableOfOption = function 
    | None -> new System.Nullable<_>() 
    | Some x -> new System.Nullable<_>(x) 

Se si osservano i tipi, queste funzioni vincolare 'T essere una struttura ed avere un costruttore di argomenti zero. Quindi, forse compilatore F # potrebbe esporre le funzioni .NET ricezione/ritorno Nullable<'T> sostituendo per un Option<'T where 'T : struct and 'T : (new : unit -> 'T)>, e inserendo le funzioni di conversione se necessario ..

+4

Questo non è vero. 'Nullable ' è una struct e, come tale, il suo valore nullo non può essere rappresentato dal puntatore nullo. Piuttosto, i casi speciali del compilatore C# il tipo 'Nullable ', che consente di utilizzare il valore letterale null; ovviamente non è lo stesso che consente alla variabile di contenere un puntatore nullo. La struttura nullable ha un campo booleano "ha valore"; il compilatore C# converte i confronti con il valore letterale null alle chiamate alla proprietà HasValue. Il runtime tratta anche l'operazione * boxing *, ed è per questo che il tuo primo esempio funziona come previsto. – phoog

+0

Grazie per la correzione, buono a sapersi! – t0yv0

+0

Aspetta un secondo. È 'Opzione ' che rappresenta l'assenza di valori dal puntatore nullo. Se cerchi la definizione di Option.Non è letteralmente solo 'null'. –

Problemi correlati