Msg Passing

Jon Yurek

The three major ways to communicate with the outside world in the Elm Architecture are Cmd a, Sub a, and Html a. This is a curious thing to say, because none of those types do anything, in the imperative sense. Regardless, it’s tempting to think of Http.send as a function that kicks off an XmlHttpRequest() in the browser and you get the result as what you defined as your Msg type.

It’s also tempting to think of that Time.every 60000 subscription as starting a setTimeout. Then you just wait for the every-minute callbacks to roll in.

This is convenient to think about, but it’s wrong. It’s not very wrong, but it’s wrong in some important ways that can hamper understanding. So, yes, the end result of the Http.send is that a request is fired off to the API you want to hit. And the end result of Time.every is that you get a callback every so often. The difference, though, is that it’s not “your code” doing it. It’s the Elm Runtime.

I’m going to focus on Cmd a here because that’s the most straightforward case, but both Sub a and Html a deal with things in a similar manner.

Msg In a Bottle

The first important thing to note is that little a. This makes Cmd a a parameterized type the same way that a List a is a parameterized type. And just like a List String describes a List that deals with Strings, a Cmd String describes a Cmd that deals with a String. The Cmd part tells Elm “This value represents a thing I want you to do” and the String tells Elm “and when it’s done, use this value to tell me about it.”

You might see (and probably will see) people using Cmd Msg fairly often. Msg isn’t magical, it’s a union type that anyone can define for themselves. Each tag in the union is a kind of response that you’re looking for. The name “Msg” is just a convention as to what Elm programmers should call this data type.

Imagine you have a personal assistant for a second. You give them a note that says “Buy 2 apples and give them to me.” and they do. It’s their job, after all. And they come back and say “I got you the apples you asked for”. The assistant in this scenario is a metaphor for the Elm Runtime, which actually does the things your Cmd as specify. The important thing to know is that you are not doing the action. You’re telling the Elm Runtime to do the action (“Buy 2 apples”) and to let you know how you want to be told when it’s done (“Give me the apples”).

Tell her it's for Creed. She'll know what that means.

OK, so that’s great. I can tell the Elm Runtime to do something for me, but I have a whole application here. I’m a busy developer. Stuff needs to get done! I have to do more than one thing at a time!

Cmd a is the equivalent of handing your assistant a note with instructions on it. Fortunately, we can do more. With Cmd.batch you can combine multiple commands into one. How do you tell someone to buy multiple things? Same way: you batch all the things you want up into one shopping list and hand them the list. Voila! You cam have you assistant buy Apples, buy Cereal, make a request to an API, and buy Potatoes all in the same trip.

And all this hangs together because of the way that Elm treats effects as data. In an imperative language (like Ruby or JavaScript), when you call a function, something gets done. In Elm, when you call a function a piece of data is produced. The Elm Runtime knows that these pieces of data contain instructions for something you want done, so it does them. This gives us a way to reason about and with those effects (like organizing them to run most efficiently). It also gives us a conceptual purity, because we can treat all these bits of data like any other bits of data. They’re not magical – unless you want to call “a program knows to do something with it” magical, in which case all programming is kinda magical.

Tell Me When It Closes

The conceptual model that we’re talking about here is that you’re telling the Elm Runtime to handle something on your behalf and then waiting for it to be done. And then, because you told Elm how to tell you, it sends you the message you were expecting.

Like the wonderful Tell Me When It Closes, you offload the stress of having to worry about you actions to someone else.

It took me some time to really grok what was going on with the pattern of types that deal with Msg and how it fits into the architecture and my thinking. But once it clicked for me, the whole way of “doing things” and the way it doesn’t really involve doing things yourself finally came into focus. Sub a, Html a, and ports all operate on more or less this same style of getting things done.