Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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
like image 249
seanomlor Avatar asked Aug 02 '15 09:08

seanomlor


1 Answers

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
like image 180
Apanatshka Avatar answered Oct 10 '22 05:10

Apanatshka