-
Notifications
You must be signed in to change notification settings - Fork 21
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
Nested field update syntax for records #379
Comments
Another possible alternative to this is to enable type providers to receive declared types see here. In theory then it might be possible to enable something like the following.
then with an accompanying Lens library along side the provider you could have the following
Or something similar. Of course the effectiveness of this option depends what limitations are in place for the type provider RFC. |
I understand the reasoning behind this: let a = { a with B.C = c } It's simple syntactic sugar to avoid doing this a lot: let a = { a with B = { a.B with C = c }}} It makes sense to me. However, I think introducing, I'm happy without using something like this because I would just create separate functions that update the specific parts then call them together. That way it is even more clear of what's going on. |
Len's are also currently generated by Myriad in one of the built-in plugins: https://moiraesoftware.github.io/myriad//how-tos/lenses.html |
I'm closing this for the reasons described well here: #379 (comment) |
I've discussed this with @vzarytovskii and will rename this suggestion to follow the limited suggestion here: #379 (comment) and mark it approved in principle. The suggestion does however leave a number of "unresolved questions" which people might want to work on
Ideally these would play well. But still the addition is a good one for the case where it's "records all the way down" and doesn't make the problems above fundamentally worse as they already apply to the "with" construct anyway. |
Implemented in |
Updated to cover only the suggestion that
be equivalent to
and corresponding for anonymous records and further nesting.
When working with complex state structures, functional programming is, without a great deal of additional tooling (tooling that does not satisfactorily exist in F#), highly inconvenient, verbose, and even error-prone. These problems are so pronounced that many cite them as a reason to label functional programming itself as inapplicable to the domains within which complex state structures are inherent!
As functional programmers, we believe otherwise, and many even believe that it is in the domain of dealing with complex state artifacts that functional programming is especially beneficial and necessary! However, with such weak syntactic constructs such as these -
we win ourselves no favors. And even in the narrow context of such a small problem, simple and promising solutions abound. For example, why doesn't this syntax have a semantics assigned to it in F#? -
Or better, given that we know at compile-time that there is a means of constructing A and B, why we can't assign a semantics to this -
and generate all the backing code for such a pure functional update automatically? And why restrict such nice syntax to only record fields? Why not let it be applicable to all members who support the concept of readability and updatability (EG - lensability) such as with here -
so that we can finally utter -
In other words, why not give the compiler some way of recognizing 'lensability' implicitly for simple cases (and perhaps explicitly with simple declarations in more refined cases such as with Map values), ultimately enabling good syntax to take advantage of it all? And yes, there have been library solutions to the problem of lensing proposed in F#. However, in experience I have found the library solution to be embarrassingly inadequate. This is due to the fact that F# does not provide out-of-the-box (nor shall it in the reasonably near-future) the language constructs necessary to build a sufficiently expressive lens library... and not even for the straight-forward use cases I outlined above! And, even if such language constructs were available, I still doubt that a form of expression as understandable and succinct as the syntax I proposed could be achieved.
For that reason, I did and still do conclude that it is necessary to build lensing as a first class construct in the language. This is so that instead of attempting to use kindedness to express lensing, the simpler (and admittedly more muscled) approaches of syntactic expansion / IL generation may be used. Thus this user suggestion.
(On a side note, perhaps if we had a sophisticated and general syntactic macro system in F# like I suggested here - archive/suggestion-5674940-implement-syntactic-macros, the solution could again be proposed as a library. However, given that such a feature whose design and implementation is daunting and not yet to be even approved in principle, this too is a non-starter for an urgently-needed construct.)
To expand on the design proposal further, et's look at the subtle distinction I've made in the words I've used above. Specifically, we notice a distinction between -
Lensing - viewing or updating a value contained by another functional value
Lenses - a general mechanism by which lensing is achieved
We've already seen the syntax I propose for lensing where the lens itself is contextually implied -
Now say we want to pull out the lens itself that it might be passed around for lensing later. Obviously, we will need a syntax for that as well. However, the desired form taken by that syntax is more nebulous, so here are a few options -
...and there are presumably many more possible forms. After all, for literally ALL the syntax I've proposed in this thread, I've merely been riffing!
Additionally, there would need to be a syntax for allowing user-defined induction of other things into the category of 'lensability'.
For example, say we have a type whose members are described at run-time like so -
We should be able to decorate the view and update functions like so -
In conclusion, F# needs first-class support for lensing / lenses because it current set of language features is inadequate to provide a library solution, and because lensing / lenses is such a fundamental property of functional programming in stateful systems. While my design proposal certainly will have some flaws that need to be smoothed over, I think it is a good enough start to get something in the works!
Original UserVoice Submission
Archived Uservoice Comments
The text was updated successfully, but these errors were encountered: