Functional Reactive Programming with Elm: An Introduction
Elm is a functional programming language that has been attracting quite a bit of interest lately. This article explores what it is and why should you care.
Elm is statically typed language with type inference. Type inference means that we don’t need to declare all the types ourselves, we can let the compiler infer many of the types for us. For example by writing
one = 1, the compiler knows that
one is an integer.
Elm is an almost pure functional programming language. Elm builds on top of many functional pattern like pure views, referential transparency, immutable data and controlled side effects. It is closely related to other ML languages like Haskell and Ocaml.
Elm is reactive. Everything in Elm flows through signals. A signal in Elm carries messages over time. For example clicking on a button would send a message over a signal.
Elm syntax resembles
Haskell, as both are ML family languages.
greeting : String -> String greeting name = "Hello" ++ name
This is a function that takes a
String and returns another
Why Use Elm?
To understand why should you care about Elm, let’s talk about some front-end programming trends in the last couple of years:
Describe State Instead of Transforming the DOM
Not long ago we were building applications by mutating the DOM manually (e.g. using jQuery). As our application grows we introduce more states. Having to code the transformations between all of them exponentially grows the complexity of our application making it harder to maintain.
Instead of doing this, libraries like React have popularised the notion of focusing on describing a particular DOM state and then let the library handle the DOM transformations for us. We only focus on describing the discreet DOM states and not how we get there.
This leads to substantially less code to write and maintain.
Events and Data Transformation
When it comes to application state, the common thing to do was to mutate the state ourselves e.g. adding comments to an array.
The benefit of doing this is that we can write ‘pure’ functions to describe these transformations. These functions are easier to understand and test. An added benefit is that we can control where our application state is changed, thus making our applications more maintainable.
Another benefit is that our views don’t need to know how to mutate state, they only need to know what events to dispatch.
Unidirectional Data Flow
Another interesting trend is having all our application events flow in a unidirectional way. Instead of allowing any component talk to any other component, we send message through a central message pipeline. This centralized pipeline applies the transformations we want and broadcasts the changes to all the parts of our application. Flux is an example of this.
By doing this we gain more visibility of all interactions that happen in our application.
Mutable data makes it very hard to restrict where it can be changed, as any component with access to it could add or remove something. This leads to unpredictability, as state could change anywhere.
By using immutable data we can avoid this, by tightly controlling where application state is changed. Combining immutable data with functions that describe the transformations gives us a very robust workflow, and immutable data helps us enforce the unidirectional flow by not letting us change state in unexpected places.
Another trend in front-end development is the use of a centralized ‘atom’ for keeping all state. Meaning that we put all state in one big tree instead of having it scattered across components.
In a typical application we usually have global application state (e.g. a collection of users) and component specific state (e.g. the visibility state of a particular component). It is controversial whether storing both kinds of state in one place is beneficial or not. But at least keeping all application state in one place has a big benefit, which is providing a consistent state across all components in our application.
Yet another trend is the use of pure components. What this means is that given the same inputs a component will always render the same output. There are no side effects happening inside these components.
This makes understanding and testing our components far easier than before, as they are more predictable.
Back to Elm
Continue reading %Functional Reactive Programming with Elm: An Introduction%