为什么F#记录不允许具有AllowNullLiteralAttribute?

时间:2009-12-06 19:34:01

标签: f# attributes nullable record

是否存在编译器实现的原因,为什么记录不能具有AllowNullLiteralAttribute属性或者这是一个选定的约束?

我确实看到这种约束强制清除代码有时但不总是。

[<AllowNullLiteralAttribute>]
type IBTreeNode = {
    mutable left : IBTreeNode; mutable right : IBTreeNode; mutable value : int}
with
    member this.Insert x =
        if x < this.value then
            if this.left = null then
                this.left <- {left = null; right = null; value = x}
            else
                this.left.Insert x
        else
            if this.right = null then
                this.right <- {left = null; right = null; value = x}
            else
                this.right.Insert x

// Would be a lot of boilerplate if I wanted these public
[<AllowNullLiteralAttribute>]
type CBTreeNode(value) = 
    let mutable left = null
    let mutable right = null
    let mutable value = value
with
    member this.Insert x =
        if x < value then
            if left = null then
                left <- CBTreeNode(x)
            else
                left.Insert x
        else
            if right = null then
                right <- CBTreeNode(x)
            else
                right.Insert x

为可变性人群添加了一个不可变版本。在这种情况下,它快了大约30%。

type OBTree =
    | Node of OBTree * OBTree * int
    | Null
with
    member this.Insert x =
        match this with
        | Node(left, right, value) when x <= value -> Node(left.Insert x, right, value)
        | Node(left, right, value) -> Node(left, right.Insert x, value)
        | Null -> Node(Null, Null, x)

2 个答案:

答案 0 :(得分:3)

我只能冒险猜测,但语言似乎采取的态度是null的使用是可以避免的(如果你需要这个功能,你总是可以使用option类型)因此null的使用实际上应该限于与其他.NET语言互操作。因此,F#特定类型不允许使用null

答案 1 :(得分:2)

嗯,记录被翻译成标准的.NET类,就像其他结构一样,所以我没有看到技术原因。

我猜这个决定是相当哲学的 - Null值是未初始化的,未定义的值,在有状态计算中被取代的东西。在F#等功能上下文中应避免这些。

所以我认为记录类型,作为“功能构造”(不是标准的.NET兼容)并不意味着携带这样的无功能数据,但用户需要手动编码(`选项类型等)。

这也可以让您了解您的代码,例如检查所有可能值的模式匹配,而不存在必须处理null值的潜在危险。

关于你的代码:你真的要求它是必要的吗?

怎么样?
data Tree = 
    | Node of int * Tree * Tree
    | Nil