【问题标题】:Cross-type record with statements in F#?F# 中带有语句的跨类型记录?
【发布时间】:2020-05-06 14:17:26
【问题描述】:

以下代码无法编译:

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,
};

【问题讨论】:

    标签: types f# record


    【解决方案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# 中,为类型建模的方式非常重要,并且会对所有使用它的代码产生连锁反应。因此,如果您的代码看起来很不稳定,请考虑是否可以改进您的类型。

    【讨论】:

    • 我不认为静态类型使这成为不可能,类型检查器只需要意识到一种记录类型中的字段是另一种记录类型的超集。 F# 不这样做的事实回答了我的问题。
    • 我同意 sdgfsdh。这不是静态类型的问题,Typescript 毕竟是静态类型的。 Typescript 使用结构类型,因此如果某些类型拥有其他类型的所有成员,则它们可以是其他类型的子类型。 F# 有结构上的平等,所以呃,你赢了一些,你输了一些。
    • @Asti 我并没有说这是不可能的,因为 F# 是静态类型的,只是它不符合语言的设计和使用方式。我不想谈太多细节,但您指出 TypeScript 具有结构类型。 F# 具有标称类型,因此很难以与所有现有功能良好交互的方式添加此功能。
    • @TheQuickBrownFox 这是一个合理的位置。 OCaml 在结构上是类型化的,但我猜 F# 名义上是为互操作而类型化的。可以期待记录类型的结构类型化的未来实现,这将使处理匿名记录更容易。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-19
    • 2011-05-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-17
    • 2021-01-19
    • 1970-01-01
    相关资源
    最近更新 更多