You are on page 1of 16

Hiring? Toptal handpicks top front-end developers to suit your needs.

Start hiring
Login

Top 3%
Why
Clients
Partners
Community
Blog
About Us
Start hiring
Apply as a Developer
Login
Questions?
Contact Us

Search Topics
Hire a developer

Getting Started with the Elm Programming Language


View all articles

by Vuk Djapic - Freelance Software Engineer @ Toptal

#Elm #FrontEnd #Functional

0shares

When the lead developer of a very interesting and innovative project suggested switching from AngularJS to Elm, my first
thought was: Why?
We already had a nicely written AngularJS application that was in a solid state, well tested, and proven in production. And
Angular 4, being a worthy upgrade from AngularJS, could have been a natural choice for the rewriteso could React or
Vue. Elm seemed like some strange domain-specific language that people have barely heard of.

Well, that was before I knew anything about Elm. Now, with some experience with it, especially after transitioning to it from
AngularJS, I think I can give an answer to that why.

In this article, we will go through the pros and cons of Elm and how some of its exotic concepts perfectly suit the needs of a
front-end web developer. For a more tutorial-like Elm language article, you can take a look at this blog post.

Elm: A Purely Functional Programming Language


If you are used to programming in Java or JavaScript and feel like it is the natural way of writing code, learning Elm can be
like falling down the rabbit hole.

The first thing you will notice is the strange syntax: no braces, lots of arrows and triangles.

You may learn to live without curly braces, but how do you define and nest blocks of code? Or, where is the for loop, or any
other loop, for that matter? While explicit scope can be defined with a let block, there are no blocks in the classic sense and
no loops at all.
Elm is a purely functional, strongly typed, reactive, and event-driven web client language.

You may start to wonder if programming is even possible this way.

In reality, these qualities add up to give you an amazing paradigm of programming and developing good software.

Purely Functional
You might think that by using the newer version of Java or ECMAScript 6, you can do functional programming. But, that is
just the surface of it.

In those programming languages, you still have access to an arsenal of language constructs and the temptation to resort to
the non-functional parts of it. Where you really notice the difference is when you cannot do anything but functional
programming. Its at that point where you eventually start to feel how natural functional programming can be.

In Elm, almost everything is a function. The record name is a function, the union type value is a functionevery function is
composed of partially applied functions to its arguments. Even the operators like plus (+) and minus (-) are functions.

To declare a programming language as purely functional, rather than the existence of such constructs, the absence of
everything else is of paramount importance. Only then you can start thinking in a purely functional way.

Elm is modeled upon mature concepts of functional programming, and it resembles other functional languages like Haskell
and OCaml.

Strongly Typed

If you program in Java or TypeScript, then you know what this means. Every variable must have exactly one type.

Some differences exist, of course. Like with TypeScript, type declaration is optional. If not present, it will be inferred. But
there is no any type.

Java supports generic types, but in a better way. Generics in Java were added later, so types are not generic unless otherwise
specified. And, to use them we need the ugly <> syntax.

In Elm, types are generic unless specified otherwise. Lets look at an example. Suppose we need a method which takes a list
of a particular type and returns a number. In Java it would be:
public static <T> int numFromList(List<T> list){
return list.size();
}

And, in the Elm language:


numFromList list =
List.length list

Although optional, I strongly suggest that you always add type declarations. The Elm compiler would never allow
operations on wrong types. For a human, its a lot easier to make such a mistake, especially while learning the language. So
the program above with type annotations would be:
numFromList: List a -> Int
numFromList list =
List.length list

It can seem unusual at first to declare the types on a separate line, but after some time it starts to look natural.

Web Client Language


What this means simply is that Elm compiles to JavaScript, so browsers can execute it on a web page.
Given that, its not a general purpose language like Java or JavaScript with Node.js but a domain-specific language to write
the client portion of web applications. Even more than that, Elm includes both writing the business logic (what JavaScript
does), and the presentational part (what HTML does)all in one functional language.

All of these are done in a very specific framework-like way, which is called The Elm Architecture.

Reactive
The Elm Architecture is a reactive web framework. Any changes in the models are rendered immediately on the page,
without explicit DOM manipulation.

In that way, its similar to Angular or React. But, Elm also does it in its own way. The key to understanding its basics is in
the signature of the view and update functions:
view : Model -> Html Msg
update : Msg -> Model -> Model

An Elm view isnt just the HTML view of the model. Its HTML which can produce messages of kind Msg, where Msg is an
exact union type you define.

Any standard page event can produce a message. And, when a message is produced, Elm internally calls the update function
with that message, which then updates the model based on the message and current model, and the updated model is again
internally rendered to the view.

