Dealing with invalid state transitions

67 views
Skip to first unread message

Tomáš Znamenáček

unread,
Jan 17, 2017, 9:03:05 AM1/17/17
to Elm Discuss
Hello!

I have an app that loads some JSON from a website and displays it. The state of the app could be modelled a bit like this:

type State =
    Loading |
    Displaying Stuff

type alias Stuff = { … }

Now I am writing the update function to handle messages:

update : Msg -> State -> (State, Cmd Msg)
update msg state = case msg of
    UpdateThis -> …
    UpdateThat -> …

My problem is that the state can be either Loading or Displaying, but most of the messages only make sense in the Displaying state, leading me to code like this:

update : Msg -> State -> (State, Cmd Msg)
update msg state = case msg of
    UpdateThis -> case state of
        Displaying stuff -> …
        _ -> (Failed "Invalid state", Cmd.none)
    UpdateThat -> case state of
        Displaying stuff -> …
        _ -> (Failed "Invalid state", Cmd.none)

Obviously, this is dumb. How can I “divide” the loading and the displaying part of the app? (Assuming that UpdateThis and UpdateThat can only arrive in the correct, Displaying state.)

Thank you!

T.

Matthew Griffith

unread,
Jan 17, 2017, 9:41:19 AM1/17/17
to Elm Discuss

You could invert your cases.


update msg state =
    case state of
           Loading ->
                  case msg of
                        (all your messages that apply when loading)
           Displaying stuff ->
                   case msg of
                        (all your messages that apply when displaying

Zinggi

unread,
Jan 17, 2017, 9:57:36 AM1/17/17
to Elm Discuss
You could use this trick:

case (state, msg) of
    (Displaying stuff, UpdateThis) -> ...
    (Displaying stuff, UpdateThat) -> ...
    (Loading, _) -> ...
    _ -> ... {- only if needed -}

Max Goldstein

unread,
Jan 17, 2017, 10:04:36 AM1/17/17
to Elm Discuss
You could model your data using the RemoteData library on elm-package, and use the map function to apply changes only to loaded data.

Tomáš Znamenáček

unread,
Jan 17, 2017, 10:30:41 AM1/17/17
to Elm Discuss
Wow, thank you very much for the responses! I went with the tuple pattern match trick for the moment, it’s better than what I had before.

But I would still be interested in splitting the app in two parts. It feels wrong to mix the loading logic with the display logic in a single function. Ideally, I would like the app to “behave like a loader” and then switch the behaviour completely to the display part, passing the loaded data or an error. And the update function running the display part would know nothing about data loading. Does that make sense?

Thank you again,

T.
Reply all
Reply to author
Forward
0 new messages