Update a field in an Elm-lang record via dot function?

筅森魡賤 提交于 2019-12-12 08:41:49

问题


Is it possible to update a field in an Elm record via a function (or some other way) without explicitly specifying the precise field name?

Example:

> fields = { a = 1, b = 2, c = 3 }
> updateField fields newVal fieldToUpdate = { fields | fieldToUpdate <- newVal }
> updateField fields 5 .a -- does not work

UPDATE:

To add some context, I'm trying to DRY up the following code:

UpdatePhraseInput contents ->
  let currentInputFields = model.inputFields
  in { model | inputFields <- { currentInputFields | phrase <- contents }}

UpdatePointsInput contents ->
  let currentInputFields = model.inputFields
  in { model | inputFields <- { currentInputFields | points <- contents }}

Would be really nice if I could call a mythical updateInput function like this:

UpdatePhraseInput contents -> updateInput model contents .phrase
UpdatePointsInput contents -> updateInput model contents .points

回答1:


Rolling your own update function

Yes, though perhaps not as nicely as getting from a field. But the idea is the same, you write a function that simply uses the record update syntax:

setPhrase r v = { r | phrase <- v }
setPoints r v = { r | points <- v }
updInputFields r f = { r | inputFields <- f r.inputFields }

Then you can write:

UpdatePhraseInput contents -> updInputFields model (flip setPhrase contents)
UpdatePointsInput contents -> updInputFields model (flip setPoints contents)

The Focus library

When you combine field and fieldSet, you get something like a Focus. Although that library works for more things than just records. Here's an example of what this would look like using Focus:

phrase = Focus.create .phrase (\upd r -> { r | phrase <- upd r.phrase })
points = Focus.create .points (\upd r -> { r | points <- upd r.points })
inputFields = Focus.create .inputFields (\upd r -> { r | inputFields <- upd r.inputFields})

Then you can write:

UpdatePhraseInput contents -> Focus.set (inputFields => phrase) contents model
UpdatePointsInput contents -> Focus.set (inputFields => points) contents model



回答2:


Ideally you could define a function which could select which field gets updated, but you cannot.

See This article, which explains why it's not currently possible to functionally update fields in a record in elm:

"Seasoned functional programmers will surely have noticed that many of these concepts sound a lot like lenses, and Elm actually already has a lens-like library authored by Evan himself, called Focus. This, however, does not actually solve the problem: it requires manual description of setters just like the purely function based approach does."

...and the following comment from the the creator of Elm explaining why proposed support for this wasn't added with the recent changes to records:

"I considered that and decided against it. I know that proposal. It's a language feature proposal, not a simple syntax thing"



来源:https://stackoverflow.com/questions/31770421/update-a-field-in-an-elm-lang-record-via-dot-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!