2009-06-03 14 views
9

¿Por qué los tipos de opciones como "opción int" no son compatibles con tipos anulables como "Nullable"?F #: ¿Por qué los tipos de opciones no son compatibles con los tipos que aceptan nulos?

Supongo que hay alguna razón semántica para la diferencia, pero no sé qué es eso.

Se usa una opción en F # cuando un valor puede existir o no. Una opción tiene un tipo subyacente y puede contener un valor de ese tipo o puede no tener un valor.

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

Eso suena la estructura anulables.

Respuesta

1

La diferencia clave es que debe probar el tipo de opción para ver si tiene un valor. Vea esta pregunta para una buena descripción de su semántica: How does the option type work in F#

+0

¿Y qué? Puede hacer ese requisito en el nivel de sintaxis de languge y seguir usando Nullable en el nivel de tiempo de ejecución. –

+0

En el nivel de tiempo de ejecución, se representan utilizando valores nulos. – Robert

+2

Lamentablemente está equivocado. No necesita verificar los tipos de opciones para ver si tienen un valor, simplemente puede llamar a la Opción .Value directamente y esperar que no obtenga una excepción. Ni siquiera hay una advertencia del compilador si no usa la coincidencia de patrones. –

0

Una vez más, esto es de mi entendimiento limitado, pero el problema probablemente radique en cómo se renderiza cada uno en la IL. La estructura "anulable" probablemente se maneje ligeramente diferente del tipo de opción.

Encontrará que las interacciones entre varios lenguajes .Net realmente se reducen a cómo se renderiza el IL. La mayoría de las veces funciona bien, pero en ocasiones causa problemas. (check out this). Justo cuando creía que era seguro confiar en el nivel de abstracción. :)

+1

Ye dioses, ese espectador es horrible. Buen artículo, aunque ... – flatline

6

Los dos tienen una semántica diferente. Solo para nombrar uno, Nullable es un constructor de datos idempotentes que solo trabaja en tipos de valores, mientras que la opción es un tipo genérico normal. Así que no se puede tener un

Nullable<Nullable<int>> 

pero puede tener un

option<option<int>> 

general, sin embargo hay algunos escenarios superpuestos, también hay cosas que puede hacer con uno pero no el otro.

+0

Eso explica por qué no puede usar Nullable > como la representación en tiempo de ejecución de la opción >. Eso no explica por qué no se puede hacer compatible la opción de caso especial con Nullable . –

+3

Tal caso especial no me parece deseable. ¿Por qué querría que ciertas instancias de la opción <'a> se representen con Nullable y otras no? – Robert

+1

F # ya está lleno de extraños casos especiales. Por ejemplo, ¿cuál es la diferencia entre una "cadena" que toma un valor o nulo y una "opción de cadena" que toma un valor o ninguno? –

14

Debido a la opción de representación en tiempo de ejecución para System.Nullable<'T>.

Nullable intenta representar la ausencia de valores por el puntero nulo, y presentar los valores por punteros a esos valores.

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

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

Considere las cadenas. Desafortunadamente, las cadenas son nulables. Así que esto es válido:

null : string 

Pero ahora un valor null tiempo de ejecución es ambigua - se puede hacer referencia a la ausencia de un valor o una presencia de un valor null. Por esta razón, .NET no permite construir un System.Nullable<string>.

Contraste esto con:

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

Dicho, se puede definir una biyección:

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) 

Si usted observa los tipos, estas funciones restringir 'T a ser una estructura y tienen un constructor de cero argumentos Entonces, quizás el compilador F # podría exponer las funciones .NET que reciben/devuelven Nullable<'T> sustituyéndolas por un Option<'T where 'T : struct and 'T : (new : unit -> 'T)>, e insertando las funciones de conversión cuando sea necesario.

+4

Esto no es verdad. 'Nullable ' es una estructura y, como tal, su valor nulo no puede representarse mediante el puntero nulo. Por el contrario, el compilador C# casos especiales el tipo 'Nullable ', que le permite utilizar el literal nulo; eso por supuesto no es lo mismo que permitir que la variable tenga un puntero nulo. La estructura nullable tiene un campo booleano "tiene valor"; el compilador de C# convierte las comparaciones con el literal nulo en llamadas a la propiedad HasValue. El tiempo de ejecución también trata la operación * boxing * especialmente, por lo que su primer ejemplo funciona como se esperaba. – phoog

+0

¡Gracias por la corrección, es bueno saber! – t0yv0

+0

Espera un segundo. Es 'Opción ' que representa la ausencia de valores por el puntero nulo. Si busca la definición de Option.None, literalmente es 'null'. –

Cuestiones relacionadas