No me gusta particularmente la respuesta que he escrito a continuación, porque creo que el lector la verá como 'predicando al coro' o como 'una tontería compleja', pero he decidido publicar de todos modos, en caso de que invite a comentarios fructíferos-discusión.
En primer lugar, puede ser digno de mención que entender que
let x : string option = Some(null)
es un valor válido, que indica la presencia (en vez de la ausencia) de un valor (algunos más que ninguno), pero el valor en sí es nulo. (El significado de un valor tal que dependerá del contexto.)
Si usted está buscando lo que veo como el modelo 'correcto' mental, que es algo como esto ...
Toda la noción de que "todos los tipos de referencia admiten un valor 'nulo'" es uno de los mayores y más costosos errores de .Net y CLR. Si hoy se reescribió la plataforma desde cero, creo que la mayoría de la gente está de acuerdo en que las referencias no se pueden anular por defecto, y usted necesitaría un mecanismo explícito para optar por nulo. Tal como está hoy, hay cientos, sino miles de API que toman, por ejemplo, "string foo" y no quiere un nulo (por ejemplo, arrojaría ArgumentNullException si pasaba null). Claramente esto es algo mejor manejado por un sistema de tipo. Idealmente, 'cadena' significaría 'no nulo', y para la minoría de APIs que do quieren nula, se escribe eso a cabo, por ejemplo, "Nullable < cadena> foo" o "Opción < cadena> foo" o lo que sea. Entonces, es la plataforma .Net existente la que es el 'bicho raro' aquí.
Muchos lenguajes funcionales (como ML, una de las principales influencias de F #) lo han sabido siempre, por lo que diseñaron sus sistemas tipo 'derecho', donde si quiere admitir un valor 'nulo', usa un constructor de tipo genérico para señalar explícitamente datos que intencionalmente pueden tener 'asbence of a value' como valor legal. En ML, esto se hace con el tipo "t opción" - 'opción' es una solución fina y de propósito general para este problema. El núcleo de F # es compatible (compilaciones cruzadas) con OCaml, un dialecto ML, y así F # hereda este tipo de su ascendencia ML.
Pero F # también tiene que integrarse con el CLR, y en el CLR, todas las referencias puede ser nulo.F # intenta caminar una línea algo bien, en el que puede definir nuevos tipos de clases en C#, y para aquellos tipos, F # se comportará ML-como (y no es fácil admitir null como un valor):
type MyClass() = class end
let mc : MyClass = null // does not compile
embargo el mismo tipo definido en un conjunto C# admitirá nulo como un valor adecuado en F #. (Y F # permite aún una puerta trasera:.
let mc : MyClass = Unchecked.defaultof<_> // mc is null
para conseguir eficacia en todo el sistema F # tipo normal y acceder al CLR directamente)
Todo esto está empezando a sonar complicado, pero básicamente el sistema de F # te permite programar un montón de F # en el estilo 'ML', donde nunca tendrás que preocuparte por null/NferentReferenceExceptions, porque el sistema de tipos te impide hacer las cosas incorrectas aquí. Pero F # tiene que integrarse muy bien con .Net, por lo que todos los tipos que se originan en código no F (como 'cadena') todavía admiten valores nulos, por lo que cuando programe con esos tipos, debe programar tan defensivamente como lo hace normalmente. el CLR. Con respecto a nulo, efectivamente F # proporciona un refugio donde es fácil hacer 'programación sin nulo, de la manera que Dios lo pensó', pero al mismo tiempo interoperar con el resto de .Net.
No he respondido realmente a su pregunta, pero si sigue mi lógica, entonces no haría la pregunta (o no lo haría, al estilo de Joshu de "Godel, Escher, Bach").
No tenía que ser así. Podrían haber mapeado funciones CLR a "opción" en lugar de "Cadena" a menos que estuvieran marcadas como nunca devuelven nulo. Y en .NET 4, se supone que las funciones deben estar marcadas como tales. –
Me gusta esta respuesta, un gran valor agregado para StackOverflow. – Benjol
Si tan solo pudiera dar respuestas 'favoritas'. Ah bueno. Anywho, si hicieran eso, Grauren, tendríamos una pesadilla de un patrón de tiempo que coincidiera con cada 'opción' que el marco escupiera. Afortunadamente, no hay tantas funciones que puedan devolver valores nulos, por lo que no tiene que ser demasiado cauteloso. – YotaXP