dark mode light mode Search Menu


How do you make a web page? Normally, you have to write code in a combination of languages: HTML, CSS, and JavaScript. The HTML you write determines what elements appear in the page. The CSS determines how the HTML looks. The JavaScript gives the whole page life and interactivity.

Elm, though, is a single programming language designed to compile to actual, functional web pages! In other words, you write Elm code and the Elm compiler turns it into the CSS, HTML, and JavaScript that makes up the final page.

Elm is a relatively new functional programming language. It both looks and feels a lot like if JavaScript and Haskell had a baby: a particularly feisty baby that immediately gave the React framework some competition.

Now, I have to say that I always like learning new programming languages, which is why I write these articles! Elm in particular, though, was probably the most fun I’ve had with a new programming language in a very long time. I won’t say it’s easy, particularly if you haven’t done much functional programming before, but it’s very satisfying.

To get started with Elm, you can go to the language’s homepage and even follow along with our examples by clicking the “Try Online” button.

There’s a few examples in the online Elm editor, but here’s our example: a super tiny Elm program that lets you enter strings into an input and then it makes a little palindrome out of what you typed.

import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onInput)
main = Html.beginnerProgram {model = "",
                            view = viewFunction,
                            update = updater}
type Msg = TextChanged String
viewFunction s = div [] [input [onInput TextChanged] [],
                        text (s ++ (String.reverse s))]
updater : Msg -> String -> String
updater msg s = case msg of
                   TextChanged s2 -> s2

For this tiny program, it compiles to the webpage shown below:

Here I’ve used the developer tools in Chrome so we can simultaneously see the web page on the left and the structure of the HTML on the right. Try matching up the HTML you see in the picture with what’s in the viewFunction in the Elm code. The div, input, and text all appear in the final page.

This function creates the HTML of the page from special data called the model. In our little program, the model is just a string. We call the function that builds the HTML the view. The view is also called to update the HTML every time the model changes.

What part of the code above changes the model? It’s the updater function. The updater has a very important job. It receives messages that represent something happening in the user interface—you clicked a button, typed in an input field, or moved the mouse—and uses the message to decide how to update the model. Messages in Elm aren’t that much different than messages in Twine except that:

  • You define them yourself
  • They can carry data, like in our case the TextChanged message holds the new string from the input field

We come to the final piece of the puzzle: who sends the message to the update function? The view does. Up above we have this snippet of code:

input [onInput TextChanged] []

The function input creates the HTML of the input but it also creates the JavaScript code for an event handler. In this case, Elm is registering an event handler for the oninput event that fires in your browser whenever you type in an input field. This event handling code is going to send the message TextChanged to the function updater.

Now we’ve tied the loop together: the view reads the model and renders HTML that the user can interact with, the event handlers created by the view send messages to the update function when the page is used, the update function reads the message and changes the model, when the model changes the view re-renders the page.

The Html.beginnerProgram is the Elm function that does this loop-tying. You give it the starting model, the view function, and the update function, and it builds the code that connects all those pieces together.

Now that we’ve gotten a feel for a complete Elm program, I want to bring up its type system. Unlike something like JavaScript, Python, Ruby, Clojure, etc. there’s a typechecker that goes through the program and makes sure that the program doesn’t misuse data. If you’re familiar with a language like Haskell, Purescript, ML, or the like then you might be used to the kind of type system that Elm has.

If you’re only exposure to typechecked languages is something like C or Java then, well, this is going to be a little different. First, instead of writing types of functions like:

int mySillyFunction(int arg1, int arg2){

In Elm you’d put the type signature and the actual definition are on different lines entirely:

mySillyFunction : Int -> Int -> Int
mySillyFunction arg1 arg2 = ...

The type signatures in Elm are largely optional. You can write them when you need to clarify things for yourself, but like in our example above you can leave them out and Elm will first infer types before checking them. This is a really cool feature that languages like Haskell, ML, and Elm have: it lets you write code that looks like an unchecked language but with higher assurance that the code is correct.

Now, we’ve only barely scratched the surface of Elm but hopefully it’s enough get you interested. Check out the links below to both my own examples and to other tutorials and interesting things about Elm!

Happy hacking!

Learn More

Purescript, another language that compiles to JavaScript but looks like Haskell


The Elm site


Mozilla’s guides to web programming the CSS/HTML/JavaScript way


A book on Haskell, one of the languages that inspired Elm


Clarissa’s repository of example Elm code