Dig into Elm

par Sébastien Morele, mis à jour le 20/04/2016

Elm is an exciting language designed by Evan Czaplicki as his thesis in 2012. Elm allows to create web application really fastly by replacing jquery/react/whatever javascript applications. Thanks to compilation, Elm removes runtime exceptions, then you will find errors before it impacts users. Sexy isn’t it ?! If it compiles, it works !

Instead of a basic approach with core concepts enumeration, we have decided to play again with an intervention app. If you remember our last article about Meteorjs, we had built a solution to manage interventions. Data model is relatively easy to understand, users can create customers, and associate them interventions. An intervention consists in our case of a title and a description.

Elm installation is well documented on the official website, then I recommand you to read it before starting. Once installed, create a new folder named « elm-interventions » for example and create a file main.elm. This is the content:

module Interventions where 
import Html exposing (text, Html)

main : Html
main =
Html.text "Welcome to interventions app"

Now, try to compile with

elm-make main.elm

Damn, an error. Elm cannot find Html module.

Let’s talk about modules

The first line into our file says « I’m creating a new module called Interventions and this is the content ». By defining a module, you give the possibility to use it later or in another application simply by importing it. It’s exactly what happen with the Html module.

With import Html exposing (text, Html)we say « from the Html module import text and Html functions ». Each time you import a module, you can call MyModule.MyFunction to call the function od the module. In our example, we have imported the text function from the Html module and we use it in 

Html.text "Welcome to interventions app"

By writing import Html exposing (..) you expose all functions from Html module (Html, text, h1, h2, ...)

NB: you can write either Html.text or text but I prefer the first case because we prefix with the module name and to me, the code is easier to understand.

Now, to fix our compilation failure, type this command line in your project repository:

elm package install evancz/elm-html

This command uses the elm package manager to download elm-html. Try again to compile. Elm has created an index.html file which contains the text "Welcome to interventions app". Great, we have just created our first Elm program, congrats !

A (big) note about functions

Impossible to present Elm without talking about functions, it's a core concept ! In Elm, functions are pure meaning If you give a function the same value, it will always produce the same result. In addition, the function has no side effects, does not mutate anything and does not impact the world around.

In our example, we have 2 functions, main and text (from the Html module) and it's time to give some informations.

In each Elm program, you have to define a main function, it's the entry point. A main function always have to return either Html or Signal (we will talk about Signals in another article). Did you notice the particularity in the text function ? All the arguments in functions are separated with spaces then, in our case, the text function takes one argument which is "Welcome to interventions app".

Let's update our file with this content

module Interventions where
import Html exposing (text, Html)
view : String -> Html
view username =
text ("Interventions list for " ++ username)
main : Html
main =
view "smorele"

Did you notice the changes ? We have added a new function intro which takes 2 arguments, returns a text and we call it from main. 

As seen below, the function text takes only one argument and this is why we use parenthesis. Remember, arguments are separated by spaces. If you remove parenthesis it means you pass 3 arguments ("Interventions list for ", ++ and username) and compilation fails. A question you may be asking is how to know what are the required arguments and the answer is: Thanks to signature ! A signature is a kind of contract, it says "OK, I need these arguments and I return this type". In our example, view : String -> Html defines a new function named view which takes a String argument and returns an Html element.

Generally speaking, all elements in a signature are separated by -> and the last element is always the return. In the case of a signature with only one element, it means the function takes no arguments.

Arg1 -> Arg2 -> ... -> Argn -> Return


REPL stands for read–eval–print loop. It's basically an interactive terminal and I always use it to test pieces of code or find function signature. This is what I have on my laptop when I launch the command:

$ elm-repl 
---- elm repl 0.16.0 -----------------------------------------------------------
 :help for help, :exit to exit, more at <https://github.com/elm-lang/elm-repl>

Now, suppose you want to use the function text from the html module but don't know what the signature is, then type

> import Html 
> Html.text
<function text> : String -> Html.Html

REPL explains the text function takes a String argument and returns an Html element. Easy isn't it ? And you can try with other modules and functions.

View improvement

In this article, we focus on basic concepts and in a last time, this is the file update to present more informations:

module Interventions where

import Html exposing (..)
import Html.Attributes exposing (id, for, name, type')

view: String -> Html
view username =
div [] [
h2 [] [text ("Interventions list for " ++ username)],
form [ id "intervention-form" ] [
label [ for "intervention-title" ][text "Title"],
input [ id "intervention-title" ][],
label [for "intervention-description" ] [text "Description"],
textarea [ id "intervention-description" ] [],
button [ type' "submit"][ text "Validate" ]
ul [] [
li [] [ text "Intervention example #1"],
li [] [ text "Intervention example #2"]

main : Html
main =
view "smorele"

If you analyse this new file version, you will notice nothing has really changed, we just improved the render by providing a form and a list.

However, I would like to give some informations. In the button definition we have to specify it as type’ (note the apostrophe), since type is a reserved word in Elm. Except this point, nothing new, we have imported Html.attributes to use them in html elements definition. Each Html element takes 2 lists in parameters, for attributes and content and then, we can compile elements like we did with div, form, ul for example.

What's next ?

It's cool, we have our first Elm application but it should be great if users could post data to create new interventions, delete them etc. All this fonctionnalities will be presented in a next article but be prepared, this will be heavy  :)