The Pragmatic Studio

What Is Elm? Essentials of the Elm Language

July 23, 2015

Elm is getting a lot of play these days, and you might be wondering what all the fuss is about. Here’s a quick overview of the essentials for the curious…

What is Elm, in under 144 characters?

Elm is a functional programming language that compiles to JavaScript and runs in the browser.

What makes it a functional programming language?

In simplest terms, Elm programs are a collection of functions. For example, here are a few familiar functions, Elm-style:

greet name =
  "Howdy, " ++ name ++ "!"

triple number =
  number * 3

add x y =
  x + y

OK, but isn’t this just like a method in my object-oriented language?

The important difference is Elm functions don’t run in the context of an object where they share state with other functions. An Elm function is stateless: it simply transforms its inputs into its output, with no side effects. Given the same inputs, a function always returns the same output.

And that’s important because… ?

Well, for starters, it means refactoring is easier because you can move code around without worrying about stuff outside the function. And the code is easier to understand in general. With a stateless function, what you see is what you get.

I heard immutability was also an important part of functional programming. What’s Elm got to say about that?

Elm is unabashed on this topic: All values in Elm are immutable! Instead of mutating data, we always transform it into something new. For example, here’s an Elm record representing an item in inventory:

item = { name = "Wool Mittens", quantity = 10 }

Here’s how to decrease the quantity by one:

new_item = { item | quantity = item.quantity - 1 }

We get a new record with the updated quantity field, and the original item record is unmodified.

Now that we’ve got the functional bases covered, what’s the quickest way to start writing Elm code?

Jump in the online editor and paste this classic first program into the left-hand pane:

import Html exposing (text)

greet name =
  "Howdy, " ++ name ++ "!"

main =
  text (greet "World")

Then hit the “Compile” button (or use the keyboard shortcut CTRL-RETURN) and you’ll see the result in the right-hand pane.

Do I have to be a math nerd to get into functional programming?

Absolutely not! Can I share a secret? I’m fairly miserable when it comes to anything beyond basic math. So math examples aren’t a big language selling point for me. Instead, I usually start learning a new language by formatting some strings. Here’s a version of that greet function that shouts and echoes a greeting through a series of transformations:

greet name =
  "Howdy, " ++ name ++ "! "
    |> String.toUpper
    |> String.repeat 3

But if you’re the mathy sort, here’s a familiar function:

factorial n =
  if n <= 0 then 1 else n * (factorial (n - 1))

Or if you think more in terms of pattern matching, here’s the equivalent:

factorial n =
  case n of
    0 -> 1
    _ -> n * (factorial (n - 1))

Who created Elm?

Evan Czaplicki originally designed Elm as his thesis in 2012 and currently works full time on Elm at NoRedInk. He’s a bright, friendly guy who keeps his eye on the big picture while understanding all the details. I instantly liked Evan and continue to be impressed by the care he takes with this language.

How do you pronounce his name?

It’s like the number seven, but without the “s”.

No, his last name?!

Ah, it’s like “Czaplicki”, but without the “C”. :-)

What is Evan’s motivation behind Elm?

His keynote at the Curry On conference gives great insight into his motivations. It’s a great keynote—you should watch it right now!

So what can I actually build with Elm?

Well, building web apps with Elm is a delight using the elm-html package. There’s no separate templating system with its own unique syntax—it’s all just Elm code! Here’s a trivial example that generates an HTML list:

import Html exposing (..)
import Html.Attributes exposing (..)

featureItem name =
  li [ class "feature" ] [ text name ]

featureList features =
  ol [ id "features" ] (List.map featureItem features)

main =
  featureList ["Functional", "Reactive", "Fun!"]

Is the HTML rendering fast?

Blazing fast!

What’s the deal with Elm being reactive? Will I glow in the dark after programming Elm?

It really depends on how much time you spend programming. If you limit your exposure to a couple hours at a time, you should be fine. But results may vary as we only have a small sample set of Elm programmers to draw from.

No, I mean as in functional reactive programming?!

Ah, sorry. In modern programming parlance, “reactive” is one of those slippery words that’s hard to pin down. Reactive applications, in general, respond (or react) to data that changes over time, such as user input. Here’s an example of tracking thumbs up and thumbs down button clicks you can try in the online editor:

module ThumbCounter exposing (..)

import Browser
import Html exposing (..)
import Html.Events exposing (onClick)

initialModel =
  { thumbsUp = 0, thumbsDown = 0 }

type Msg = ThumbsUp | ThumbsDown

view model =
  div []
    [ button [ onClick ThumbsUp ] [ text "Thumbs Up" ]
    , div [] [ text (toString model) ]
    , button [ onClick ThumbsDown ] [ text "Thumbs Down" ]
    ]

update msg model =
  case msg of
    ThumbsUp ->
      { model | thumbsUp = model.thumbsUp + 1 }

    ThumbsDown ->
      { model | thumbsDown = model.thumbsDown + 1 }

main =
  Browser.sandbox
    { init = initialModel
    , view = view
    , update = update
    }

You may notice this program follows a popular webapp pattern: it has a model (an Elm record) representing the application state, a view function that renders the model as HTML, and an update function that transforms the model from one state to the next depending on a user action represented by a message. This simple pattern is known as the Elm Architecture.

