1

I want to change some deeply nested values inside my model.

type alias Tone = ( String, Int )

type alias Fret =
    {   number : Int
    ,   tone : Tone
    ,   active : Bool
    }

type alias GuitarString =
    {   number : Int
    ,   frets : List Fret
    }

My model is called "Fretboard":

type alias Fretboard =
    {   guitarStrings : List GuitarString
    }

How could I change the value of the active field inside a certain fret?

The hierarchy is:

Fretboard > GuitarStrings > Frets

Thank you.

Timo
  • 121
  • 6

1 Answers1

3

In your model, you have a few lists and you'll have to have a way of specifying which item in the list to update. The elm-community/list-extra package has some nice helpers for updating a value in a list, some by a conditional and another by specifying an index.

In this example, I'm using updateIf to check on the string number stored in the .number of the GuitarString. This will probably be fine, but it means you will have to be responsible to make sure the number exists and only exists once in that list. You could also update at an index by using updateIfIndex; it just depends on how you typically handle these in your app.

Here is an example set of update functions for your need using only the elm-community/list-extra package as a dependency.

setGuitarActiveFretTone : Int -> Tone -> Fretboard -> Fretboard
setGuitarActiveFretTone string tone fb =
    { fb
        | guitarStrings =
            updateIf
                (\gs -> gs.number == string)
                (setActiveFretTone tone)
                fb.guitarStrings
    }

setActiveFretTone : Tone -> GuitarString -> GuitarString
setActiveFretTone tone gs =
    { gs | frets = updateIf .active (setTone tone) gs.frets }

setTone : Tone -> Fret -> Fret
setTone tone fret =
    { fret | tone = tone }

If you plan on doing lots of nested updates, you may want to consider using lenses from a library like arturopala/elm-monocle (here's a small example on another StackOverflow answer).

Chad Gilbert
  • 36,115
  • 4
  • 89
  • 97