types - F# 中带有语句的跨类型记录?
问题描述
以下代码无法编译:
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 和 value 之类的功能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# 中,为类型建模的方式非常重要,并且会对所有使用它的代码产生连锁反应。因此,如果您的代码看起来很不稳定,请考虑是否可以改进您的类型。
推荐阅读
- excel - n 值的质数
- .htaccess - 编写 htaccess 以隐藏 html 文件扩展名 + 使 http 转到 https + 使 xyz.com 转到 www.xyz.com
- bash - 我们可以在另一个 elseif 条件上使用一个 if 循环条件中提供的变量值吗
- regex - Apache CouchDB v2.3.1 上的 Mango Query 是否支持正则表达式选择器中的 \D 字符
- sqlalchemy - 无法使用 SQLALchemy 连接到 SQL Server
- flutter - flutter_bloc 子小部件关闭父小部件的块
- excel - 您是否需要将工作簿和工作表都传递给子/函数
- javascript - 如何在 JS 中将构造函数转换为类声明
- node.js - Axios 发布请求正文只是服务器端的一个空对象(React - Axios - Node.js - Express)
- javascript - CSS中的条纹元素样式设置