If Msg is a function, all update does is apply the function:
type alias Msg = Model -> Model
update msg model =
msg model
Or in a more complete version with side effects:
type Msg = Msg (Model -> (Model, Cmd Msg)) -- Needs to be a custom type to be recursive
update (Msg msg) model =
msg model
It is kind of neat in the sense that that is all that is needed to implement update instead of a steadily growing case statement.
Typically my update
case statement will break out each branch into its own update-like function anyway, named after what it does. So instead of triggering those with Msg
s capturing the parameters for each, I would just use them directly in the view
or in other update-like functions.
However, I can think of another reason not to do this, which is to do with race conditions in the real world…
Elm is single threaded, and event driven. The real world is parallel. This means that real world events can arrive into your Elm code not necessarily in the same order each time. My favourite example is a dialog box with a “close” button. When the dialog is opened it sends a network request to fetch some data to show in the box. When the data arrives it puts the dialog box into a certain state depending on the data. But if the user clicks close before the data arrives, we do not want to transition into that new dialog box state, because the box has already gone! Network call and close click can give rise to a race condition, even though Elm is single threaded.
So we use a state machine to marshall real world events into a sequence of state machine transitions that we consider to be legal states of the program, and eliminate the spurious transition that would resurrect the closed dialog if data arrives later.
type Model
= Closed
| OpenWaitingForData
| OpenGotData
type Msg
= DataFetched
| CloseClick
| OpenClicked
update msg model =
case (model, msg) of
(Closed, OpenClicked) -> OpenWaitingForData
(OpenWaitingForData, CloseClicked) -> Closed
(OpenGotData, CloseClicked) -> Closed
(OpenWaitingForData, DataFetched) -> OpenGotData
_ -> model
If Msg
was just a function, we would have to model the states as branches in the view
instead, to limit state transitions from events happening only in certain situations. Doable, but update
like above often does a very good job of modelling the state machine transitions directly in an easily readable format.