fsprojects / FSharp.Data

F# Data: Library for Data Access
https://fsprojects.github.io/FSharp.Data
Other
816 stars 288 forks source link

Add Support For Copy-and-Update Record Expressions #914

Closed jon49 closed 8 years ago

jon49 commented 8 years ago

Currently the whole tree of the JSON must be updated when editing JSON items. It would be nice to be only update a single portion of a JSON value. larry shows the current way it must be created. george shows a proposed partial update way of updating a jsonprovider record.

#r @"..\..\packages\FSharp.Data.2.2.5\lib\net40\FSharp.Data.dll"
open FSharp.Data

type People = JsonProvider<""" { "fullName":{ "firstName":"John", "lastName":"Laffy"}, "age":94 } """>

let john = People.GetSample ()

let larry =
    let larry = People.FullName("Larry", "Laffy")
    let larry' =
        People.Root(fullName = larry, age = 10)
    larry'

let george =
    {john with FullName = {
        john.FullName with {
           FirstName = "George"}}}

This issue is raised due to my own desire and by suggestion of comment two in this answer on StackOverflow.

Any other suggestions or current practices would be appreciated.

tpetricek commented 8 years ago

Type providers cannot currently provide F# records, so we won't be able to get it to work with the with syntax.

I don't think there is any really good solution for this in F# currently, to be honest. I would like to be able to write something like:

let george = { john with FullName.FirstName = "George" }

But that would require (1) type providers that can provide records and (2) extension to F# that allows using with on nested properties.

There were various proposals for using lenses or zippers or whatnot, but I think none of those have the level of usability that we need for a main-stream library like F# Data.

So for now, I'm afraid we don't have a good solution - and my recommendation is to just write the (longer and not so fun) code to clone the two objects.

jon49 commented 8 years ago

I think I was trying to use this tool incorrectly. I was trying to use it as a shortcut for creating a Json-Schema type. Now, that I understand the use case for JsonProviders and its limitations I don't know if this will still be hurdle in the future or not. So, it would be nice to have but it appears that it is currently not possible.

Thanks for responding.

tpetriceck, Yes, it would be nice to write updates with nested properties like you wrote above!

ploeh commented 8 years ago

@tpetricek Is it still the case that F# type providers can't provide records?

I'm not implying that it's your responsibility, but I do know that you have insights into this field :smile:

I can live with the lack of lenses (I can glue that on myself), but I'd really like to be able to use copy-and-update expressions. Having to write out the entire copy code myself sort of defeats the purpose of type providers in the first place.

Is there a language feature suggestion about this somewhere?

MatthiasWeiser commented 8 years ago

Support Provided Union and Record Types is the related user voice issuer.

ploeh commented 8 years ago

Thank you, @MatthiasWeiser I'd like to vote, but I'm out of votes :disappointed:

tpetricek commented 8 years ago

@ploeh I voted for you :-)

I would love to have a good story for this, but I'm not sure what that would be at the moment. Lenses are good theory, but without decent syntax, it would take F# Data in a very different direction than the one it tries to follow currently.

We could emulate with keyword and provide something like:

let george =
    john.With(fullName = john.FullName.With(firstName = "George"))

I think this is as good as we can do without some nice with syntax extension.

jon49 commented 8 years ago

That would definitely make them more than read only. Especially if you could do multiple fields at one in the with method. Really, it would be almost equivalent, just different syntax, trading in the curlies for parans!

I up voted the issue too :+1:

jkone27 commented 3 years ago

This feature would be amazing! 😀