24 Nov 2021
5 min read
Developers typically encounter Elm when they want to make a dynamic web application—something Elm excels at. There are already great guides which introduce Elm for that purpose. The very first example in the Elm Guide is a counter app that lets you increment and decrement a number.
<ul> <li>apples</li> <li>oranges</li> <li>bananas</li> </ul>
Why can't we just write
<li> for item in ["apples", "oranges", "bananas"]</li>? HTML isn't very DRY.
CSS has many of the same limitations. While new CSS features like CSS variables certainly mitigate the issue of code reusability, it still isn't a programming language. CSS nesting, for instance, is still a working draft, and not yet implemented in any browser. This is why there have been so many HTML and CSS preprocessors: SASS/SCSS for CSS, Pug for HTML. Each tries to make HTML and CSS into more of an actual programming language.
Enter Elm. It's a delightful language for modern web programming. Elm has Haskell-inspired syntax, and takes inspiration from other languages, as well. It's type-safe, but with optional type annotations. This means that errors are usually discovered at compile time, rather than at runtime. That means that if it compiles, it's very likely to run without errors from then on. The compiler error messages are friendly, and so is the community, which is very open and supportive. Even though it's a new language, it has seen a lot of adoption already in the industry, and has a ton of packages available for it. Elm compiles to HTML, CSS, and JS, so instead of wrangling those three languages (or three analogous preprocessor languages), you just write Elm, and it handles the rest.
Here's the bare minimum web page you can make with Elm.
module Main exposing (..) import Html exposing (..) main = text "hello world!"
You can run this example here on Ellie, if you don't yet have Elm installed.
What's happening here?
text, as well as the other Html functions we'll use, are in the HTML Module, which we have to import.
text "hello world"instead of
text("hello world")as it would look in Python-like languages.
Now let's prototype a toy web page, about whether puppies or kittens are cuter:
module Main exposing (..) import Html exposing (..) import Html.Attributes exposing (..) main = main_  [ h1 [ style "color" "red" ] [ text "Puppies or kittens?" ] , p  [ text "This page considers the problem of whether puppies or kittens are cuter." ] , img [ src "https://placekitten.com/g/400/400" ]  ]
Here's what's going on here:
[ a, b, c ]
p [ attribute1, attribute2 ] [ element1, element2 ]. Thus, the
main_function has no attributes, but has three children:
styletakes two arguments, the CSS selector, and its value.
We can DRY out this website, by abstracting away functionality that repeats. For instance, if we want two kitten photos, instead of writing two
<img src=""/> tags, we can write a function that will do both.
Functions that take parameters look like this:
greet name = "Hello" ++ name ++ "!". The
greet function takes the
name argument, and inserts it into the greeting, such that calling
greet "Jonathan" returns
So if we want to have two images, one which loads a placeholder kitten image from
https://placekitten.com/g/400/400 and another from
https://placekitten.com/g/300/300, we can write that like this:
module Main exposing (..) import Html exposing (..) import Html.Attributes exposing (..) kitten size = img [ src ("https://placekitten.com/" ++ size ++ "/" ++ size) , style "border" "1px solid red" ]  main = main_  [ h1 [ style "color" "red" ] [ text "Puppies or kittens?" ] , p  [ text "This page considers the problem of whether puppies or kittens are cuter." ] , kitten "400" , kitten "300" ]
Alternatively, you can write your site in Markdown:
module Main exposing (..) import Html exposing (..) import Html.Attributes exposing (..) import Markdown exposing (toHtml) content : Html msg content = toHtml  """ # Apple Pie Recipe 1. Invent the universe. 2. Bake an apple pie. """ main = content
To run this example in Ellie, you should install the package Markdown using the sidebar to the left.
"""are for multi-line literal strings.
Once you've outgrown Ellie, and want to build pages locally, download installers from here. Or install via npm if you already have node:
npm install -g elm. That enables you to run
elm build to generate your site from a Main.elm file.
Ground Floor, Verse Building, 18 Brunswick Place, London, N1 6DZ
108 E 16th Street, New York, NY 10003
Join over 111,000 others and get access to exclusive content, job opportunities and more!