记录F#的变化

Dax*_*ohl 10 f# type-providers

我想要一些方法来定义相关记录.例如,

type Thing       = { field1: string; field2: float }
type ThingRecord = { field1: string; field2: float; id: int; created: DateTime }
Run Code Online (Sandbox Code Playgroud)

要么

type UserProfile = { username: string; name: string; address: string }
type NewUserReq  = { username: string; name: string; address: string; password: string }
type UserRecord  = { username: string; name: string; address: string; encryptedPwd: string; salt: string }
Run Code Online (Sandbox Code Playgroud)

以及从一个转换到另一个的方式,而不需要写那么多样板文件.即使是第一个完整的例子也是:

type Thing =
  { field1: string
    field2: float }
  with
    member this.toThingRecord(id, created) =
      { field1 = this.field1
        field2 = this.field2
        id = id
        created = created } : ThingRecord
and ThingRecord =
  { field1: string
    field2: float
    id: int
    created: DateTime }
  with
    member this.toThing() =
      { field1 = this.field1
        field2 = this.field2 } : Thing
Run Code Online (Sandbox Code Playgroud)

当你起床field10等时,它将成为一种负担.

我目前使用反射以不安全(和缓慢)的方式执行此操作.

我添加了一个with语法请求,以扩展到uservoice上的记录定义,这将满足这一需求.

但是,是否有一种类型安全的方法可以做到这一点?也许与类型提供商?

scr*_*wtp 5

是的,这是F#否则有光泽的装甲的缺点。我觉得没有一个通用的解决方案可以轻松地继承或扩展记录。毫无疑问,是一个胃口-我数了崇尚沿着这些路线的改进十几UserVoice的提交-这里有几个领头的人,随意投票了:12345

当然,您可以采取一些措施来解决此问题,并且根据您的情况,它们可能对您很有用。但最终-它们是解决方法,您必须牺牲一些东西:

  • 使用反射时的速度和类型安全性
  • 简单地说,当您走类型安全的道路并拥有完整的记录以及它们之间的转换功能时,
  • 当您决定退回到普通的.NET类和继承时,记录提供的所有语法和语义优势都是免费的。

类型提供者不会削减它,因为它们并不是元编程真正的好工具。那不是他们设计的目的。如果尝试以这种方式使用它们,那么必然会遇到一些限制。

首先,您只能提供基于外部信息的类型。这意味着,尽管您可以使用类型提供程序通过反射从.NET程序集中提取类型并提供一些基于该类型的派生类型,但您不能“全面了解”正在构建的程序集。因此,无法从同一程序集中先前定义的类型派生任何方法。

我想您可以通过围绕类型提供程序构建项目来解决此问题,但这听起来很笨拙。即使如此,你不能提供记录类型反正还没有,所以最好你可以做的是纯.NET类。

对于为数据库提供某种ORM映射的更特定的用例,我想您可以使用类型提供程序就好了。只是不作为通用元编程工具。