Idea: Use e.onClick instead of onClick to reduce boilerplate

(0) I’d like it to be easier to use divide-and-conquer when writing larger apps. This post follow on from my post Why not use: update fn state = fn state. The responses there greatly improve my understanding, and helped me move forward. Thank you. In this longer post, I’ve made an effort to be clear and concise.

I hope the ideas in this post will help us reduce the boilerplate code needed to follow best practice. I’ve put a proof of concept up on Ellie: https://ellie-app.com/cz6ktBpCBRNa1. You might want to look at it first.

(1) A toy version of the problem is to combine two mini-programs into a slightly larger mini-program. And we want this to be easy. Suppose count and santa create the mini-programs as follows.

main = Browser.sandbox count
main = Browser.sandbox santa

(2) First we write something that works. It does what we want.

init = { count = count.init, santa = santa.init }

(3) Next we write something that usually fails, with a type mismatch.

view state =
    div []
        [ div [] [ count.view state.count ]
        , div [] [ santa.view state.santa ]
        ]

(4) This will happen, for example, if count uses Int as its message type, and santa uses String. As usual, to solve let’s define a union message type.

type Msg
    = CountMsg Int
    | SantaMsg String

(5) Now suppose that there’s new function mutate allows the message type to be changed after the Html has sent the message. We want something like this to work.

view state =
    div []
        [ div [] [ mutate CountMsg count.view state.count ]
        , div [] [ mutate SantaMsg santa.view state.santa ]
        ]

(6) Instead of mutating the message after the Html has sent the message, we could equivalently change the message type before the Html sends the message. Although more clumsy to use, it is something that can be done with Elm 0.19. If you’ve not done so already, now’s a good time to look at https://ellie-app.com/cz6ktBpCBRNa1

(7) I see no way of writing mutate in Elm 0.19. My idea could be used today, and later implemented in the core / compiler of a later version of Elm.

The function you need is Html.map
https://package.elm-lang.org/packages/elm/html/latest/Html#map

1 Like

Thank you @G4BB3R . Good response. This makes my life much easier (and gives me more confidence in my idea).

1 Like

Also, a piece of (I hope useful) unsolicited advice would be to avoid as much as possible “componentarization” of an app. What I mean by that is making small elements that have their own update function. This leads to much more boilerplate and message wrapping (with Html.map, Attribute.map, Cmd.map) and unwrapping in the parent update function. So if piece of visual element can be modeled of just state and view try to not extend it with updates and messages.

When you want to add events to a piece of view it is sometimes better to just inverse control and ask for a () -> Attribute msg or similar as argument of the view function.

1 Like

Thank you @mattpiz. Your advice is welcome. My next step is to rework my Ellie example using Html.map. I’ll then look at your advice again. (I’m a beginner, so gaining personal experience by making mistakes isn’t always a waste of time.)

To all: When I’ve got a Html.map example and more experience most likely I’ll start a new topic. I’d be grateful until then if you could quietly not post, and so let this topic close in 10 days time.

1 Like

If you have not already seen it, this talk is worth your time. It explains lots of techniques that you can (should) use before resorting to so called ‘nested TEA’:

‘Componentizing’ an Elm program is not always bad, it is still a useful technique. Once you learn it, you will probably go through a phase of componentizing everything before you begin to ask are there better ways?

I also think that in many programming languages boilerplate is understood as a bad thing that must be eliminated. So in Java or Angular we get lots of @Annotations, each of which is a short cut to some piece of boilerplate. But then hardly anyone has any idea what the program is actually doing and tracing bugs in the annotations is a nightmare. In Elm we do not regard boilerplate as a bad thing and prefer to be explicit over being concise. It took a good while of using Elm for me to appreciate this.

I like to compare Elm programs to the hardware design languages Verilog or VHDL when it comes to boilerplate. There you define units of logic, then explicitly wire them together. If you componentize things in Elm - you will need wiring.

3 Likes

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