Édipo Féderle
Édipo Féderle

Reputation: 4257

Update record field from Collection

I am playing a little bit with Elm these days, but I stuck with a simple case where I want to update a record field. My code is like this:

-- MODEL


initialModel : Model
initialModel =
    { selectedLanguage = "german"
    , allCards = Card.cards
    }


type alias Msg =
    { description : String
    , data : String
    , id : String
    }

The update function

update : Msg -> Model -> Model
update msg model =
    case List.head (model.allCards) of
        Just card ->
            { card | fliped = True }
        Nothing -> model

but I see this:

Something is off with the 1st branch of this `case` expression:

50|             { card | fliped = True }
                ^^^^^^^^^^^^^^^^^^^^^^^^
The 1st branch is a record of type:

    { back : String, fliped : Bool, front : String, id : String }

But the type annotation on `update` says it should be:

    Model

Hint: Seems like a record field typo. Maybe back should be allCards?

Hint: Can more type annotations be added? Type annotations always help me give
more specific messages, and I think they could help a lot in this case!
Detected errors in 1 module.

I think I should always return a model from update function like my type says, but cannot figure out how. Any advice here?

Upvotes: 4

Views: 76

Answers (1)

glennsl
glennsl

Reputation: 29126

You'll have update the allCards field of model too. You can nest the card update inside the model update if the former returns a list instead of just a single card:

update : Msg -> Model -> Model
update msg model =
    { model
    | allCards =
        case model.allCards of
            card :: rest ->
                { card | fliped = True } :: rest

            [] ->
                []
    }

Or you can bind the new allCards to a name if you prefer:

update : Msg -> Model -> Model
update msg model =
    let
        newAllCards =
            case model.allCards of
                card :: rest ->
                    { card | fliped = True } :: rest

                [] ->
                    []
    in
    { model | allCards = newAllCards }

I pattern match directly on the list here instead of using List.head, as that also gives me the remainder of the list and I don't have to deal with an intermediary Maybe value (or two actually, since List.tail returns a Maybe as well). The card::rest branch hits if allCards contains at least one card, so the only remaining case is therefore [], which is easy enough to handle.

Also, flipped is spelled with two ps ;)

Upvotes: 4

Related Questions