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