Guilherme Escarabel
Guilherme Escarabel

Reputation: 83

Elm: Update value in sub types

I have this type

type alias Cat =
 { head : Head
 }

type alias Head =
  { eyes : Int
  , nose : Int
  , mouth : Mouth
  }

type alias Mouth =
  { tongue : Int
  , prey : Prey
  }

type alias Prey =
  { left : Int
  , right : Int 
  }

Inserting values

cat : Cat
cat = 
  { head = 
    { eyes = 2
    , nose = 1
    , mouth = 
      { tongue = 1
      , prey = 
        { left = 1
        , right = 1
        }
      }
    }
  }

I'm usually doing this to change the right side of the prey

let  
  newCat = 
    (Cat 
      (Head oldValue.eyes oldValue.nose 
        (Mouth 
          (Prey oldValue.left 1)
        )
      )
    )
in
 ({model | cat = newCat }, Cmd.none)

And I hate hitting that, but I can not figure out how to do it the right way. When I try to do it right I can not return 'type cat'.

How to change the right prey in the right way?

Upvotes: 1

Views: 86

Answers (1)

Emmanuel Rosa
Emmanuel Rosa

Reputation: 9885

You're already doing it the right way.

When you're dealing with nested records, you have to build them up, just like you're already doing.

Now, what you can do is abstract newCat and turn it into a function of type Int -> Cat -> Cat. Then, you'd be able to do ({model | cat = updateRightPrey 1 model.cat }, Cmd.none)

But honestly, you may want to reconsider your data model. Does Head, Mouth, and Prey actually provide any value? What would you loose (and what would you have to gain) if you flatten your model like this:

type alias Cat = 
  { eyes : Eyes
  , nose : Nose
  , tongue : Tongue
  , left : Prey
  , right : Prey 
  }

type alias Eyes = Int
type alias Nose = Int
type alias Tongue = Int
type alias Prey = Int

Even if you change all those Int type alias to types...

type Eyes = Eyes Int

... it would be a lot simpler than dealing with nested records:

let
    cat = model.cat
in
({model | cat = { cat | right = 1 }, Cmd.none)

or...

let
    cat = model.cat
in
({model | cat = { cat | right = Prey 1 }, Cmd.none)

Upvotes: 5

Related Questions