Non mi piace particolarmente la risposta che ho digitato di seguito, perché penso che il lettore lo vedrà come "predica al coro" o come "qualche assurdità complessa", ma ho deciso di postare in ogni caso, nel caso in cui invita fruttuosi commenti-discussione.
Prima di tutto, può essere notevole capire che
let x : string option = Some(null)
è un valore valido, che indica la presenza (anziché assenza) di un valore (Alcuni anziché Nessuno), ma il valore è di per sé nullo. (Il significato di tale valore dipenderebbe dal contesto.)
Se siete alla ricerca di quello che vedo come il modello mentale 'giusto', va qualcosa di simile ...
L'intero concetto che "tutti i tipi di riferimento ammettono un valore" null "è uno degli errori più grandi e costosi di .Net e CLR. Se la piattaforma fosse stata ridefinita da zero oggi, penso che la maggior parte delle persone concorda sul fatto che i riferimenti non sono annullabili per impostazione predefinita e che occorrerebbe un meccanismo esplicito per l'attivazione di null. Così com'è oggi, ci sono centinaia, se non migliaia di API che prendono ad es. "string foo" e non voglio un valore nullo (ad es. genererebbe ArgumentNullException se hai passato null). Chiaramente questo è qualcosa di meglio gestito da un sistema di tipi. Idealmente, "stringa" significherebbe "non null" e per la minoranza di API che do desidera null, lo si scrive, ad es. "Nullable < string> pippo" o "Opzione < string> pippo" o qualsiasi altra cosa. Quindi è la piattaforma .Net esistente che è lo "strano" qui.
Molti linguaggi funzionali (come ML, una delle influenze principali di F #) lo hanno sempre saputo, e quindi hanno progettato i loro sistemi di tipi 'giusti', dove se si desidera ammettere un valore 'nullo', si usa un costruttore di tipi generici per segnalare esplicitamente dati che possono avere intenzionalmente 'asbence di un valore' come valore legale. In ML, questo è fatto con il tipo "t opzione" - "opzione" è una soluzione fine e generica a questo problema. Il nucleo di F # è compatibile (cross-compile) con OCaml, un dialetto ML, e quindi F # eredita questo tipo dal suo antenato ML.
Ma F # deve anche integrarsi con il CLR, e nel CLR, tutti i riferimenti possono essere nulli.F # tenta di camminare una linea un po 'bene, in quanto è possibile definire nuovi tipi di classi in F #, e per quei tipi, F # si comporterà ML-simile (e non facilmente ammettere nulla come valore):
type MyClass() = class end
let mc : MyClass = null // does not compile
tuttavia lo stesso tipo definito in un assembly C# ammetterà null come valore corretto in F #. (E F # consente ancora un back-door:.
let mc : MyClass = Unchecked.defaultof<_> // mc is null
per ottenere in modo efficace in tutto il normale sistema di F # tipo e accedere direttamente al CLR)
Questo è tutto cominciando a sembrare complicato, ma in fondo il sistema F # ti consente di programmare moltissimo F # nello stile 'ML', dove non devi mai preoccuparti di null/NullReferenceExceptions, perché il sistema di tipi ti impedisce di fare le cose sbagliate qui. Ma F # deve integrarsi bene con .Net, quindi tutti i tipi che provengono dal codice non F # (come 'string') continuano ad ammettere valori nulli, e quindi quando si programma con quei tipi si deve ancora programmare in modo difensivo come si fa normalmente il CLR. Riguardo a null, in effetti F # offre un rifugio dove è facile fare 'programmare senza nulla, come Dio ha voluto', ma allo stesso tempo interagire con il resto di .Net.
Non ho davvero risposto alla tua domanda, ma se segui la mia logica, allora non avresti fatto la domanda (o non l'avrei annullata, la MU di La Joshu da "Godel, Escher, Bach").
Non doveva essere in questo modo. Potrebbero aver mappato le funzioni CLR in "opzione" anziché "String" a meno che non siano state contrassegnate come non restituiscono mai nulla. E in .NET 4, le funzioni dovrebbero essere contrassegnate come tali. –
Mi piace questa risposta, un sacco di valore aggiunto per StackOverflow. – Benjol
Se solo potessi risposte "preferite". Ah bene. Qualunque cosa, se lo facessero, Grauren, avremmo un modello da incubo di tempo corrispondente a ogni 'opzione' che il framework sputa. Per fortuna, non ci sono molte funzioni che possono restituire valori nulli, quindi non devi essere troppo cauto. – YotaXP