Event-driven

A lot like JavaScript, Elm is event-driven. But unlike, for example, Node.js, where individual callbacks are supplied for the
async actions, Elm events are grouped in discrete sets of messages, defined in one message type. And, like with any union
type, information that separate type values carry could be anything.

There are three sources of events that can produce messages: user actions in the Html view, execution of commands, and
outer events to which we subscribed. Thats why all three types, Html, Cmd, and Sub contain msg as their argument. And, the
generic msg type must be the same in all three definitionsthe same one supplied to the update function (in the previous
example, it was the Msg type, with a capital M), where all message processing is centralized.

Source Code of a Realistic Example


You can find a complete Elm web application example in this GitHub repository. Although simple, it shows most of the
functionality used in everyday client programming: retrieving data from a REST endpoint, decoding and encoding JSON
data, using views, messages, and other structures, communicating with JavaScript, and all that is needed to compile and
package Elm code with Webpack.
The application displays a list of users retrieved from a server.

For an easier setup/demo process, Webpacks dev server is used for both packaging everything, including Elm, and serving
the users list.

Some functionality is in Elm, and some in JavaScript. This is done intentionally for one important reason: To show the
interoperability. You probably want to try Elm to start, or gradually switch existing JavaScript code to it, or add new
functionality in the Elm language. With the interoperability, your app continues to work with both Elm and JavaScript code.
This is probably a better approach than to start the whole app from scratch in Elm.

The Elm part in the example code is first initialized with config data from JavaScript, then the list of users is retrieved and
displayed in the Elm language. Lets say we have some user actions already implemented in JavaScript, so invoking a user
action in Elm just dispatches the call back to it.

The code also uses some of the concepts and techniques explained in the next section.

Application of Elm Concepts


Let us go through some of the exotic concepts of the Elm programming language in real-world scenarios.

Union Type
This is the pure gold of the Elm language. Remember all those situations when structurally different data needed to be used
with the same algorithm? Its always difficult to model those situations.

Here is an example: Imagine you are creating pagination for your list. At the end of each page, there should be links to
previous, next, and all pages by their numbers. How do you structure it to hold the information of which link the user
clicked on?

We can use multiple callbacks for previous, next, and page number clicks, or we can use one or two boolean fields to
indicate what was clicked, or give special meaning to particular integer values, like negative numbers, zero, etc. But none of
these solutions can model exactly this kind of user event.

In Elm, its very simple. We would define a union type:


type NextPage
= Prev
| Next
| ExactPage Int

And we use it as a parameter for one of the messages:


type Msg
= ...
| ChangePage NextPage

Finally, we update the function to have a case to check the type of nextPage:
update msg model =
case msg of
ChangePage nextPage ->
case nextPage of
Prev ->
...

Next ->
...
ExactPage newPage ->
...

It makes things very elegant.

Creating Multiple Map Functions with <|


Many modules include a map function, with several variants to apply to a different number of arguments. For example, List
has map, map2, , up to map5. But, what if we have a function which takes six arguments? There is no map6. But, there is a
technique to overcome that. It uses the <| function as a parameter, and partial functions, with some of the arguments applied
as mid results.

For simplicity, suppose a List only has map and map2, and we want to apply a function that takes three arguments on three
lists.

Here is how the implementation looks:


map3 foo list1 list2 list3 =
let
partialResult =
List.map2 foo list1 list2
in
List.map2 (<|) partialResult list3

Suppose we want to use foo, which just multiplies its numeric arguments, defined like:
foo a b c =
a * b * c
So the result of map3 foo [1,2,3,4,5] [1,2,3,4,5] [1,2,3,4,5] is [1,8,27,64,125] : List number.

Lets deconstruct what is going on here.

First, in partialResult = List.map2 foo list1 list2, foo is partially applied to every pair in the list1 and list2.
The result is [foo 1 1, foo 2 2, foo 3 3, foo 4 4, foo 5 5], a list of functions that takes one parameter (as the first
two are already applied) and returns a number.

Next in List.map2 (<|) partialResult list3, it is actually List.map2 (<|) [foo 1 1, foo 2 2, foo 3 3, foo 4
4, foo 5 5] list3. For every pair of these two lists, we are calling the (<|) function. For example, for the first pair, it is
(<|) (foo 1 1) 1, which is the same as foo 1 1 <| 1, which is the same as foo 1 1 1, which produces 1. For the
second, it will be (<|) (foo 2 2) 2, which is foo 2 2 2, which evaluates to 8, and so on.

