Fsharp记录中的可选参数

时间:2017-03-23 06:40:30

标签: properties f# nullable records

我需要为我的F Sharp记录修改和添加新属性。但是它会为之前没有这个新字段的实例提供错误。我把它设为Nullable,但仍然出现同样的错误,请帮我解决这个问题

2 个答案:

答案 0 :(得分:7)

我认为你的意思是"可选"就像在"在实例化记录时我不提供的字段"。但是,遗憾的是,F#记录中没有可选字段(或者幸运的是,取决于您的观点)。您指定的所有记录字段必须出现在实例化时。

另见this closely related question

您可以考虑这种权衡:

  • 使用记录。每次更新记录时,F#编译器都会尖叫并提醒您使用此记录的所有位置,并且您现在需要提供其他信息。对于您添加的字段,附加信息可以是None,如果它们是选项。最大的优势:您的代码本身不必处理所有可能的情况,如果缺少field1该怎么办?如果缺少field2该怎么办?"

  • 使用。更新类时,F#编译器不会对您放入类中的信息执行任何类型的完整性检查。 (您可以将记录视为所有字段都是构造函数参数的类,并且必须提供所有字段)。因此,更新类定义不会产生任何开销,但是您的代码需要处理所有缺少的值。

我个人更喜欢唱片只是因为它强迫我思考添加新字段的含义。

当然有一个中间立场:您可以使用记录,但通过静态成员或类似的东西实例化所有记录:

type Name = 
    { 
        First: string
        Family: string
    }        
    static member Create(first, family) = { First = first; Family = family}

如果在您的代码中,您始终使用Name.Create来实例化记录,那么您当然可以添加MiddleName字段而无需任何消费者代码注意。

答案 1 :(得分:5)

Option type优于F#中的null,原因很简单,“未初始化的变量”在功能思维方式中不存在。

让我们首先构建一个代表VacationRequest的记录,该记录必须得到老板的批准。

type VacationRequest =
   {Name : string
    Date : DateTime
    Approval : string option}

您的方法存在的问题是所有字段都必须在构造时分配,因此无法编译:

let holiday =
   {Name = "Funk"
    Date = DateTime(2020,12,31)}

您可以使用辅助函数解决此问题,该函数隐式设置选项值。

let fillInRequest name date =
   {Name = name 
    Date = date 
    Approval = None}

现在您可以使用辅助函数构建记录。

let holiday = fillInRequest "Funk" <| DateTime(2020,12,31)

将代码发送给FSI时,注意到了一些有趣的事情。

val holiday : VacationRequest = {Name = "Funk";
                                 Date = 31/12/2020 12:00:00 ;
                                 Approval = null;}

然后老板可以更新请求(创建记录)

let approvedHoliday =
    {holiday with Approval = Some "boss' name"}
val approvedHoliday : VacationRequest = {Name = "Funk";
                                         Date = 31/12/2020 12:00:00 ;
                                         Approval = Some "boss' name";}

或以不加改变的方式发回

let betterLuckNextTime = holiday