Thibaut Géry

My first impressions with Elm

13 Feb 2017

Elm is a domain-specific programming language for declaratively creating web browser-based graphical user interfaces. Elm is purely functional, and is developed with emphasis on usability, performance, and robustness.

Elm is a functional programming language created in 2012 by Evan Czaplicki for his thesis. The platform is now used in production by a few companies: NoRedInk or Pivotal Tracker.

The idea is to compile Haskell Elm to Javascript to create web site. I wanted to give it a try because:

The Javascript fatigue I just can’t keep up with all framework and library in JS to setup a website, I has became so complex, maybe there is a more stable and easier platform,

I love functional programming and Javascript is only partly functional, the language is not fully immutable (even if it’s better with const keyword in EcmaScript6),

I wanted to feel like a hipster again.

TL:DR: My expectations are partly achieved: there are not 42 libraries to do the same thing but you still need too much tools around your project. The language being close to Haskell is definitely functional, there is no state (at least they are “hidden”) and the language rely on Message to exchange informations. It feels sometimes a bit of a burden but only because I am a beginner.

First of all I chose the following tutorial www.elm-tutorial.org and the produced code is available on GitHub. I just copy/paste some code while reading the explanation then I started to implement some functionality by myself.

Here are a list of my first impressions:

First of all the compilation and the unit test are lightning fast.

This may be biased since I am currently coding in Scala and its compiler is extremely slow, but it is real pleasure to code.

You don’t have the time to slack off on reddit or hacker news. It seems even faster than babel.

The compiler is really strict

It’s the first time I like a compiler, I usually don’t compliment compiler, yet:

it is strictly typed and the compiler does some type inference (nothing new in functional programing)

so far the compiler has been able to warn me for my multiple errors. For example when using pattern matching, the compiler makes sure that you haven’t forgot one the type. The following code will produce an error since I have forgotten the GeneratePlayer in the pattern matching.

On the landing page, the documentation state “No Runtime Exceptions” and it looks like like they are not lying.
I feel like I don’t really need to test that my component are integrating well with each others. Nonetheless, I do need to test my business logic.

The community is small but very active

The community is quite small but really active. Yet it means one things: you just can’t copy/paste your exception and expect to find the answer on stackoverflow. For example, to have a better understanding of the testing framework, I look at the core library tests.
However the number of IDE integration is pretty high.

Steep learning curve

The learning curve is pretty steep, especially if you are not familiar with functional programming, Haskell is definitely a plus. At first sight the following expression is not very clear

No interoperability with Javascript

Even if we can use Javascript and Elm in the same webpage, it’s not possible to use javascript library in Elm code. It would definitely break the message architecture with all those awful callback.

Still too many tools needed

This is one of my deception: I was expecting to get rid of npm, bower, webpack, gulp & co but it ain’t that simple:

most of the project use npm like elm-css because the test’s runner is a node binary.

if you want to integrate external CSS stylesheet like Semantic UI or even your own you can use Webpack and use the Elm loader. I am not sure this is enough to add a new tool (you could use a direct link to a CDN for example)

Damn it’s easy to write unit test

Since all the code is immutable, it’s a pleasure to write unit test: no need to mock, no side effect. The tests are easily understanding like the following snippet from my project

layers:ListPlayerplayers=[{id="1",name="toto",level=1}]tests:Testtests=[describe"deletePlayer"[test"should remove no player if not in list"<|\()->letactual=deletePlayer"3"playersinExpect.equalListsactualplayers

I have found two limitations:

the tooling is not optimized: there is two elm-package.json one for the tests and one the application, the tests need the dependencies of the tested function, so you have to duplicate most of your dependencies.

I still need to figure how to test the function using pattern command to share a state like the following snippet

No “Oh my god, I will only use this from now on” effect

It might be for the best since I have always been deceived after that initial feeling because it would only mean that there is some kind of dark magic going on under the hood.

So far, I like to language and the developer experience but its usage is not widespread enough to be used for my clients. I will nonetheless consider it for my next personal project, It will strengthen my functional programing skills which is always a plus.