This method can be particularly useful with mapN functions for decoding JSON objects with many fields, as Json.Decode
provides them up to map8.

Remove All Nothing Values from a List of Maybes


Lets say we have a list of Maybe values, and we want to extract only the values from the elements that have one. For
example, the list is:
list : List (Maybe Int)
list =
[ Just 1, Nothing, Just 3, Nothing, Nothing, Just 6, Just 7 ]

And, we want to get [1,3,6,7] : List Int. The solution is this one line expression:
List.filterMap identity list

Lets see why this works.

List.filterMap expects the first argument to be a function (a -> Maybe b), which is applied on elements of a supplied
list (the second argument), and the resulting list is filtered to omit all Nothing values, and then the real values are extracted
from Maybes.

In our case, we supplied identity, so the resulting list is again [ Just 1, Nothing, Just 3, Nothing, Nothing, Just
6, Just 7 ]. After filtering it, we get [ Just 1, Just 3, Just 6, Just 7 ], and after value extraction, it is [1,3,6,7],
as we wanted.

Custom JSON Decoding

As our needs in JSON decoding (or deserializing) start to exceed what is exposed in the Json.Decode module, we might
have troubles creating new exotic decoders. This is because these decoders are invoked from the middle of the decoding
process, e.g., within Http methods, and its not always clear what their inputs and outputs are, especially if there are a lot of
fields in the supplied JSON.

Here are two examples to show how to handle such cases.

In the first one, we have two fields in incoming JSON, a and b, denoting sides of a rectangular area. But, in an Elm object,
we only want to store its area.
import Json.Decode exposing (..)
areaDecoder = map2 (*) (field "a" int) (field "b" int)
result = decodeString areaDecoder """{ "a":7,"b":4 }"""
-- Ok 28 : Result.Result String Int

The fields are individually decoded with the field int decoder, and then both values are supplied to the provided function
in map2. As multiplication (*) is also a function, and it takes two parameters, we can just use it like that. The resulting
areaDecoder is a decoder which returns the result of the function when applied, in this case, a*b.
In the second example, we are getting a messy status field, which can be null, or any string including empty, but we know
the operation succeeded only if it is OK. In that case, we want to store it as True and for all other cases as False. Our
decoder looks like this:
okDecoder =
nullable string
|> andThen
(\ms ->
case ms of
Nothing -> succeed False
Just s -> if s == "OK" then succeed True else succeed False
)

Lets apply it to some JSONs:


decodeString (field "status" okDecoder) """{ "a":7, "status":"OK" }"""
-- Ok True
decodeString (field "status" okDecoder) """{ "a":7, "status":"NOK" }"""
-- Ok False
decodeString (field "status" okDecoder) """{ "a":7, "status":null }"""
-- Ok False

The key here is in the function supplied to andThen, which takes the result of a previous nullable string decoder (which is a
Maybe String), transforms it to whatever we need, and returns the result as a decoder with help of succeed.

Key Takeaway
As can be seen from these examples, programming in the functional way may not be very intuitive for Java and JavaScript
developers. It takes some time to get used to it, with a lot of trial and error. To help understand it, you can use elm-repl to
exercise and check the return types of your expressions.

The example project linked to earlier in this article contains several more examples of custom decoders and encoders which
might also help you understand them.

But Still, Why Choose Elm?


Being so different from other client frameworks, the Elm language is certainly not yet another JavaScript library. As such,
it has a lot of traits which can be considered positive or negative when compared to them.

Lets start with positive side first.

Client Programming Without HTML and JavaScript

Finally, you have a language where you can do it all. No more separation, and awkward combinations of their mixing. No
generating HTML in JavaScript and no custom templating languages with some stripped-down logic rules.

With Elm, you have just one syntax and one language, in its full glory.

Like what you're reading?


Get the latest updates first.
Enter your email address...
Get Exclusive Updates
No spam. Just great engineering posts.
Like what you're reading?
Get the latest updates first.
Thank you for subscribing!
Check your inbox to confirm subscription. You'll start receiving posts after you confirm.

0shares
Uniformity
As almost all of the concepts are based on functions, and a few structures, the syntax is very concise. You dont have to
worry if some method is defined on the instance or the class level, or if it is just a function. They are all functions defined on
the module level. And, there arent a hundred different ways for iterating lists.

In most languages, there is always this argument about whether the code is written in the languages way. A lot of idioms
need to be mastered.

In Elm, if it compiles, its probably the Elm way. If not, well, it certainly isnt.

Expressiveness

Although concise, the Elm syntax is very expressive.

