# Updating nested records

**URL:** <https://discourse.elm-lang.org/t/updating-nested-records/9719>\
**Category:** Learn\
**Created:** [March 18, 2024, 10:46pm UTC](https://discourse.elm-lang.org/t/updating-nested-records/9719 "2024-03-18T22:46:26Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![tomka](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/tomka/32/5121_2.png) [@tomka](https://discourse.elm-lang.org/u/tomka)\
**Post date:** [March 18, 2024, 10:46pm UTC](https://discourse.elm-lang.org/t/updating-nested-records/9719/1 "2024-03-18T22:46:26Z")

</div>

Hi,

I am experimenting with records and I am a little bit confused. In the example person2 and person3 should be the same, but person3 gives me an error…  
Can anybody explain the difference?

```elm
type alias Date =
    { day : Int
    , month : Int
    , year : Int
    }

type alias Person =
    { firstName : String
    , lastName : String
    , birthDate : Date
    }

person1 : Person
person1 =
    { firstName = "Tom"
    , lastName = "Smith"
    , birthDate = { day = 6, month = 6, year = 2006 }
    }

person2 : Person
person2 =
    let date = person1.birthDate
    in
    { person1 | birthDate = { date | month = person1.birthDate.month + 1 } }

person3 : Person
person3 =
    { person1 | birthDate = { person1.birthDate | month = person1.birthDate.month + 1 } }

```

---

<div class="post-metadata">

**Author:** ![HuwCampbell](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/huwcampbell/32/5127_2.png) [@HuwCampbell](https://discourse.elm-lang.org/u/HuwCampbell)\
**Post date:** [March 19, 2024, 12:29am UTC](https://discourse.elm-lang.org/t/updating-nested-records/9719/2 "2024-03-19T00:29:20Z")

</div>

The Elm compiler only accepts a name in the update position, not an expression. The issue is tracked [here](https://github.com/elm/compiler/issues/1375).

There’s no fundamental reason why this is the case, semantically it would make no difference, but that’s the way it is. I believe the Gren fork has fixed this.

---

<div class="post-metadata">

**Author:** ![Lucas\_Payr](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/lucas_payr/32/4993_2.png) [@Lucas\_Payr](https://discourse.elm-lang.org/u/Lucas_Payr)\
**Post date:** [March 19, 2024, 6:12am UTC](https://discourse.elm-lang.org/t/updating-nested-records/9719/3 "2024-03-19T06:12:51Z")

</div>

I believe the reason that Evan has given is this:

> [@Proposal: record setters](https://discourse.elm-lang.org/t/proposal-record-setters/5920/6):
>
> the current design encourages the use of named top-level functions

Also in the docs you find

> People coming from JavaScript tend to (1) overuse records and (2) have a habit of breaking records into smaller records and to distribute them among a bunch of different files. These are both traps in Elm! [(source)](https://elm-lang.org/docs/records)

so person2 would be the idomatc way to write it in elm.

Also, if you have have to update a field a lot, it might be helpful to write a utility function for it:

```auto
mapMonth : (Int -> Int) -> Date -> Date
mapMonth fun date =
   { date | month = fun date.month }

person4 : Person
person4 =
   { person1 | birthDate = mapMonth (\n -> n + 1) person1.birthDate } 

```

---

<div class="post-metadata">

**Author:** ![tomka](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/tomka/32/5121_2.png) [@tomka](https://discourse.elm-lang.org/u/tomka)\
**Post date:** [March 19, 2024, 7:31am UTC](https://discourse.elm-lang.org/t/updating-nested-records/9719/4 "2024-03-19T07:31:58Z")

</div>

OK, thank you. I wasn’t sure if I was doing something wrong or not understanding correctly. But then it’s just a design decision by Evan. I would find it logical to use the notation of person2. But well, that’s how it is.

I’m curious to see how Gren and Elm will develop…

---

<div class="post-metadata">

**Author:** ![dwayne](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dwayne/32/5478_2.png) [@dwayne](https://discourse.elm-lang.org/u/dwayne)\
**Post date:** [March 19, 2024, 2:52pm UTC](https://discourse.elm-lang.org/t/updating-nested-records/9719/5 "2024-03-19T14:52:30Z")

</div>

Another way to write it is as follows:

```auto
updateBirthDate : (Date -> Date) -> Person -> Person
updateBirthDate transform person =
    { person | birthDate = transform person.birthDate }

person5 : Person
person5 =
    updateBirthDate (\date -> { date | month = date.month + 1 }) person1

```

This way you can update any field of `birthDate` and not just `month`.

For another example, see [`updateForm`](https://github.com/rtfeldman/elm-spa-example/blob/cb32acd73c3d346d0064e7923049867d8ce67193/src/Page/Login.elm#L204-L206) from `Page.Login` in `rtfeldman/elm-spa-example`.

---

<div class="post-metadata">

**Author:** ![dta](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dta/32/1917_2.png) [@dta](https://discourse.elm-lang.org/u/dta)\
**Post date:** [March 19, 2024, 3:06pm UTC](https://discourse.elm-lang.org/t/updating-nested-records/9719/6 "2024-03-19T15:06:39Z")

</div>

This is the only error message in Elm that I find to be genuinely unhelpful. Most others explain what the problem is and explain how to fix it, but this one is really cryptic especially since it seems like the mistake should be valid code.

---

<div class="post-metadata">

**Author:** ![paulh](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/paulh/32/5022_2.png) [@paulh](https://discourse.elm-lang.org/u/paulh)\
**Post date:** [March 20, 2024, 7:36am UTC](https://discourse.elm-lang.org/t/updating-nested-records/9719/7 "2024-03-20T07:36:27Z")

</div>

You could also combine both approaches above from @dwayne and @Lucas_Payr:

```elm
updateBirthMonth : Int -> Person -> Person
updateBirthMonth newMonth =
    updateBirthDate <|
        mapMonth <|
            \_ -> newMonth

incrementBirthMonthBy : Int -> Person -> Person
incrementBirthMonthBy increment =
    updateBirthDate <|
        mapMonth <|
            \n -> n + increment

person6 : Person
person6 =
    updateBirthMonth 7 person1

person7 : Person
person7 =
    incrementBirthMonthBy 2 person1

```

@dwayne has a small typo

```auto
updateBirthDate (\date -> { date | month = month + 1 }) person1

```

should be

```auto
updateBirthDate (\date -> { date | month = date.month + 1 }) person1

```

---

<div class="post-metadata">

**Author:** ![dwayne](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dwayne/32/5478_2.png) [@dwayne](https://discourse.elm-lang.org/u/dwayne)\
**Post date:** [March 20, 2024, 3:57pm UTC](https://discourse.elm-lang.org/t/updating-nested-records/9719/8 "2024-03-20T15:57:39Z")

</div>

@paulh Thanks, fixed!

---

<div class="post-metadata">

**Author:** ![system](https://canada1.discourse-cdn.com/flex035/uploads/elm_lang/original/1X/50a05e53677a2c3b47776d7abd0f113eb50193a1.png) [@system](https://discourse.elm-lang.org/u/system)\
**Post date:** [March 30, 2024, 3:57pm UTC](https://discourse.elm-lang.org/t/updating-nested-records/9719/9 "2024-03-30T15:57:58Z")

</div>

Closed on March 30, 2024, 3:57pm UTC

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.
