Fsharp记录中的可选参数

Hes*_*han 4 f# records nullable properties

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

Ant*_*fer 7

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

另见这个密切相关的问题.

您可以考虑这种权衡:

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

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

我个人更喜欢唱片,因为它迫使我思考添加新领域的含义.

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

type Name = 
    { 
        First: string
        Family: string
    }        
    static member Create(first, family) = { First = first; Family = family}
Run Code Online (Sandbox Code Playgroud)

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


Fun*_*unk 5

选项类型优于F#中无效,原因很简单,即"未初始化变量"不思考的功能性的方式存在.

让我们从构建代表a的记录开始,该记录VacationRequest必须得到老板的批准.

type VacationRequest =
   {Name : string
    Date : DateTime
    Approval : string option}
Run Code Online (Sandbox Code Playgroud)

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

let holiday =
   {Name = "Funk"
    Date = DateTime(2020,12,31)}
Run Code Online (Sandbox Code Playgroud)

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

let fillInRequest name date =
   {Name = name 
    Date = date 
    Approval = None}
Run Code Online (Sandbox Code Playgroud)

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

let holiday = fillInRequest "Funk" <| DateTime(2020,12,31)
Run Code Online (Sandbox Code Playgroud)

在向FSI发送代码时注意到了一些有趣的事情.

val holiday : VacationRequest = {Name = "Funk";
                                 Date = 31/12/2020 12:00:00 ;
                                 Approval = null;}
Run Code Online (Sandbox Code Playgroud)

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

let approvedHoliday =
    {holiday with Approval = Some "boss' name"}
Run Code Online (Sandbox Code Playgroud)
val approvedHoliday : VacationRequest = {Name = "Funk";
                                         Date = 31/12/2020 12:00:00 ;
                                         Approval = Some "boss' name";}
Run Code Online (Sandbox Code Playgroud)

或者不加改变地发回去

let betterLuckNextTime = holiday
Run Code Online (Sandbox Code Playgroud)