This is achieved mostly through the use of union types, formal type declarations, and the functional style. All of these
inspire the use of smaller functions. At the end, you get code which is pretty much self-documenting.

No Null
When you use Java or JavaScript for a very long time, null becomes something completely natural to youan inevitable
part of programming. And, although we constantly see NullPointerExceptions and various TypeErrors, we still dont
think that the real problem is the existence of null. Its just so natural.

It becomes clear quickly after some time with Elm. Not having null not only relieves us from seeing runtime null reference
errors over and over again, it also helps us write better code by clearly defining and handling all situations when we might
not have the actual value, thus also reducing technical debt by not postponing null handling until something breaks.

The Confidence That It Will Work

Creating syntactically correct JavaScript programs can be done very quickly. But, will it actually work? Well, lets see after
reloading the page and testing it thoroughly.

With Elm, it is the opposite. With static type checking and enforced null checks, it needs some time to compile, especially
when a beginner writes a program. But, once it compiles, there is a good chance that it will work correctly.

Fast

This can be an important factor when choosing a client framework. The responsiveness of an extensive web app is often
crucial for the user experience, and thus the success of the whole product. And, as tests show, Elm is very fast.

Pros of Elm vs Traditional Frameworks

Most of the traditional web frameworks offer powerful tools for web app creation. But that power comes with a price: over-
complicated architecture with lots of different concepts and rules on how and when to use them. It takes a lot of time to
master it all. There are controllers, components, and directives. Then, there are the compilation and config phases, and the
run phase. And then, there are services, factories, and all the custom template language used in provided directivesall
those situations when we need to call $scope.$apply() directly to make the page refresh, and more.

Elm compilation to JavaScript is certainly also very complicated, but the developer is protected from having to know all the
nuts and bolts of it. Just write some Elm and let the compiler do its work.

And, Why Not Choose Elm?


Enough with praising Elm. Now, lets see some of its not-so-great side.

Documentation
This is really a major issue. The Elm language lacks a detailed manual.

The official tutorials just skim through the language and leave a lot of unanswered questions.

The official API reference is even worse. A lot of functions lack any sort of explanation or examples. And, then there are
those with the sentence: If this is confusing, work through the Elm Architecture Tutorial. It really does help! Not the
greatest line you want to see in the official API docs.

Hopefully, this will change soon.

I dont believe Elm can be widely adopted with such poor documentation, especially with people coming from Java or
JavaScript, where such concepts and functions are not intuitive at all. To grasp them, much better documentation with a lot
of examples is needed.

Format and Whitespace

Getting rid of curly braces or parentheses and using white space for indentation could look nice. For example, Python code
looks very neat. But for creators of elm-format, it wasnt enough.

With all the double line spaces, and expressions and assignments split into multiple lines, Elm code looks more vertical than
horizontal. What would be a one-liner in good old C can easily stretch to more than one screen in the Elm language.

This may sound good if you are paid by lines of code written. But, if you want to align something with an expression started
150 lines earlier, good luck with finding the right indentation.

Records Handling

It is difficult to work with them. The syntax to modify the field of a record is ugly. There is no easy way to modify nested
fields or to reference arbitrarily fields by name. And if you are using the accessor functions in a generic way, there is a lot of
trouble with proper typing.

In JavaScript, a record or object is the central structure which can be constructed, accessed, and modified in a lot of ways.
Even JSON is just a serialized version of a record. Developers are used to working with records in web programming, so
difficulties in their handling in Elm can become noticeable if they are used as the primary data structure.

More Typing

Elm requires more code to be written than JavaScript.

There is no implicit type conversion for string and number operations, so a lot of int-float conversions and especially
toString calls are needed, which then requires parentheses or function application symbols to match the correct number of
arguments. Also, the Html.text function requires a string as an argument. A lot of case expressions are needed, for all those
Maybes, Results, types, etc.

The main reason for this is the strict type system, and that can be a fair price to pay.
JSON Decoders and Encoders

One area where more typing really stands out is JSON handling. What is simply a JSON.parse() call in JavaScript can span
hundreds of lines in the Elm language.

Of course, some kind of mapping between JSON and Elm structures is needed. But the need to write both decoders and
encoders for the same piece of JSON is a serious problem. If your REST APIs transfer objects with hundreds of fields, this
will be a lot of work.

Wrap Up
We have seen about Elm, its time to answer the well-known questions, probably as old as programming languages
themselves: Is it better than the competition? Should we use it in our project?

The answer to the first question may be subjective, as not every tool is a hammer and not everything is a nail. Elm can shine
and be a better choice over other web client frameworks in many cases while falling short in others. But it offers some really
unique value that can make web front-end development a lot safer and easier than the alternatives can.

