sdgfsdh
sdgfsdh

Reputation: 37045

Cross-type record with statements in F#?

The following code does not compile:

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
  }

A work-around is to write a helper, perhaps like so:

let toEmployee (p : Person) : Employee = 
  {
    FirstName = p.FirstName
    LastName = p.LastName
    Salary = Unchecked.defaultof<_>
  }

let e : Employee = 
  {
    toEmployee p with Salary = 1
  }

But this is a bit tedious.

Does F# offer a better way?

This is a common thing to do in JavaScript, for example:

const e = {
  ...p,
  salary: 1,
};

Upvotes: 2

Views: 72

Answers (1)

TheQuickBrownFox
TheQuickBrownFox

Reputation: 10624

As a statically and nominally typed language this is not possible in F# and this is by intentional design.

Supposing you did have that feature like the JS and a value let e = {...p; Salary = 1}. Then suppose you rename a field on Person. What should the type of e be inferred to? What should the error message say? There aren't easy answers to this question, and it could become very complicated and hard to understand very fast in a larger codebase.

It's better to write out the new record manually. It's a bit more verbose but it fits the general F# theme of being more explicit in some dimensions, so that you can be less specific with annotating types (allowing more type inference). If you could be very implicit with both then it would create an explosion of complexity.


Another option which might help here is to change your model to put repeated fields into a separate type:

type Person = 
  { FirstName : string
    LastName : string }

type Employee = 
  { Person : Person
    Salary : int }

let p = 
  { FirstName = "Steve"
    LastName = "Jobs" }

let e = { Person = p; Salary = 1 }

In F# the way you model your types is very important and has a knock on effect on all of the code that uses it. So if your code seems wonky, consider if your types could be improved.

Upvotes: 4

Related Questions