Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow change generic types in with expressions #1292

Closed
5 tasks done
lucasteles opened this issue Jul 20, 2023 · 3 comments
Closed
5 tasks done

Allow change generic types in with expressions #1292

lucasteles opened this issue Jul 20, 2023 · 3 comments

Comments

@lucasteles
Copy link

When working with large generic data structures and we need to copy all data but change some generic type field to another type we can't use with and have to explicitly copy each field of the record. eg:

type Foo<'t> = {
  A: int
  B: 't
  C: string
}

let fooInt = { A = 1; B = 2; C = "foo" }

// do not compile 
let fooString = { fooInt with B = "three" } 

I believe this makes sense, just changing the type would look dangerous. But I think we could have some way to do this when wanted:

let fooString = { fooInt with B<string> = "three" } 

// or also 
let fooString = { fooInt with B<_> = "three" } 

The existing way of approaching this problem in F# is

Explicitly set each field without with

let fooString = { A = fooInt.A; B = "three"; C = fooInt.C }

Pros and Cons

The advantages of making this adjustment to F# are
easier data structure manipulation

The disadvantages of making this adjustment to F# are
add complexity to the syntax

Extra information

**Estimated cost (XS, S, M, L, XL, XXL): ?

Related suggestions:

Affidavit (please submit!)

Please tick this by placing a cross in the box:

  • This is not a question (e.g. like one you might ask on stackoverflow) and I have searched stackoverflow for discussions of this issue
  • I have searched both open and closed suggestions on this site and believe this is not a duplicate
  • This is not something that has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it.

Please tick all that apply:

  • This is not a breaking change to the F# language design
  • I or my company would be willing to help implement and/or test this

For Readers

If you would like to see this issue implemented, please click the 👍 emoji on this issue. These counts are used to generally order the suggestions by engagement.

@smoothdeveloper
Copy link
Contributor

Another workaround:

type Foo<'t> = 
  {
    A: int
    B: 't
    C: string
  }
  static member mapB f x = { A = x.A; B = f x.B; C = x.C }

let fooInt = { A = 1; B = 2; C = "foo" }
let fooString = Foo.mapB (fun _ -> "three") fooInt 

I agree it would feel natural, but I'm concerned about people inadvertently changing the type, and I'm not convinced with the generic parameter adorned to the field name.

let fooString : Foo<string> = { fooInt with B = "three" } 
let fooString : Foo<_> = { fooInt with B = "three" } 

Maybe this would be better, without changing the grammar?

@realparadyne
Copy link

This feels very related to the already approved-in-principle spread operator. #1253

You want to take what you can from the existing record but provide a new value for one (or more) of the fields and if those are of a different type, then the newly produced record is of a suitable type (anonymous or not).

It just sounds like a specific case that the spread operator will be needing to support and may already be intended.

@lucasteles
Copy link
Author

Closing in favor of #1253

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants