DEV Community

Cover image for Why is Elm such a delightful programming language?
Marcio Frayze
Marcio Frayze

Posted on • Updated on

Why is Elm such a delightful programming language?

A Brazilian Portuguese version is available here.


Elm is a programming language created by Evan Czaplicki and a recurring definition used to describe it is:

"A delightful language for reliable web applications." - Elm website.

I like this description because it shows the philosophy of the language and its community. A formal definition could be something like: Elm is a pure functional programming language with immutable data structure, soundness type system, currying, and blah blah blah. But instead, the author preferred to highlight his real intention: to create a safe language that web developers feel pleasure in using it. The rest is a consequence of that!

But as you may know, there are several other alternatives to JavaScript for webapp development. Most of them (including Elm) are languages that are transpiled into JavaScript. A list of some famous (and not so famous) alternatives include: CoffeScript, TypeScript, Reason, ReScript, PureScript, Blazor, ClojureScript,...

With so many options, what would be Elm's main feature that makes it so delightful and unique?

Elm's main differences

Pure functions

There are several factors that make me like this language so much, but if I had to highlight only one technical feature that makes it so different from other solutions, it would be: Elm is a pure language. This means that all the functions we write in Elm are mandatory pure, i.e. they cannot cause side effects.

This feature forces a different mindset in software development. In a way, it deprives you of a number of possibilities but that, together with an architecture designed for this, manages to make development much more predictable, safe, easy to test and maintain.

When I found out that Elm was a pure language, the first question I asked myself was:

🤔 But how can it be possible to develop a dynamic page without making a REST call? After all, this is a form of side effect!

And yes, that it is possible. Even if all the functions you implement are pure, there is a runtime capable of performing (in a very controlled manner) some types of side effects, including triggering REST services.

This very short and easy to follow guide shows how this is possible. Even if you never develop a real project in Elm, you'll probably find ideas there that you'll be able to reuse in other languages and frameworks. It was only after reading this guide and understanding how Elm's architecture works that I finally understood, for example, how React, Flutter, Redux, MobX and similars work! 😉

But that's not the main feature that makes me like Elm so much.

Friendly error messages

Another exalted feature within the Elm community is it's compiler's ability to generate super-friendly error messages. This is a constant concern and in each new version the messages become clearer. According to this post, the goal is that error messages not only point out the flaws but can also teach the syntax of the language. This helps even more if you are a new to the functional paradigm.

But this is not the main feature that makes me like Elm so much.

Immutability

All data structures are immutable in Elm. Once a value is assigned to a variable, it cannot be changed within the same scope. That is, the following code is invalid in Elm:

x = x + 1
Enter fullscreen mode Exit fullscreen mode

If you enter the Elm REPL (running the elm repl command) and try to run the code above, you receive the following error message:

> x = x + 1
-- CYCLIC DEFINITION ------------------------------------------------------ REPL

The `x` value is defined directly in terms of itself, causing an infinite loop.

2| x = x + 1
   ^
Are you are trying to mutate a variable? Elm does not have mutation, so when I
see x defined in terms of x, I treat it as a recursive definition. Try giving
the new value a new name!

Maybe you DO want a recursive value? To define x we need to know what x is, so
let’s expand it. Wait, but now we need to know what x is, so let’s expand it...
This will keep going infinitely!

Hint: The root problem is often a typo in some variable name, but I recommend
reading <https://elm-lang.org/0.19.1/bad-recursion> for more detailed advice,
especially if you actually do need a recursive value.
Enter fullscreen mode Exit fullscreen mode

The first time I saw this message, I almost fell off my chair. How come I can't increment the value of x??? It was the first language I knew in which this was forbidden! But deep down I always thought that incrementing a variable didn't make any sense. In mathematics, the following system of equations is considered invalid:

x = 1 and x = x + 1

Doesn't it seem obvious that if x has the value 1, it (in this scope) could never be equal to itself plus one? So why was this is so normalized in the programming world?

You may be wondering how you could develop an entire system without being able to change (reassign) variables. And that was one of the reasons I ventured into this language. I had to understand how this would be possible! Over time I have realized how immutability helps me create simpler code and avoids a number of bugs.

But that's still not the main feature that makes me like Elm so much.

No null (or undefined) references

Every JavaScript developer has come across a "undefined is not a function"! As I said before, error messages in Elm are created with great care, so a message as vague and generic as this would never appear in a code made in Elm.

But Elm's compiler goes way beyond that. As I have already described in this article (in pt-BR), the possibility of assigning a null refence to a variable brings a number of problems and became known as "the billion dollar mistake". And Elm took the most direct and sensible attitude to solve this problem: completely eliminated the possibility of creating null or undefined references! Using techniques such as Maybe, the Elm compiler can handle all scenarios where a missing value needs to be represented.

Elm brings other similar concepts as well, but for other purposes, such as the use of Result rather than the infamous idea of exceptions.

But that's still not the main feature that makes me like Elm so much.

No runtime errors (in practice)

Another feature that draws a lot of attention and has a lot of prominence within the Elm community is the absence of errors at runtime.

It is almost impossible to generate unexpected failures while running applications written in Elm. There are reports of systems with more than 600,000 lines of Elm code that do not present unexpected errors (those untreated exceptions) during their execution.

JavaScript programers know that, no matter how hard they try, errors will emerge in unusual situations. In Elm that doesn't happen. If there is a slightly possibility of a problem, the compiler will show where and how it can occur and will force you to deal with all possible situations. It's like programming with someone helping you all the time not to screw up!

I discuss this in more detail in this article.

But that's still not the main feature that makes me like Elm so much.

An amazing package management system

Every JavaScript developer has cursed at NPM at least a few times in their life. Who has never spent hours trying to find an obscure error and then delete the node_modules, download the dependencies again and everything works as if by magic, without ever finding the real source of the problem? At least with me, this has happened numerous times.

And when I have to update JavaScript project dependencies, there's always that butterflies in my stomach! Those strange console error messages and hours trying to find the reason why a function is no longer found. A simple minor update to a library can cause major problems and give me headaches.

Elm's package manager doesn't usually let me down. First, because it forces the use of semantic versioning. For example: if a package maintainer tries to upload a new version with a modified signature of a public function and changes only the last (minor) version number of the package, the upload of the new version will be refused! Thanks to pure functions and an excellent type system, the server is able to catch this and invalidate the submission.

And this also brings us some extra really nice features. It is possible, for example, to compare what has changed from one version of a package to another, using the command elm diff followed by the name and the versions you want to compare:

elm diff Microsoft/elm-json-tree-view 1.0.0 2.0.0
This is a MAJOR change.

---- JsonTree - MAJOR ----

    Changed:
      - parseString : String -> Result String Node
      + parseString : String -> Result Error Node

      - parseValue : Value -> Result String Node
      + parseValue : Value -> Result Error Node
Enter fullscreen mode Exit fullscreen mode

The example above shows that from version 1.0.0 to 2.0.0 of the elm-json-tree-view package, the return type of the parseString function changed. It was Result String Node and became Result Error Node.

I'm not aware of another language that has a package manager that can do this. 😃

Another big advantage over NPM is that all third-party functions imported via Elm packages are also pure. So they are unable to carry out any types of side effects without your consent. This brings a strong guarantee in terms of security. While in NPM, third-party code will be allowed to do whatever it wants, without any kind of control.

But that's still not the main feature that makes me like Elm so much.

Balance

My career has always revolved around object-oriented languages (mostly Java). But around 2017 I started venturing into the world of Functional Programming.

When I started reading about this universe, a language that appeared recurrently was Haskell. It was a sort of holy place where people who really understood the subject would end up. Dazzled by the possibility of finding my holy grail, I started to venture into this language. Early on I realized that the path would be more tortuous than I imagined. Between comings and goings, I read some books and took some courses. But the learning curve was steeper than I expected!

I tried many different approaches, from trying to learn a more pragmatic framework like IHP (a kind of "Ruby on Rails" of the Haskell world), to very theoretical books and courses about Category Theory and Lambda Calculus. I would like to say that I found a way to significantly shorten the learning curve and became fluent in this language, but I would be lying through my teeth.

Even though I couldn't get too deep into this language, I managed to see a light at the end of the tunnel. A more colorful and happy world! But without a lot of help, I couldn't get there. It was frustrating, but I decided to postpone this journey. Another issue was that even if I got to the other side of that long path, I would hardly be able to bring many people with me. It would be like convincing my friends to do a multi-day and super difficult trail, promising that at the end they would see a beautiful waterfall. I found few people willing to face this journey with me.

Two people walking alone in the snow

Furthermore, Haskell was created within the academic world and, although today it is used in the most diverse areas, it is still quite common to find discussions within this community that, although interesting, are difficult to understand. There are exceptions, such as the Simple Haskell initiative. But I think it's safe to say that overall it's a difficult community to get into.

And in the middle of this path I came across Clojure: a functional language from the LISP family, much simpler and easier to learn. In a short time I was able to understand it's philosophy and was already using it in practice in a real system at work! I even created an Introduction to Functional Programming course (in Brazilian Portuguese) using this language as a base. But, although I like it a lot and want to learn more about it, I miss some features that only a strongly typed and pure language could provide.

It was along this journey that I came across Elm. Until then, I wasn't very interested in front-end. My career has been very back-end oriented. But I saw there an opportunity to flatten that learning curve. Since Elm is a domain specific language (webapp development), it is much simpler than Haskell! I decided to give it a chance as a way to prepare myself for facing Haskell later.

As I got to know the Elm community, I realized that this was a very good choice. The creator of the language has a very solid background in Haskell (the Elm compiler is written in Haskell) and makes it clear that his goal is precisely to bring the benefits he found in that language to more people. But that wouldn't be possible if he brought along all of Haskell's baggage and complexity.

When I say complexity, I'm not just referring to the more technical parts of the language, but also everything around it. You won't find people from the Elm community saying that to understand Elm you first need to study about Monads, Functors, Type Classes and many other topics that are frequently discussed in the Haskell community. And not because the community does not see value in it, but because they understand that it is possible to find another approach where, through simpler language, be able to transmit the ideas behind these concepts to more people. Later, if they wish, they can go deeper into these themes and find out for themselves what it all means. But to develop a good webapp, it is not necessary to understand the details of a Monad.

This balance between bringing from Haskell what really provides value, and avoiding those parts that are too complex (and with little added value - at least within the context of webapps development), makes us have a very clean, well-designed language with a much less steep learning curve.

Finding this balance is a difficult task. Advanced developers, already familiar with complex tricks and that are seeking a higher level of abstraction, may get frustrated and consider that Elm lacks fundamental tools. On the other hand, beginners in the world of functional programming, who are still not used to an expression-oriented programming language, may suffer when discovering, for for example, that every if needs an else.

Finally, we come to the reason that I believe is the main reason why Elm is such a delightful programming language: it manages to find (at least according to my criteria) a great balance in all of this.

And if you give it a chance and read the Elm introduction guide, maybe you'll also fall in love with this paradigm and never see programming with the same eyes again !

Bonus - Elm Fullstack?

I don't know if I'll ever be able to understand Haskell in depth and finally be able to reach that beautiful waterfall I was promised. But who knows, maybe I don't even need to follow this path? Evan has hinted that he is working on bringing Elm to the backend as well! On May 22, 2023 he will make the first public presentation of his work.

So this might be the best time in history to learn Elm! If you're as excited as me, I recommend (again) starting with the beginner's guide. Then you can continue with the book Elm in Action or, if you prefer an online course, this Udemy course by Carlos Saltos or this course by Richard Feldman.


Did you like this text? Checkout my other articles at: https://segunda.tech/tags/english and follow me on twitter.

Top comments (17)

Collapse
 
konnik profile image
konnik

What a nice read, thank you, this made my day.

My journey into functional programming was very similar to yours, struggling with Haskell and then found Elm and directly fell in love with it. It surely is a delightful language.

I'm now back into Haskell, thanks to the experience from Elm it's much more approachable this time.

Excited to hear Elm on the backend is about to happen also. Happy days.. 👊

Collapse
 
marciofrayze profile image
Marcio Frayze

Thank you very much for the comment.
I'm glad you enjoyed it! And thanks for sharing your journey.

Evan is making it clear that it's still all very experimental but it’s impossible not to get excited about the possibility of being able to use elm on the backend officially!

Collapse
 
eekee profile image
Ethan Azariah

In an old Lisp book, I once read a line something like, "Math is a describing what is. Programming is describing how to." It's quite true for imperative languages, especially those which don't incorporate any functional programming techniques. Functional programming is more mathematical; it doesn't look like a good match for the processes of the real world and the things we expect from computing, but in practice, it is. Imperative programming seems right and natural to me but over the years I've seen so many examples of functional programming being more powerful than imperative that there must be something to it. This power is present even at the deepest possible level. Modern C and C++ compilers secretly create a new variable for every assignment, turning the language into a functional language internally, so they can apply optimizations which only work with functional languages. Deeper still, modern CPU cores JIT-optimize the machine code they execute, having over 100 hidden registers so they can apply the same functional-language optimizations.

Part of me wonders if similarly powerful optimizations are waiting to be discovered in imperative programming, but this hope fades with every passing decade that functional languages continue to get more powerful and more applicable to real hardware. (Functional code is ideal for massively parallel applications.) Naturally, I've been meaning to try a functional language. I had a little go with APL already, but only half-way 'got' it. The character set was surprisingly all right, but figuring out how to get things done was a struggle. I wonder if Elm might be easier to grasp. It would help that it's a Web language; I can readily picture the transformations from input to output in functional terms.

Collapse
 
