以下代码无法编译:
type Person =
{
FirstName : string
LastName : string
}
type Employee =
{
FirstName : string
LastName : string
Salary : int
}
let p : Person =
{
FirstName = "Steve"
LastName = "Jobs"
}
let e : Employee =
{
p with Salary = 1
}
一种解决方法是编写一个助手,也许像这样:
let toEmployee (p : Person) : Employee =
{
FirstName = p.FirstName
LastName = p.LastName
Salary = Unchecked.defaultof<_>
}
let e : Employee =
{
toEmployee p with Salary = 1
}
但是这有点乏味。
F#提供了更好的方法吗?
例如,这在JavaScript中是很常见的事情:
const e = {
...p,
salary: 1,
};
作为静态类型的语言,这在F#中是不可能的,这是有意设计的。
假设您确实具有该功能,例如JS和值let e = {...p; Salary = 1}
。然后,假设您重命名Person
上的字段。应该推断e
的类型是什么?错误消息应该怎么说?这个问题没有简单的答案,在更大的代码库中,它可能变得非常复杂且难以快速理解。
最好手动写出新记录。它稍微冗长一些,但符合F#的一般主题,即在某些维度上更加明确,因此您可以在注释类型上不那么具体(允许更多类型推断)。如果您可能对两者都非常含蓄,那么这将造成复杂性激增。
另一个可能在这里有用的选项是更改模型以将重复的字段放入单独的类型:
type Person =
{ FirstName : string
LastName : string }
type Employee =
{ Person : Person
Salary : int }
let p =
{ FirstName = "Steve"
LastName = "Jobs" }
let e = { Person = p; Salary = 1 }
在F#中,对类型进行建模的方式非常重要,并且会影响所有使用该类型的代码。因此,如果您的代码看上去很奇怪,请考虑是否可以改进您的类型。