(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.