为什么像"int option"这样的选项类型不兼容像Nullable这样的可空类型?
我假设存在差异的一些语义原因,但我无法弄清楚那是什么.
当值可能存在或不存在时,使用F#中的选项.选项具有基础类型,可以包含该类型的值,也可以没有值.
http://msdn.microsoft.com/en-us/library/dd233245%28VS.100%29.aspx
这肯定听起来像Nullable结构.
t0y*_*yv0 17
由于运行时表示选择System.Nullable<'T>.
Nullable尝试通过空指针表示缺少值,并通过指向这些值的指针来显示值.
(new System.Nullable<int>() :> obj) = null
|> printfn "%b" // true
(new System.Nullable<int>(1) :> obj).GetType().Name
|> printfn "%s" // Int32
Run Code Online (Sandbox Code Playgroud)
现在考虑字符串.不幸的是,字符串可以为空.所以这是有效的:
null : string
Run Code Online (Sandbox Code Playgroud)
但是现在null运行时值是不明确的 - 它可以指缺少值或存在null值.出于这个原因,.NET不允许构造一个System.Nullable<string>.
与此对比:
(Some (null : string) :> obj).GetType().Name
|> printfn "%s" // Option`1
Run Code Online (Sandbox Code Playgroud)
话虽这么说,人们可以定义一个双射:
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)
Run Code Online (Sandbox Code Playgroud)
如果观察类型,则这些函数约束'T为结构并具有零参数构造函数.因此,也许F#编译器可以Nullable<'T>通过替换它来接收/返回.NET函数Option<'T where 'T : struct and 'T : (new : unit -> 'T)>,并在必要时插入转换函数.
两者有不同的语义.仅举一例,Nullable是一个幂等数据构造函数,仅适用于值类型,而option是普通泛型类型.所以你不能拥有
Nullable<Nullable<int>>
Run Code Online (Sandbox Code Playgroud)
但你可以有一个
option<option<int>>
Run Code Online (Sandbox Code Playgroud)
一般来说,虽然有一些重叠的场景,但你也可以用一个而不是另一个做.
主要区别在于必须测试选项类型以查看它是否具有值。有关其语义的详细描述,请参阅此问题:How does the option type work in F#