Elm - "Haskell for the web"
Elm is a language that was mostly designed to handle web frontend development using functional programming and immutable languages. It was mainly inspired by Haskell, so you won’t have a hard time learning the language if you are familiar with Haskell and its strong typed, pure functional way. The philosophie of Elm is to find problems at compile time thanks to its strong typing and to have zero runtime errors.
In my professional software development career, I mostly did backend development.
Whenever a web frontend was needed, I relied on frameworks like Primefaces
or ZK
so that the HTML, Javascript
and CSS details were mostly taken care of. I never really got into frontend development, partly because I was
reluctant to use Javascript as I think it is a language with a lot of unfortunate design choices where you often
only notice at runtime when something goes wrong. In my pet projects, I tried out a bit Vue.js which I really like
as it is not too invasive and very light weight, but you still have to use Javascript (or something like CoffeScript
or Typescript). As a big Clojure fan, I also tried ClojureScript, but it never really felt as the correct solution
for me. So I gave up again to find the language/framework to encourage me to improve my frontend development capabilities.
Then I read about Elm (in the excellent book Seven more languages in seven weeks
). As I recently rediscovered Haskell
Elm and its architecture felt like a good and fun way to do frontend development. The syntax came pretty naturally to me
as it is very similar to Haskell. Let me show you how to write a simple web application in Elm and demonstrate how it looks like.
Install Elm
Let’s start with the basics. First you’ll have to install Elm (the easiest way is via npm or download from the officialsite). At the time of writing version 0.19
was the current
version. There were a lot of incompatible changes in the previous versions of Elm, so if you read this post when a newer Elm version is available, some code may not work anymore. I’ll try to keep the code up to date…
Setup an empty elm project
- Create a directory where you want to create your object
- Open a shell (or similar console) and go into the directory
- execute the command
elm init
- Respond ‘Y’ when prompted, if you want to create an
elm.json
file - This will create a
src/
directory and aelm.json
file and nothing more
elm.json
contains the following code
As you can see, this will only setup a minimal project with dependencies to some important core packages. For our first example this is enough, but for more advance stuff there are better templates from which to start. I like it, because you really only get a simple project file from which to start without dependencies to tons of 3rd party libraries that you don’t know what they are good for.
The src/
directory is still empty, so we will create a new file named Main.elm
. Let’s add following content:
After creating this file, we can just compile it by running elm make src/Main.elm
.
This will create file index.html, which will contain the generated javascript code together with the Elm runtime. If you open the file in the browser, you will see “Hello World” appearing.
Write an integer calculator in Elm
So now that we saw the obligatory “Hello World”, we can do something slightly more complex: a calculator! With this calculator, we will type in two numbers and it will return all result from the basic arithmetic operators +, -, * and /, so for example for number1 = 12
and number2 = 3
it will return
12 + 3 = 15
12 - 3 = 9
12 * 3 = 36
12 / 3 = 4
For this exercise we will use the bootstrapper create-elm-app which will create us the base structure of an Elm program. You need to install it with npm install -g create-elm-app
. This bootstrapper creates us a few more things, like default css files, a service worker, a skeleton html file where your compile code will end up and most importantly a basic src/Main.elm
.
After installing create-elm-app
via npm, call create-elm-app elm-calculator
. This will create the project and especially a Main.elm
file with following content:
Now you can see the Elm architecture. You have the following sections:
- Model: contains the data structure and the initial data for the dynamic parts of your page
- Update: contains a function that describes changes to the model when messages are triggered. Messages can get triggered when some HTML events occur like for example the
onClick
event on a button - View: This is more or less the template of the program. It transforms the model into an HTML representation
- Subscription: We don’t use subscriptions here, but subscriptions are another possibility to trigger messages. You can for example have subscriptions on time intervals or on events like keys being hit on the keyboard. So subscriptions can be used to implement timers or to handle keyboard input in games
- Program: in the program section we put all the other parts together
Next call elm-app start
. This will compile your Elm files and start a webserver that serves your webpage at localhost:3000
. It will reload when we save a file from the project and display compilation errors in the browser when we have some. As one of Elm key features is its strong typing, it’s very probable that you will get compilation errors from time to time. Fortunately, the Elm creator took great care of writing meaningful error messages, so you will usually get a useful hint on how to fix them and not some hard-to-understand error messages. The good thing about this is that finding the problems at compile time will prevent you from finding them at runtime.
So now that we have our structure in place, we can start implementing our program. We’ll start with the model. Our model will contain the two numbers as well as the results of all arithmetic operations. Open the file src/Main.elm
and change the type alias Model:
Model
is now a type alias for a record with the properties we specified. The record type in elm is a dictionary with determined properties. The order of the properties is not important.
Next we need our initial values. We will use 0 as initial value for operand1 and operand2, the other properties are then derived from it. But wait: what is the initial value for quotient
if operand2 is 0? As division by 0 is not allowed, we need to readjust our model slightly to indicate that quotient
can have no value. For this we use the Maybe
type. If you know Haskell, you’ll know this type, if not: Maybe a
is a type class (a generic type) that has either no value (called Nothing
) or a value of type a
called Just
, e.g. if a=Int
a value of type Maybe Int
could be Just 1234
. So in the next code sample, I’ll adjust the model to use Maybe Int
and will add the initial values for the model:
Next we will describe the view (first without events):
We only see the initial values of zero, we can change any value without anything happening.
So we first need to write what should happen, when we update the values of the two operands. We do this in the UPDATE section of our program. First we define two messages, one for each operand. Next in the update
function, we define what should happen, when these events occur. As in both cases we recalculate all operations, I extracted this common part to a separate function called updateCalculatedValues
:
Now that we added those functions, we just need to make our view send these messages when the values of the input fields change. For this we use the onInput
events. Finally, we also set the readonly attributes of all other fields to true, so that we cannot change them anymore.
Now we have everything in place and we can change the operands in our calculator as we want it and the results are automatically updated.
Where to go from here
The main purpose of this post was to demonstrate how a simple frontend can be written in Elm. I focused more on the web framework than on the language which may be a topic for another post. As usual if you want to learn the language, I can recommend you to do it on Exercism which also has an Elm track. The language guide to Elm is the first starting point if you want to learn its syntax. Then just play around with Elm and try a bit more complex things. You could for example try to make our calculator more beautiful by adding CSS styles to it.
One important tool for Elm development is html-to-elm where you can paste some html code which will be transformed into an Elm view.
Another cool tool is Ellie where you can write ELM code online, immediately see the rendered result and also have the possibility to share code examples with others.
I hope I gave you an insight on frontend development with Elm. Feel free to give me feedback via e-mail or if you have any questions.