Search code examples
f#functor

Generics in record "with" syntax


If I've got a record with a generic field, is there any way to mimic the convenient with syntax when changing the generic?

i.e. if I have

type User<'photo> = // 'photo can be Bitmap or Url
  { first: string; last: string; address: string; phone: string; photo: 'photo }

I want to be able to write something like

let loadUser(user: User<Url>): User<Bitmap> =
  { user with
    photo = download user.photo }

But it looks like I've got to write this instead.

let loadUser(user: User<Url>): User<Bitmap> =
  { first = user.first
    last = user.last
    address = user.address
    phone = user.phone
    photo = download user.photo }

Is there a way to get the first syntax?


Solution

  • not directly but you can make your User into a functor (for the photo part):

    let fmap (f : 'a -> 'b) (user: User<'a>): User<'b> =
      { first   = user.first
        last    = user.last
        address = user.address
        phone   = user.phone
        photo   = f user.photo }
    

    once and write (for example):

    let loadUser (user : User<Url>) : User<Bitmap> =
        fmap download user
    

    also you could rename fmap into withPhoto if you prefer let loadUser = withPhoto download :D

    now it might be a bit strange that the photo part is any kind of data/type so I would think about renamig this part just into value - but that's just me