marciofrayze profile image
Marcio Frayze

I can readily picture the transformations from input to output in functional terms.

Yes! And that's the essence of The Elm Architecture: guide.elm-lang.org/architecture/

Thanks a lot for your comment and insight.

Collapse
 
vicsteiner profile image
Victor Steiner Ferreira

Hi Marcio an hello from another Brazilian here.

Man I have a similar path with FP. Started with Haskell (keep reading and learning it but ...). I think it is a super beautiful language but I agree totally with your perspective on it.

I work as a data engineer so I also have been looking at Scala (functional but not pure ... I like it but honestly sometimes seems more confuse than Haskell to me) but Elm looks much more close to what I have been learning with Haskell.

I have some plan for data tools that involve front end development and I am pretty inspired in trying out Elm for it thanks to your article.

Let's see how it goes!

Collapse
 
neysacassin73045 profile image
Neysa Cassin

Yeah ELM is nice!

Collapse
 
fyodorio profile image
Fyodor

Elm is nice and anything but delightful 😅

Collapse
 
kromdaniel profile image
Daniel Krom

AFAIK, elm is no longer maintained (last stable release, 3 years ago), was it changed?

Collapse
 
marciofrayze profile image
Marcio Frayze

Hello Daniel, thanks for the comment.

You can learn more about the Elm roadmap (the language/compiler) here: github.com/elm/compiler/blob/maste...

In short, the current situation is: "If you like what you see now, that's pretty much what Elm is going to be for a while." But I don't consider that to be unmaintained. It's more like stable ;)

The compiler's current moment goes through a stage that goes back to its origins. Something more experimental, less like a typical open-source project. And as I comment at the end of the article, Evan is trying to use Elm in the backend, but it's not something he speaks too publicly yet.

If you want to know more about how Evan sees Elm's development, I recommend this talk:
youtube.com/watch?v=uGlzRt-FYto

And if you want to understand the future of language, this podcast (from 2021 but I believe that ideas are still valid):
elm-radio.com/episode/open-source-...

But in the meantime, the community around the compiler remains very active and producing amazing things!
Not long ago elm-land (elm.land) was released and version 3 of elm-pages (elm-pages.com) is in development. Among other amazing tools, like elm-review.

The Elm Radio podcast and the Elm Weekly are great sources of information about the current status of the Elm ecosystem.

I'm currently using elm-land in production and that's the best front-end framework I ever worked with. =)

Collapse
 
mihneasim profile image
Mihnea Simian

Thanks for the bringing this topic up, there aren't many people writing on functional programming, especially in frontend.
I was lead to have the same belief as Daniel, you might want to listen to Jesse Tomchak starting at 31:09. Jesse calls it abandoned: repos exist, you can open issues, but there's no one on the other side.
But I get what you're saying, elm is a compiler, it does not need to depend on recurring updates/releases. And there's inherent value in learning and practicing functional programming, despite of the status of a language or a language-compiler.

Thread Thread
 
marciofrayze profile image
Marcio Frayze • Edited

Thanks for the comment Mihnea.

I just listened to that episode.

Well, he says that Evan "moved to something else". But, clearly Evan is still working on Elm and experimenting with new frontiers. Not only on the technical side of things, but finding a more sustanable way to maintain the project (since he is no longer working at NoRedInk).

But I can see why Jesse might feel this way. There are times I felt like that too.
The latest "news" on the official page is from 2019. Defenitly not a common thing on a active open source project, right? In the Elm forum people debate about that from time to time. It's a big contrast with React or Vue communities.

In fact because of this "fear of missing out the next web revolution", I tried many alternative to Elm. React, Vue, Angular, PureScript, Polymer, Ember, Hyperapp, ... but couln't find one that filled that void. So I went back, gave Elm a real chance last year (using in a real project at my job - an internal project, I didn't fell confortable adding a foreign tech into our main product) and I'm really happy with how it's turing out. That fear kinda went away and I never felt so productive and happy developing a front-end.

There are a few other things Jesse says about FP in that episode that I disagree with, but I have no data to backup my opinions, so I guess there is no benefits in pointing them out.

But as you said, learning Elm (and FP) by itselft is of great value for any developer.

Collapse
 
absynce profile image
Jared M. Smith

Folks who are unfamiliar with how the Elm ecosystem works can check this out: iselmdead.info/. I use Elm at work every day and love it, including that I don't have to upgrade and learn new concepts all the time. I can focus on building things instead. 🎉

Collapse
 
peterrybar profile image
Peter Rybár

Some comments may only be visible to logged-in visitors. Sign in to view all comments. Some comments have been hidden by the post's author - find out more