For the second question, to avoid answering with also the age-old it depends, the simple answer is: Yes. Even with all the
disadvantages mentioned, just the confidence that Elm gives you about your program being correct is reason enough to use
it.

Coding in Elm is also fun. Its a totally new perspective for anyone who is used to the conventional web programming
paradigms.

In real use, you dont have to switch your entire app to Elm immediately or start a new one completely in it. You can
leverage its interoperability with JavaScript to give it a try, starting with a portion of the interface or some functionality
written in the Elm language. You will quickly find out if it suits your needs and then broaden its usage or leave it. And who
knows, you may also fall in love with the world of functional web programming.

Understanding the Basics


What is the Elm programming language?

Elm is a purely functional, strongly typed, reactive, and event-driven web client language.

About the author


View full profile
Hire the Author
Vuk Djapic, Serbia
member since July 14, 2016
JavaJavaScriptSpringAngularJS
Vuk has 10 years of experience developing various Java and JavaScript projects. He has worked on the rich client front-end
applications, various server side frameworks with web and application servers, components and architecture in a clustered
environment, middleware, and integrations. With a strong mathematical background, he has analytical and problem solving
skills and always works in accordance with technology standards and best practices. [click to continue...]
Hiring? Meet the Top 10 Freelance Front-End Developers for Hire in December 2017
1 Comment Toptal
1 Login

Sort by Best
Recommend 2 Share

Join the discussion

LOG IN WITH
OR SIGN UP WITH DISQUS ?

Name

Pwndz Kigozi 4 days ago


No experience in any functional programming language before & hence the strange looking code to me ;-/.
Refreshing knowing what happens on the other side of the island though. Thanks for the write-up.
Reply Share

Subscribe d Add Disqus to your siteAdd DisqusAdd Privacy

comments powered by Disqus


Subscribe
The #1 Blog for Engineers
Get the latest content first.
Enter your email address...
Get Exclusive Updates
No spam. Just great engineering posts.
The #1 Blog for Engineers
Get the latest content first.
Thank you for subscribing!
Check your inbox to confirm subscription. You'll start receiving posts after you confirm.

0shares

Trending articles

Fastlane: iOS Automation on Cruise Control2 days ago Magento 2: Revision or Revolution?3 days

ago Getting Started with the Elm Programming Language9 days ago GraphQL vs. REST - A

GraphQL Tutorial12 days ago Tips to Attract, Manage, and Retain Software Developers16 days ago

Getting Started with TensorFlow: A Machine Learning Tutorial17 days ago Quick Wins in the Enterprise With

Salesforce AppExchange24 days ago From Solving Equations to Deep Learning: A TensorFlow Python
Tutorial25 days ago
Relevant Technologies

Front-End
Web

About the author


Vuk Djapic
Front-end Developer
Vuk has 10 years of experience developing various Java and JavaScript projects. He has worked on the rich client front-end
applications, various server side frameworks with web and application servers, components and architecture in a clustered
environment, middleware, and integrations. With a strong mathematical background, he has analytical and problem solving
skills and always works in accordance with technology standards and best practices.

Hire the Author


Toptal connects the top 3% of freelance talent all over the world.

Toptal Developers
Android Developers
AngularJS Developers
Back-End Developers
C++ Developers
Data Scientists
DevOps Engineers
Ember.js Developers
Freelance Developers
Front-End Developers
Full Stack Developers
HTML5 Developers
iOS Developers
Java Developers
JavaScript Developers
Machine Learning Engineers
Magento Developers
Mobile App Developers
.NET Developers
Node.js Developers
PHP Developers
Python Developers
React.js Developers
Ruby Developers
Ruby on Rails Developers
Salesforce Developers
Scala Developers
Software Developers
Unity or Unity3D Developers
Web Developers
WordPress Developers

See more freelance developers


Learn how enterprises benefit from Toptal experts.

Join the Toptal community.


Hire a developer
or
Apply as a Developer

Highest In-Demand Talent


iOS Developer
Front-End Developer
UX Designer
UI Designer
Financial Modeling Consultants
Interim CFOs

About

Top 3%
Clients
Freelance Developers
Freelance Designers
Freelance Finance Experts
About Us

Contact

Contact Us
Press Center
Careers
FAQ

Social

Facebook
Twitter
Google+
LinkedIn

Toptal

Hire the top 3% of freelance talent


Copyright 2010 - 2017 Toptal, LLC

Privacy Policy
Website Terms

Home Blog Getting Started with the Elm Programming Language

You might also like