Elm - what is it good for?

Introduction to Elm

Elm is a small but expressive language for building purely functional user interfaces for the browser. Elm code compiles down to JavaScript/HTML so our dream of writing JavaScript without actually writing any JavaScript may finally be here! All values in Elm are immutable and it is a statically typed modular language, syntactically quite similar to Haskell.

But what's so good about Elm and why should you bother learning yet another programming language? Well. Firstly, we need something other than JavaScript for the frontend devs to play with. Secondly (and on a more serious note): Signals. Signals are the key feature of Elm and the reason it is very much of interest to the bleeding edge community. In order to really understand the power of Signals and how to use them would take an entire afternoon, but in simple terms, a Signal is "a value that changes over time" which you can sample and react to in discrete or continuous intervals. A Signal can be of any type (String, Int, Tuple, Record) and can denote anything, for example, the mouse position on the screen, the width and height of the browser window, the collection of currently pressed down keys etc. The reason this is such a groundbreaking language feature is that gets rid of the need for callbacks when modelling change over time. All Elm programs end up with a very clear MVC pattern and the use of Signals prevents async issues like the Model getting out of sync with the View.

Hello, World!

But let's go back to basics. First things first! Everybody loves a good Hello World.

[gist id="e6ff84252fb67bca0957" file="Hello.elm"]

Neat! But this brings us quickly to the biggest problem Elm has so far as a frontend language... file size. The size of the compiled version of the above code is 288KB (for comparison, the latest version of jQuery is 252KB). The reason the compiled file is so big is that even though all I'm doing is printing out "Hello, world!", in order to compile that Elm code into JavaScript, the entire Elm core library (and any dependencies I've installed, e.g. the html module) need to be included. This means that the file size is going to grow more logarithmically rather than linearly as your app gets bigger, but the reality is that you start out with a huge source file for not a lot of content.

This is a shame because otherwise there is an amazingly risk-adverse way to try out an Elm component in your existing application: after compiling your code, you can simply embed it to any div in an existing application with just 2 lines of JavaScript!

In order to do this, simply compile your Elm code into JavaScript with

>> elm make Hello.elm --output=app.js

And embed this file in your index.html like so: 

Elm embed in div
Elm embed in div

The only thing to watch out for is that Hello.elm must have a module declaration at the top of the file. In this case, it would have to be module Hello where. This is needed because we're using the module name to initialize the app. The Elm component can then send/receive values from the rest of your application using Elm's Ports system.

Alternatively you can launch the Elm app fullscreen like so:

Elm fullscreen
Elm fullscreen

Documentation and Partially Applied Functions

One of the things that threw me when I first started looking at Elm documentation was the way method signatures are written. For example, take a look at the method signature for the repeat function in the String module:

>> repeat: Int -> String -> String

We can kind of infer what the function does: it takes in an Int and a String and returns the String repeated Int times. However, there is no distinction between the separators of input and output values: an arrow is used for both. It is implicit that the last value in the method signature is the type of the return value. There is actually a really good reason for this and it is to do with partially applied functions. Here's the String.repeat function in the Elm REPL:

Elm String.repeat
Elm String.repeat

And this is the same function but with an intermediate step where we create a partially applied function:

Elm String.repeat partially applied
Elm String.repeat partially applied

Notice that at each step, we get a printout of the current method signature and it goes from

>> Int -> String -> String

>> String -> String

>> String

Partially applied functions are supported in plenty of languages, but there is something really nice about having the method signatures actually written in a way that encourages actually understanding and using them.

Signals

This is the core feature of Elm. This is what makes the language so neatly reactive.

[gist id="d4ca611a48700e32ef76" file="Window.elm"]

The above code listens to the Window.dimensions Signal which broadcasts a tuple of the window width and height in pixels. The area function is applied to this these values and the result displayed in the browser. You can try this in the online editor. Resize the window and see the value dynamically update. Yay.

Side note: method signatures in Elm are actually optional! The above code would still work if I removed them, however once you include them, the Elm compiler will check that they match what the function does and not compile if there are any discrepancies.

Mailboxes

Mailboxes are basically "signals that have an address you can send messages to". You can use them for reacting to UI events.

[gist id="cf8b199dc181001c18f9" file="Mailbox.elm"]

Here, I have defined a Mailbox for a String, and an Input field with essentially an onChange event handler. Whenever the text content of the input field changes, I call an anonymous function which passes the changed text into the Mailbox address. This same value is printed out to the page in the paragraph below.

Again, feel free to copy/paste this code into the online editor to try it out yourself. Or read more about Mailboxes here.

So... the future?

"Should I write my next eCommerce site in Elm?" ... I think we're not quite there yet. But I it has huge potential. In fact, integrating Elm into an existing React/Flux application has been done before with huge success! The article also includes a tutorial on how to port a store from the Flux TodoMVC example to Elm.

Writing Elm is fun. It's a bit of a challenge as the online community is very small still (Googling for a "common" Elm problem will usually not get you to a solution). On the plus side, Elm compiler preemptively picks up on any runtime errors so you'll never see undefined is not a function ever again. I'd say that alone makes it worth giving it a go.

There're a few resources to get started with. Read the documentation.Learn by example.Do an online course.Try out the online editor.

And if you like it, come to our special Elm edition of Functional Programming for the Web with Evan Czaplicki who will perhaps convince us why we should write our next eCommerce site in Elm.

Kadi Kraman

Software Engineer

More from Kadi