# Preventing invalid states in update function

**URL:** <https://discourse.elm-lang.org/t/preventing-invalid-states-in-update-function/7060>\
**Category:** Learn\
**Created:** [March 8, 2021, 1:58am UTC](https://discourse.elm-lang.org/t/preventing-invalid-states-in-update-function/7060 "2021-03-08T01:58:22Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![DullBananas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dullbananas/32/3709_2.png) [@DullBananas](https://discourse.elm-lang.org/u/DullBananas)\
**Post date:** [March 8, 2021, 1:58am UTC](https://discourse.elm-lang.org/t/preventing-invalid-states-in-update-function/7060/1 "2021-03-08T01:58:22Z")

</div>

In the update function, it’s common to have `_` in the case statement to ignore invalid Msg+Model combinations. I prevented this by defining Msg as `() -> (Model, Cmd Msg)`

[https://ellie-app.com/cyRWcG6pYCxa1](https://ellie-app.com/cyRWcG6pYCxa1)

is it possible to do this without stale update bug? would this cause bad performance?

---

<div class="post-metadata">

**Author:** ![perty](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/perty/32/4459_2.png) [@perty](https://discourse.elm-lang.org/u/perty)\
**Post date:** [March 8, 2021, 7:24am UTC](https://discourse.elm-lang.org/t/preventing-invalid-states-in-update-function/7060/2 "2021-03-08T07:24:45Z")

</div>

What is the “state update bug”?

---

<div class="post-metadata">

**Author:** ![Augustin82](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/augustin82/32/1591_2.png) [@Augustin82](https://discourse.elm-lang.org/u/Augustin82)\
**Post date:** [March 8, 2021, 8:32am UTC](https://discourse.elm-lang.org/t/preventing-invalid-states-in-update-function/7060/3 "2021-03-08T08:32:08Z")

</div>

You can have desynchronization, in certain cases, where the `model` that was used to initialize the function has not been updated (because the DOM hasn’t had time to be updated) and so you will “work” on a previous version of the model.

---

<div class="post-metadata">

**Author:** ![rupert](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/rupert/32/1775_2.png) [@rupert](https://discourse.elm-lang.org/u/rupert)\
**Post date:** [March 8, 2021, 10:22am UTC](https://discourse.elm-lang.org/t/preventing-invalid-states-in-update-function/7060/4 "2021-03-08T10:22:05Z")

</div>

By doing it as `() -> (Model, Cmd Msg)` you are throwing away the version of the model that you should be using, since you are always ignoring the input `model` parameter. Out of all the ways you could try and make a variation on the usual MVU pattern, this is probably the worst choice.

---

<div class="post-metadata">

**Author:** ![lydell](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/lydell/32/178_2.png) [@lydell](https://discourse.elm-lang.org/u/lydell)\
**Post date:** [March 8, 2021, 11:34am UTC](https://discourse.elm-lang.org/t/preventing-invalid-states-in-update-function/7060/5 "2021-03-08T11:34:02Z")

</div>

> [@Augustin82](#):
>
> You can have desynchronization, in certain cases

What’s a concrete example of such a case? I tried to make one with `Time.every`, but it seems to work correctly: [https://ellie-app.com/cz3HYRPqpWka1](https://ellie-app.com/cz3HYRPqpWka1)

Edit: Tried to do it with `Process.sleep` instead, but got stuck on:

```auto
type alias Msg =
    () -> ( Model, Cmd Msg )

```

being an error:

```auto
This type alias is recursive, forming an infinite type!

19| type alias Msg =
               ^^^
When I expand a recursive type alias, it just keeps getting bigger and bigger.
So dealiasing results in an infinitely large type! Try this instead:

    type Msg =
        Msg
            (() -> ( Model, Cmd Msg ))

Hint: This is kind of a subtle distinction. I suggested the naive fix, but I
recommend reading <https://elm-lang.org/0.19.1/recursive-alias> for ideas on how
to do better.

```

---

<div class="post-metadata">

**Author:** ![Augustin82](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/augustin82/32/1591_2.png) [@Augustin82](https://discourse.elm-lang.org/u/Augustin82)\
**Post date:** [March 8, 2021, 1:50pm UTC](https://discourse.elm-lang.org/t/preventing-invalid-states-in-update-function/7060/6 "2021-03-08T13:50:33Z")

</div>

I know for sure we had problems in our codebase related to partial application of model to an update function. Theoretically, it’s going to happen if message A fires and then message B fires before the view where it was created has been updated. So it’s unlikely for simple examples, but could happen more frequently when you have both frequent updates and slow rerendering.  
On the other hand, in this talk, Roman Potasovs explains that he creates the update functions in the view and has not encountered any problem: [Roman Potasovs Is performance enough in Elm to create full fledged video games Elm Europe 2019 - YouTube](https://www.youtube.com/watch?v=_flFAV0_TeY)

So, obviously, one should do as one wants, but one’s opening oneself to possible bug with one method, and to no possible bug with the other.

---

<div class="post-metadata">

**Author:** ![rupert](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/rupert/32/1775_2.png) [@rupert](https://discourse.elm-lang.org/u/rupert)\
**Post date:** [March 8, 2021, 2:34pm UTC](https://discourse.elm-lang.org/t/preventing-invalid-states-in-update-function/7060/7 "2021-03-08T14:34:32Z")

</div>

> [@lydell](#):
>
> What’s a concrete example of such a case?

Here is the Ellie I wrote to illustrate how stale state can happen: [https://ellie-app.com/yVC9wPk33xa1](https://ellie-app.com/yVC9wPk33xa1)

---

<div class="post-metadata">

**Author:** ![DullBananas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dullbananas/32/3709_2.png) [@DullBananas](https://discourse.elm-lang.org/u/DullBananas)\
**Post date:** [March 8, 2021, 2:52pm UTC](https://discourse.elm-lang.org/t/preventing-invalid-states-in-update-function/7060/8 "2021-03-08T14:52:55Z")

</div>

> [@lydell](#):
>
> Edit: Tried to do it with `Process.sleep` instead, but got stuck on:
> 
> ```auto
> type alias Msg =
> () -> ( Model, Cmd Msg )
> 
> ```

To have Cmd, you can’t use a type alias; do this

```auto
type Msg
    = Msg (() -> ( Model, Cmd Msg ))

```

---

<div class="post-metadata">

**Author:** ![allanderek](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/allanderek/32/1360_2.png) [@allanderek](https://discourse.elm-lang.org/u/allanderek)\
**Post date:** [March 8, 2021, 3:20pm UTC](https://discourse.elm-lang.org/t/preventing-invalid-states-in-update-function/7060/9 "2021-03-08T15:20:12Z")

</div>

> [@lydell](#):
>
> What’s a concrete example of such a case? I tried to make one with `Time.every` , but it seems to work correctly: [https://ellie-app.com/cz3HYRPqpWka1](https://ellie-app.com/cz3HYRPqpWka1)

Coury Ditch [wrote a blog post](https://blog.realkinetic.com/the-trickiest-elm-bug-ive-ever-seen-988aff6cbbd7) regarding such a stale message bug and I also wrote a [blog post](http://blog.poleprediction.com/posts/2021-02-16-stale-messages/) regarding this in which the bug manifested itself via auto-fill for forms. That happened because you essentially got multiple field-update messages within one render loop.

---

<div class="post-metadata">

**Author:** ![DullBananas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dullbananas/32/3709_2.png) [@DullBananas](https://discourse.elm-lang.org/u/DullBananas)\
**Post date:** [March 9, 2021, 3:43pm UTC](https://discourse.elm-lang.org/t/preventing-invalid-states-in-update-function/7060/10 "2021-03-09T15:43:25Z")

</div>

> [@rupert](#):
>
> Here is the Ellie I wrote to illustrate how stale state can happen: [https://ellie-app.com/yVC9wPk33xa1](https://ellie-app.com/yVC9wPk33xa1)

is there one that works with touchscreen?

---

<div class="post-metadata">

**Author:** ![opvasger](https://avatars.discourse-cdn.com/v4/letter/o/8e8cbc/32.png) [@opvasger](https://discourse.elm-lang.org/u/opvasger)\
**Post date:** [March 9, 2021, 4:32pm UTC](https://discourse.elm-lang.org/t/preventing-invalid-states-in-update-function/7060/11 "2021-03-09T16:32:11Z")

</div>

> [@DullBananas](#):
>
> In the update function, it’s common to have `_` in the case statement to ignore invalid Msg+Model combinations

Alexis King has some thoughts on type-safety and wildcards in pattern-matches. It’s somewhat related, and perhaps useful reading ☀ [Names are not type safety](https://lexi-lambda.github.io/blog/2020/11/01/names-are-not-type-safety/)

---

<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 9, 2021, 5:28pm UTC](https://discourse.elm-lang.org/t/preventing-invalid-states-in-update-function/7060/12 "2021-03-09T17:28:28Z")

</div>

> [@DullBananas](#):
>
> is there one that works with touchscreen?

Since the example is with an old version of elm, I can’t save a modification, but if you put this is the command in `init`, you’ll start out with a stale update:

```
Cmd.batch
    [ Task.perform identity (Task.succeed (Event 0))
    , Task.perform identity (Task.succeed (Event 0))
    ]

```

> [@opvasger](#):
>
> thoughts on type-safety and wildcards in pattern-matches

This brings up the question: Is there a way to model updates in a way that actually restricts the `(Msg, Model)` pairs that can be encountered?

---

<div class="post-metadata">

**Author:** ![rupert](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/rupert/32/1775_2.png) [@rupert](https://discourse.elm-lang.org/u/rupert)\
**Post date:** [March 9, 2021, 8:32pm UTC](https://discourse.elm-lang.org/t/preventing-invalid-states-in-update-function/7060/13 "2021-03-09T20:32:11Z")

</div>

> [@dta](#):
>
> This brings up the question: Is there a way to model updates in a way that actually restricts the `(Msg, Model)` pairs that can be encountered?

Given a `Model` what `Msg`s are possible from that model:

```auto
allowed : Msg -> Model -> Maybe Msg

```

You could define that function, then use it while building the `view`? But you will probably implement it with a wildcard `_ -> Nothing`?

---

<div class="post-metadata">

**Author:** ![DullBananas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dullbananas/32/3709_2.png) [@DullBananas](https://discourse.elm-lang.org/u/DullBananas)\
**Post date:** [March 10, 2021, 4:21am UTC](https://discourse.elm-lang.org/t/preventing-invalid-states-in-update-function/7060/14 "2021-03-10T04:21:11Z")

</div>

> [@dta](#):
>
> This brings up the question: Is there a way to model updates in a way that actually restricts the `(Msg, Model)` pairs that can be encountered?

Not completely unless you use the current model when constructing a Msg. When you don’t do this, all possible Msg values need to be handled regardless of the model’s state when the update function runs.

---

<div class="post-metadata">

**Author:** ![jfine2358](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/jfine2358/32/3875_2.png) [@jfine2358](https://discourse.elm-lang.org/u/jfine2358)\
**Post date:** [March 10, 2021, 9:51am UTC](https://discourse.elm-lang.org/t/preventing-invalid-states-in-update-function/7060/15 "2021-03-10T09:51:00Z")

</div>

> [@dta](#):
>
> This brings up the question: Is there a way to model updates in a way that actually restricts the `(Msg, Model)` pairs that can be encountered?

(0) This is a really good question. Thank you @dta. It gets to the heart of what needs to be done.

(1) I’m not sure if this makes sense, but what if the `Model` was a union type (or contained a union type)? For example

```elm
type Focus = Browse BrowseModel | Order OrderModel

```

(2) Now ensure that when `Focus` is `Browse` the view doesn’t create Order messages, and vice versa.

(3) The lag problem (aka stale update bug) described earlier in this message still exists. (I think it’s a feature of Javascript.) In the view the focus might still be `Browse` even though in model it is `Order`.

(4) Having a union type in the model could make it much easier for `update msg model` to do the right thing.

(5) In our example, if the `view` send a `BrowseMsg` when the model state is `Order` the right thing might be to change the focus to `Error`. (So now `Focus` needs a new variant.)

(6) And when `view` gets an `Error` it goes into a modal state, and asks the user what to do.

---

<div class="post-metadata">

**Author:** ![rupert](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/rupert/32/1775_2.png) [@rupert](https://discourse.elm-lang.org/u/rupert)\
**Post date:** [March 10, 2021, 10:46am UTC](https://discourse.elm-lang.org/t/preventing-invalid-states-in-update-function/7060/16 "2021-03-10T10:46:17Z")

</div>

> [@jfine2358](#):
>
> Having a union type in the model could make it much easier for `update msg model` to do the right thing.

Yes, and this is often how I do it.

The `Model` describes the states of a state machine. The `Msg` describes the events that can move between states. The state relationship is a subset of the cross product of the `Model` and the `Msg`. As its a subset, there is likely to be a wildcard (`_ -> (model, Cmd.none`) for the cases where no valid state machine transition exists.

Here is an example for a vending machine - which is often used in introductory courses on state machines:

```auto
type Model
    = Start
    | Money Int
    | Refunding
    | Vending

type Msg
    = InsertMoney Int
    | TryRefund
    | TryBuy
    | RefundComplete
    | VendComplete

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case ( msg, model ) of
        ( InsertMoney val, Start ) ->
            ( Money val, Cmd.none )

        ( InsertMoney val, Money oldVal ) ->
            ( Money (val + oldVal), Cmd.none )

        ( TryRefund, Money val ) ->
            ( Refunding, refund )

        ( TryBuy, Money val ) ->
            ( Vending, vend )

        ( RefundComplete, Refunding ) ->
            Start

        ( VendComplete, Vending ) ->
            Start

        ( _, _ ) ->
            ( model, Cmd.none )

```

This code was directly derived from an initial pen-and-paper sketch of the state machine.

In the above example, if someone was to insert money and then press both the ‘vend’ and ‘refund’ buttons at the same time, one will get processed before the other. This will put the machine into either the `Refunding` or `Vending` states. In those states, the other button action will be ignored (stale update). This prevents someone from getting both the product AND a refund with some cheeky action on the buttons.

This is an example of how putting a state machine on an asynchronous event stream transforms it into an ordered stream of valid events only. The real world is always going to be asynchronous and it is usually the job of a UI to tame that real world event stream, and state machines are an ideal way of modelling and implementing that. Again - similarities with design methodologies used in hardware definition languages.

---

<div class="post-metadata">

**Author:** ![DullBananas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dullbananas/32/3709_2.png) [@DullBananas](https://discourse.elm-lang.org/u/DullBananas)\
**Post date:** [March 11, 2021, 1:27am UTC](https://discourse.elm-lang.org/t/preventing-invalid-states-in-update-function/7060/17 "2021-03-11T01:27:33Z")

</div>

> [@dta](#):
>
> Since the example is with an old version of elm, I can’t save a modification, but if you put this is the command in `init` , you’ll start out with a stale update:
> 
> ```auto
> Cmd.batch
> [ Task.perform identity (Task.succeed (Event 0))
> , Task.perform identity (Task.succeed (Event 0))
> ]
> 
> ```

I updated the example to 0.19 and added that to `init`:

[https://ellie-app.com/cBbWsmsGpbta1](https://ellie-app.com/cBbWsmsGpbta1)

---

<div class="post-metadata">

**Author:** ![DullBananas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dullbananas/32/3709_2.png) [@DullBananas](https://discourse.elm-lang.org/u/DullBananas)\
**Post date:** [March 12, 2021, 3:26am UTC](https://discourse.elm-lang.org/t/preventing-invalid-states-in-update-function/7060/18 "2021-03-12T03:26:20Z")

</div>

> [@Augustin82](#):
>
> it’s unlikely for simple examples, but could happen more frequently when you have both frequent updates and slow rerendering.

Is there a way to make sure the updates aren’t too frequent?

---

<div class="post-metadata">

**Author:** ![rupert](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/rupert/32/1775_2.png) [@rupert](https://discourse.elm-lang.org/u/rupert)\
**Post date:** [March 12, 2021, 9:22am UTC](https://discourse.elm-lang.org/t/preventing-invalid-states-in-update-function/7060/19 "2021-03-12T09:22:42Z")

</div>

That isn’t really the problem.

There is a queue of events that gets fed to the `update`. The `view` can place events onto that queue. The view is updated with the animation frame - so it only gets a new copy of the `Model` around 60 times a second. If events fire quickly from the `view`, then 2 or more events can be built against the same `Model` version.

It does not matter how quick or slow the `update` runs, it just pulls events from the queue and processes them. If some events are stale, its not because of the `update` function, but the `view` that put them there in the first place.

The solution is to not capture state from the `Model` in your `Msg`s. So instead of

```auto
type Msg 
    = MoveCursorTo Int -- Absolute value based off model. (value = model.pos + delta)
    | ...

```

Always work with deltas against the `Model`:

```auto
type Msg
    = MoveCursorBy Int -- Relative to the model. (value = delta)
    | ...

```

Then the problem is solved.

Unfortunately, I don’t think there is an easy way to use types to enforce this design pattern. Maybe something along the lines of:

```auto
type Position = ...
type Delta = ...

applyDelta : Delta -> Position -> Position

makeDelta : Int -> Delta

extractPosition : Position -> Int

```

So make `Position` opaque and only provide constructors for `Delta` and the ability to apply deltas. Worth doing? Not so sure.

---

<div class="post-metadata">

**Author:** ![jfine2358](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/jfine2358/32/3875_2.png) [@jfine2358](https://discourse.elm-lang.org/u/jfine2358)\
**Post date:** [March 12, 2021, 11:24am UTC](https://discourse.elm-lang.org/t/preventing-invalid-states-in-update-function/7060/20 "2021-03-12T11:24:43Z")

</div>

> [@rupert](#):
>
> The solution is to not capture state from the `Model` in your `Msg` s.

(0) Here’s my understanding of the situation. Disclaimer. I know something about logic and formal methods, but am a newcomer to programming Elm. If I get something wrong, I’ll learn something new.

This is a long post, in part because I first summarise previous valuable statements from other contributions. Steps (11) and (12) give a demo of some key ideas.

(1) There are two problems here that require a solution. One is the user experience. The other is the design and implementation of the app.

(2) There are two states (of the `Model`) here. One is the `state` that was passed to `view` to generate the HTML that the user sees (or screen reads etc). The user can change that HTML, by typing into a text box. Call this `view_state`.

(3) The other state is the one most recently returned to Elm by the `update` function. Call this the `update_state`.

(4) Due to lag and timing issues, the two states may not be in strict lockstep. Relevant (and surprising) here is [Lockstep - Wikipedia](https://en.wikipedia.org/wiki/Lockstep).

(5) Suppose the `view_state` contains a `PressOnce` button that vanishes after it is pressed. If the user is quick, or is a robot, the view can send two `PressOnce` messages to`update`.

(6) Here’s the result of [Never Trust User Input - Google Search](https://www.google.com/search?q=Never+Trust+User+Input).

(7) The `update` method in the Elm app should have an appropriate level of mistrust of the messages sent to it from the `view` generated HTML. Each `state` and so each `view_state` has a version / sequence number.

(8) Having the view HTML return this version number as part of every message might help the `update` message to be appropriately suspicious. The `update` could treat the version number as a security token which can expire.

(9) What is appropriate user experience depends on the context. In some situations, presenting a [Modal window - Wikipedia](https://en.wikipedia.org/wiki/Modal_window) is the right thing to do. Wikipedia says

> A modal window creates a mode that disables the main window but keeps it visible, with the modal window as a child window in front of it. Users must interact with the modal window before they can return to the parent application.

(10) A banking app might present a modal window whose HTML can generate only two messages, namely `Confirm` or `Cancel`. This might be inappropriate in a gaming app.

(11) While typing this message, Discourse shows at the foot of the page an _OK, Buffering or Blank_ icon. Perhaps this is a visual indication of the the mismatch if any between what I’ve been calling the `view_state` and the `update_state`.

(12) If you draft a reply to this message, you’ll have a demonstration of what I mean. You don’t have to send the draft message.

[Next page](https://discourse.elm-lang.org/t/preventing-invalid-states-in-update-function/7060.md?page=2)
