# Minimising the use of \_-\>

**URL:** <https://discourse.elm-lang.org/t/minimising-the-use-of/1885>\
**Category:** Learn\
**Created:** [September 4, 2018, 7:13pm UTC](https://discourse.elm-lang.org/t/minimising-the-use-of/1885 "2018-09-04T19:13:42Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jess\_Bromley](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/jess_bromley/32/3396_2.png) [@Jess\_Bromley](https://discourse.elm-lang.org/u/Jess_Bromley)\
**Post date:** [September 4, 2018, 7:13pm UTC](https://discourse.elm-lang.org/t/minimising-the-use-of/1885/1 "2018-09-04T19:13:42Z")

</div>

I have been a great fan of the fact that Elm forces you to consider every possibility in `case` expressions, and readily understand how much safer this makes it to “just change” code and know that the compiler will make sure you consider all the consequences of the change.

Until recently I happily accepted that the price for this is that sometimes one must write “unnecessary” code (e.g. sometimes you know a `Maybe` will never be `Nothing`), and have been doing my best to avoid `_ ->` constructs wherever possible.

But recently, in trying to embrace the ideas from Richard Feldman’s talk about “making impossible states impossible”, I have found myself regularly using custom types rather than records for my `Model` and I find this leads to me resorting more and more to `_ ->` in my `update` loop. I’m hoping someone can suggest a better design pattern to avoid this, or explain how they deal with it…

Let me illustrate the problem with a toy example. Say I have a `Model` with four states:

```auto
type Model
    = Init FormData
    | Running Document Status
    | PopupDialog PopupState Document Status
    | FatalError String

```

where `FormData` is a record containing `String` fields I need the user provide to start my application, e.g. maybe an address to connect to in order to retrieve some data, a password, the name of the data etc. etc. Most of this will never be needed again once the application is initialised and those things that are needed will no longer simply be strings but instead become an integral part of the `Document` which I actually get back and where the major work of the application takes place. Additionally I want to model some kind of dialog that might need to appear on top of this work (maybe when the user wants to commit changes back to the Document’s source, or if there is a conflict etc etc), and be able to tell the user when something unrecoverable has gone wrong.

The `Msg` type for my `update` loop would thus look something like:

```auto
type Msg
    -- Init related messages
    = AddressChanged String
    | PasswordChanged String
    | ResourceNameChanged String
    | SubmitRequest
    -- Init -> Running transition related messages
    | DocumentReceived
    | RequestError String
    -- Running related messages
    | DocumentEdited String
    | VerifyDocument
    | AddComment Position String
    | EditComment Position String
    | DeleteComment Position
    | StatusChanged Status
    | CommitChanges
    -- PopupDialog related messages
    | CancelPopup
    | PopupFieldChanged String
    | PopupTickBoxChecked Bool
    | SubmitPopup

```

The problem now is how best to organise the `update` loop. There only seem to be two choices.

# Choice 1

```auto
update msg model =
    case model of
        Init formData ->
            case msg of
                -- Handle all Init and (Init -> Running transition) related messages
                ...
                -- Explicitly ignore each and every other message, or else resort to "_ ->"

        Running doc status ->
            case msg of
                -- Handle all Running related messages
                ...
                -- Explicityly ignore each and every other message, or else resort to "_ ->"

        PopupDialog state doc status ->
            case msg of
                -- Handle all PopupDialog related messages
                ...
                -- Explicitly ignore each and every other message, or else resort to "_ ->"

        FatalError err ->
            -- This time we really can safely ignore everything!
            ( model, Cmd.none )

```

But the problem is as each state becomes more complex the more messages there are to explicitly ignore and eventually the temptation to just use `_ ->` is overwhelming, but that of course makes the code fragile to changes.

I mulled over the idea of instead using `_ -> FatalError "Incorrect message received"` and then removing it in production. But the problem is sometimes a non-relevant message _may_ in fact occur and _should_ be ignored (e.g. the user accidentally double clicks/double touches the submit button during the `Init` process and the second copy of the event/message arrives when we have already transitioned to `Running`).

# Choice 2

```auto
update msg model =
    case msg of
        AddressChanged newVal ->
            case model of
                Init formData ->
                    -- return an updated FormData, possibly applying verification first

                -- Explicitly ignore each and every other model pattern/subtype or resort to "_ ->"

        PasswordChanged newVal ->
            case model of
                Init formData ->
                    -- return an updated FormData, possibly applying verification first

                -- Explicitly ignore each and every other model pattern/subtype or resort to "_ ->"

        ...

```

This at least ensures that _every_ message type is always handled, but even with only a few different `Model` patterns/subtypes to match on requires _a lot_ of writing code to ignore messages or resorting to `_ ->`. Although it instinctively feels somehow less dangerous to use `_ ->` when pattern matching on the `Model` than on the `Msg`.

# Choice 3

Okay, so actually there is a third choice I can think of, which is to split all or some of the different `Model` subtypes off into separate “pages” each with its own message type and update loop as in the standard SPA example. But this feels quite a big thing to do. I am finding that many of my applications fall in to the category where they don’t feel big enough to break into separate “pages” but are nevertheless large enough that it becomes very hard not to resort to liberal use of `_ ->` in the `update` loop.

–

**So the question is:** is there a fourth choice/design pattern that I’m missing? How do others deal with this when using a custom type for their `Model`?

Thanks! And sorry for such a long post, but I couldn’t see how to explain it without a fair bit of code to show what I meant…

---

<div class="post-metadata">

**Author:** ![Sebastian](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/sebastian/32/98_2.png) [@Sebastian](https://discourse.elm-lang.org/u/Sebastian)\
**Post date:** [September 5, 2018, 1:51am UTC](https://discourse.elm-lang.org/t/minimising-the-use-of/1885/2 "2018-09-05T01:51:44Z")

</div>

I would like to know what is a better pattern for this too.

I have seen something like:

```auto
case (model, msg) of
        (Init formData, AddressChanged newVal) -> 

```

This allows to have one failing `_ ->` at the end. But we have avoided this because it makes the Elm 0.18 compiler quite slow. I’m also not sure if this is clearer at all.

We use pattern #2 from above quite a lot in our app.

We avoid reusing messages when we have this pattern, so we have something like:

```auto
type Msg
    = Stage1_DoSomething
   | Stage2_DoSomethingElse

```

Because of this we only have two branches for a message. The one with the correct model and the one with any other model, in this case we use `_->`.

---

<div class="post-metadata">

**Author:** ![joakin](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/joakin/32/171_2.png) [@joakin](https://discourse.elm-lang.org/u/joakin)\
**Post date:** [September 5, 2018, 12:16pm UTC](https://discourse.elm-lang.org/t/minimising-the-use-of/1885/3 "2018-09-05T12:16:08Z")

</div>

I think this depends a lot on what exactly you are modelling, so the answers will be better the more specific your question is.

For this specific example you mention, another thing you can do, if it fits your design goals and current situation, is to create custom types for the messages that align with the constructors of the model. Something like this:

```elm
    type Model
        = Init FormData
        | Running Document Status
        | PopupDialog PopupState Document Status
        | FatalError String

    type Msg
        = InitMsg InitMsg
        | RunningMsg RunningMsg
        | PopupDialogMsg PopupDialogMsg

    type InitMsg
        = AddressChanged String
        | PasswordChanged String
        | ResourceNameChanged String
        | SubmitRequest
        | DocumentReceived
        | RequestError String

    type RunningMsg
        = DocumentEdited String
        | VerifyDocument
        | AddComment Position String
        | EditComment Position String
        | DeleteComment Position
        | StatusChanged Status
        | CommitChanges

    type PopupDialogMsg
        = CancelPopup
        | PopupFieldChanged String
        | PopupTickBoxChecked Bool
        | SubmitPopup

    update msg model =
        case ( model, msg ) of
            ( Init formData, InitMsg initMsg ) ->
                case initMsg of
                    AddressChanged str ->
                        Debug.todo "Do things"

                    PasswordChanged str ->
                        Debug.todo "Do things"

                    ResourceNameChanged str ->
                        Debug.todo "Do things"

                    SubmitRequest ->
                        Debug.todo "Do things"

                    DocumentReceived ->
                        Debug.todo "Do things"

                    RequestError str ->
                        Debug.todo "Do things"

            ( Running doc status, RunningMsg runningMsg ) ->
                Debug.todo "Match only on RunningMsg states"

            ( PopupDialog popupState document status, PopupDialogMsg popupDialogMsg ) ->
                Debug.todo "Match only on PopupDialogMsg states"

            ( _, _ ) ->
                Debug.todo
                    ("We don't have messages right now that are not namespaced or global to all model states"
                        ++ "And FatalError doesn't seem to use any messages to do anything so ignore the rest of options"
                        ++ "So ignore anything that comes here."
                    )

```

By doing this, I think the code easily shows a few things:

- `FatalError` doesn’t have any interactivity, as it has no related messages
- Each stage (constructor) of the model type have a set of isolated messages it interacts with, so it is a fairly well isolated state machine
- If you add new steps to a stage, the pattern matching will help you add the new code
- We default to ignoring messages from other stages as the preferred strategy. But we could do something different (error reporting) or add specific clauses to the main case to catch specific messages/state pairs and report errors or do state transitions. If this happened though, I’d give a second look to the interactions to see how this could be avoided.

If this starts getting very big, I’d make some functions for the different sub-case functionality, like:

```elm
updateInit : InitMsg -> FormData -> (Model, Cmd Msg)

updateRunning : RunningMsg -> Document -> Status -> (Model, Cmd Msg)

```

Those functions could make the state transitions and transition to a different model constructor stage. Playing with types here also brings a lot of information, for example, if `updateInit` doesn’t return a `Cmd Msg` then you know it doesn’t produce side effects, or if instead of returning a `Model` it returned a `FormData` then you would know that function would never transition model to a different stage.

Like I said at the beginning, the modelling and design is very specific to the particular use case, specially because you can use the type system and language tools to get the biggest benefits for your particular use cases.

---

<div class="post-metadata">

**Author:** ![Jess\_Bromley](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/jess_bromley/32/3396_2.png) [@Jess\_Bromley](https://discourse.elm-lang.org/u/Jess_Bromley)\
**Post date:** [September 5, 2018, 7:14pm UTC](https://discourse.elm-lang.org/t/minimising-the-use-of/1885/4 "2018-09-05T19:14:17Z")

</div>

Thanks! I really like the idea of creating `update` functions that are more specific to both message and model subtype/pattern.

I definitely think splitting messages into subtypes will help with a lot of my projects.

Unfortunately I do have one thing I’m working on at the moment that doesn’t easily fit into that category: I have `NetworkMsg` messages that reflect loss of connections, receipt of data, etc. that need to be handled by multiple, but not all, different model states. I’ll have to have another look at that project to see if there’s a way I can split this up to make things easier along the same lines…

If not I’ll maybe post the specifics to see if there’s something I’ve missed.

Thanks again 🙂

---

<div class="post-metadata">

**Author:** ![system](https://canada1.discourse-cdn.com/flex035/uploads/elm_lang/original/1X/50a05e53677a2c3b47776d7abd0f113eb50193a1.png) [@system](https://discourse.elm-lang.org/u/system)\
**Post date:** [September 15, 2018, 7:14pm UTC](https://discourse.elm-lang.org/t/minimising-the-use-of/1885/5 "2018-09-15T19:14:19Z")

</div>

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.