Can I integrate Elm into my current web project?

You bet! Just feed your .elm file into the elm make utility and it spits out a JavaScript file:

elm make ThumbCounter.elm --output thumb-counter.js

Then include the generated JavaScript file in an HTML file:

<script src="thumb-counter.js"></script>

And kick off the Elm program to run in a specific DOM node on the page:

<div id="elm-app-runs-here"></div>

<script>
  Elm.ThumbCounter.init({
    node: document.getElementById("elm-app-runs-here")
  })
</script>

So here’s the full HTML file:

<!DOCTYPE html>
<html>
  <head>
    <script src="thumb-counter.js"></script>
  </head>
  <body>
    <div id="elm-app-runs-here"></div>
    <script>
      Elm.ThumbCounter.init({
        node: document.getElementById("elm-app-runs-here")
      })
    </script>
  </body>
</html>

You can use this technique to have an Elm program take over any DOM node!

Do I need to know any JavaScipt at all to use Elm?

For starters, just those one or two lines above. Otherwise Elm doesn’t assume you know any JavaScript.

But can I use my favorite JavaScript library in my Elm app?

Nah, we don’t allow any of that crazy stuff ‘round here. It’s entirely too unreliable. The Elm compiler even has a special two-pass process whereby it detects hand-written JavaScript and effectively turns it into a no-op. Safety first and all. (Admit it, I had ya going there!) Actually, interop with JavaScript is embraced by Elm. You can send messages from Elm to JavaScript and vice versa using ports.

And there’s a REPL, right?

Yup! I wouldn’t consider using a new language without one:

$ elm repl

> numbers = List.range 1 10
[1,2,3,4,5,6,7,8,9,10] : List Int

> numbers = [1..10]

> List.sum numbers
55 : Int

> List.map (\n -> n * 2) numbers
[2,4,6,8,10,12,14,16,18,20] : List Int

> List.filter (\n -> n < 5) numbers
[1,2,3,4] : List Int

> :exit

I heard it’s a strongly-typed language. I love me some dynamic language. Do I have to go back to declaring types?

No, it’s not required. In fact you won’t notice any type declarations in the examples above. Elm is a statically-typed language and yet we don’t have to declare any types because the Elm compiler automatically infers most types.

When I first started using Elm, I was glad type declarations were optional. But can I tell you something I thought I’d never say after using Ruby for over a decade? I find that declaring types in Elm help me think through and accurately document the “contract” of functions, which clarifies their intent for me and other folks who may come along and read the code.

Give it a try. I think you’ll be surprised by the benefits of static typing in this modern language.

Is the compiler as awesome as everyone says?

Yes! Honestly, I don’t even think of it as a compiler in the traditional sense. It’s more like a friendly assistant you wouldn’t want to code without.

And is the debugger as awesome as everyone says?

Yes, and it just keeps getting better. In all fairness, the debugger is still rather new and experimental. However, it’s blazing a trail in fairly uncharted (and exciting) territory. We think it’s going to be a real game changer! In fact, we put together a 3-minute video on how the debugger might be used on a project to improve communication.

What kind of open source libraries are available for Elm?

The Elm package catalog has a growing collection of community packages.

How do I install packages?

The Elm package manager is a real treat. To install a community package, for example the elm/http package, use:

elm install elm/http

Will my code break when a new package version is released?

(I made up this question because the answer is so cool!)

Not likely. I love that the package manager automatically enforces semantic versioning for every package based on API changes. You can even get a diff of what’s changed between two versions of a package so you can upgrade with confidence:

elm diff elm/http 1.0.0 2.0.0

Why are you guys excited about Elm?

First and foremost, it’s designed to be fun and friendly to use. It embraces the good parts of functional programming, and with its clean and readable syntax, world-class tooling, and friendly compiler, Elm is truly a delightful language.

Don’t let its friendly face fool you though; Elm is also incredibly powerful and ready for the biggest projects. The Elm Architecture helps you create complex, modular web apps with code that stays easy to maintain as you add features. Toss in great performance, no runtime exceptions, and JavaScript interop, and you’ve got a super-charged way to produce reliable, scalable, and maintainable web apps.

But what we love most about Elm is that you can actually build practical stuff with it quickly!

OK, so here’s the big question: Is Elm for me?

I know, it’s tough to keep on top of everything that’s changing. Shiny things are fun, but learning something new comes with a cost. So you have to make smart investments.

Here’s what I can say: Learning Elm is what finally got me into functional programming. I believe that’s a skill I’ll continue to use through the rest of my career. So the payoff of learning Elm has been more than just new language syntax in my toolbelt. Learning Elm has made me a better all-around programmer. So for me, it’s totally been worth it.

To help you make a thoughtful decision, check out these 4 ways of knowing if learning Elm will be worth your time.

Cool. So what resource do you recommend for learning more about Elm?

Thought you’d never ask! Our popular Elm course walks you through how to build a reactive web app, step-by-step. It’s a great way to get introduced to functional programming. We designed this course to be the resource we would have wanted while learning Elm.

Build a complete Elm web app from scratch!

Quickly get up to speed with Elm and functional programming as you build a reactive web app step-by-step in our 3.5-hour Building Web Apps With Elm course.