F#:为什么选项类型与可空类型不兼容?

时间:2009-06-03 20:23:22

标签: f# null

为什么像“int option”这样的选项类型不兼容像Nullable这样的可空类型?

我认为差异有一些语义上的原因,但我无法弄清楚那是什么。

  

当值可能存在或不存在时,使用F#中的选项。选项具有基础类型,可以保留该类型的值,也可以没有值。

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

这肯定听起来像Nullable结构。

4 个答案:

答案 0 :(得分:16)

由于System.Nullable<'T>的运行时表示选择。

Nullable尝试通过空指针表示缺少值,并通过指向这些值的指针显示值。

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

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

现在考虑字符串。不幸的是,字符串可以为空。所以这是有效的:

null : string

但现在null运行时值不明确 - 它可以指缺少值或存在null值。因此,.NET不允许构造System.Nullable<string>

与此对比:

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

即说,可以定义一个双射:

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)

如果观察类型,这些函数将'T约束为结构并具有零参数构造函数。所以也许F#编译器可以通过替换Nullable<'T>来公开接收/返回Option<'T where 'T : struct and 'T : (new : unit -> 'T)>的.NET函数,并在必要时插入转换函数。

答案 1 :(得分:6)

两者有不同的语义。仅举一例,Nullable是一个幂等数据构造函数,仅适用于值类型,而option是普通泛型类型。所以你不能拥有

Nullable<Nullable<int>>

但你可以有一个

option<option<int>>

一般来说,虽然有一些重叠的场景,但也有一些你可以用一个而不是另一个做。

答案 2 :(得分:1)

关键区别在于必须测试选项类型以查看它是否具有值。有关其语义的详细说明,请参阅此问题:How does the option type work in F#

答案 3 :(得分:0)

同样,这是我有限的理解,但问题可能在于每个如何在IL中呈现。 “可空”结构可能与选项类型略有不同。

你会发现各种.Net语言之间的相互作用实际上归结为IL的呈现方式。大部分时间它工作得很好,但偶尔会导致问题。 (check out this)。就在你认为相信抽象层次是安全的时候。 :)