# Introduction to Elm programming language for React developers

Taking a short break from the [Let's code a Virtual DOM!](https://kkalamarski.me/series/virtual-dom) series, I decided to write an article on the **technology** that has inspired me to create my own virtual DOM in the first place.

That technology is a **programming language** called [Elm](https://elm-lang.org/). It can be used to build highly reactive **front-end** applications. 

What makes it different from Javascript or Typescript? 

## Why should you care?

It's a **purely functional** statically typed programming language - a **dialect** of [haskell](https://www.haskell.org/).

If at this point, you are a bit sceptical about it - that's fine. Functional languages **tend to be complex** and hard to learn. But Elm is different.

Its **simplicity** makes it **easy to learn** - you are not expected to know maths or anything from category theory upfront. Of course, there will be some **new things to learn** (and probably unlearn too).

It uses a **virtual DOM** and redux-like state management to build reactive UIs (*Redux was even inspired by Elm)*. So if you are a **React developer** you'll feel right at home!

Elm is **simple and logical**. Its compiler will guide you along the way - almost like a **pair-programming** buddy. All that makes it a perfect language to **learn functional programming**.

Why else should you bother to give Elm a try?

### No Runtime Exceptions

How many times have you encountered the **following errors** in your Javascript applications:
`TypeError: undefined is not a function`, `TypeError: Cannot read property 'value' of null`?

Elm is advertising that there are **"No Runtime Exceptions"** in applications built with it. It's because **the compiler** will catch all those errors in the build time. It can guarantee that if the code compiles, **it will not crash**.

### Excellent compiler

In Elm, the compiler is your **best friend**. On the top of the "no runtime exceptions" promise, it's known of well thought and **helpful error messages**.

It will guide you by hand, and will even **offer some suggestions** as to how to fix the error! 

![Zrzut ekranu 2022-05-10 o 23.18.22.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1652217509714/BfegqjuZG.png align="center")

### Enforced app structure

In React there are a million ways to do the same thing. Let's think about state management. Redux, Flux, MobX, Recoil and other libraries are used to do the same thing in a slightly different manner. If you happen to change a project, and it uses the library you don't know it means that you need to **waste your time** learning the new technology again.

In Elm, all applications look the same. All follow **the same pattern**. If you know how to work with one Elm app, you will quickly be able to switch between different applications without having to worry about re-learning everything from scratch.

![Zrzut ekranu 2022-05-10 o 23.15.38.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1652217342296/dpXR038aK.png align="center")

### Great performance

Elm is fast. As we've mentioned before, it uses a custom implementation of a virtual DOM, that has been designed for **speed and simplicity**. Elm **compiles to Javascript** but produces s**mall assets**, which can **boost the performance** of your app.

![Zrzut ekranu 2022-05-10 o 23.16.15.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1652217378665/6SF-EmXlN.png align="center")

## Show me the code!

If all of that convinces you to give Elm a try, it's high time to look at some code.

The easiest way to start working with Elm is to use an [Ellie editor](https://ellie-app.com/).

![Ellie](https://cdn.hashnode.com/res/hashnode/image/upload/v1652217970756/rQ-tj7M4w.png align="left")

Feel free to open this link in a new tab and follow along.

### Imports
Imports, like in many languages are placed on the top of the file.
In Elm, each file is a module and needs to have a unique name. It's set in the first line of the file, along with a list of exposed (or exported in JS term) functions.

```elm
module Main exposing (main)
```

### Type declarations
In Elm we are able to create custom types like this:

```elm
type alias Model =
    { count : Int }
```

This is an equivalent of Typescript's:

```typescript
type Model = { count: number }
```

Note the `alias` keyword. It's very important here, as Elm also allows us to create custom types that will be treated as values. The syntax for them can be seen below:

```elm
type Msg
    = Increment
    | Decrement
``` 

### Declaring functions
In Elm, everything is a function.

Let's take for example `initialModel`:

```elm
initialModel =
    { count = 0 }
```

Even though it looks like a variable assignment, in reality, it's a function. 
In Typescript it would look like this:

```typescript
const initialModel = () => ({ count: 0 })
```

If the function takes any arguments, they're placed before the `=` sign.

```elm
update msg model = 
  -- ...
```
| `--` is a comment in elm

### Type annotations

In the application generated by Ellie, over each function you can find a Type annotation for that function. They're optional but highly encouraged. 

```elm
update : Msg -> Model -> Model
update msg model =
  -- ...
```

It can be a little confusing at first, but `Msg -> Model -> Model` means that the first argument is of type `Msg`, the second is of type `Model` and the function returns a `Model` type.

It's like that because of a [partial application](https://en.wikipedia.org/wiki/Partial_application), a pattern found in many functional languages. 

## The application architecture

A basic Elm application consists of three functions: `view`, `init` and `update`.

```elm
main : Program () Model Msg
main =
    Browser.sandbox
        { init = initialModel
        , view = view
        , update = update
        }
```

- `init` is the initial state of the model of our application.
- `view` is the function that renders UI onto the screen
- `update` is a function fired every time a Msg (message or action in Redux) is sent. It would be a reducer in React world.

### The `view` function

The `view` function is a core of the app in Elm. It takes a `Model` as its argument and returns an `Html Msg` type.

```elm
view : Model -> Html Msg
view model =
    div []
        [ button [ onClick Increment ] [ text "+1" ]
        , div [] [ text <| String.fromInt model.count ]
        , button [ onClick Decrement ] [ text "-1" ]
        ]
```

What would this code look like in React?

```typescript
const view = (model: Model) => (
  <div>
    <button onClick={() => dispatch('Increment')}>
      +1
    </button>
    <div>
      {String(model.count)}
    </div>
    <button onClick={() => dispatch('Decrement')}>
      -1
    </button>
  </div>
)
```

The result of this code is a simple counter.

![counter](https://cdn.hashnode.com/res/hashnode/image/upload/v1652220024295/EFnE4YsF2.png align="left")

Now, what happens when someone clicks the button?

### Dispatching events

Let's focus on the part when an event is dispatched. It's happening in the `onClick` attribute of a button.

```elm
button [ onClick Increment ] [ text "+1" ]
```

The `onClick Increment` part is dispatching the `Increment` action on a button click.

Actions are called Messages in Elm. Two messages - Increment and Decrement - were defined in the code above:

```elm
type Msg
    = Increment
    | Decrement
``` 

Those messages are sent to the `update` function automatically every time the `onClick` handler is fired. No need to manually dispatch them.

## The `update` function

The state is managed in the `update` function. Every time a new message is sent, the update function updates the state.

```elm
update : Msg -> Model -> Model
update msg model =
    case msg of
        Increment ->
            { model | count = model.count + 1 }

        Decrement ->
            { model | count = model.count - 1 }
```

The update function takes two arguments, the first is a message sent, and the second is a previous model.

How could it be written in typescript?

```typescript
const update = (msg: Msg, model: Model): Model => {
  switch (msg) {
    case 'Increment':
      return { ...model, count: model.count + 1 }
      
    case 'Decrement':
      return { ...model, count: model.count - 1 }

    default:
      return model
  }
}
```

It behaves exactly like a reducer function known from Redux or the `useReducer` hook.

What's nice, Elm will make sure that all possible outcomes are handled properly:

Let's add a new Message `Reset`:

```elm
type Msg
    = Increment
    | Decrement
    | Reset
```

Now if we run the code we'll get the following compiler error:

![missing Reset](https://cdn.hashnode.com/res/hashnode/image/upload/v1652221111573/6G-3_bGCc.png align="left")

The compiler is telling us what we have missed!

## Conclusion

I hope that this short introduction got you interested in learning Elm. It's a fantastic language that makes development much more interesting. Of course, it will not replace React or Javascript. But it can help you to develop good practices and learn new approaches to software development.

If you would like to play around with the Elm code, I encourage you to try the following task:

| Add a reset button to the page

This will involve editing the ` view` function, updating the `Msg` type and adjusting the `update` function to reset the counter. 

If you are interested in learning more about Elm, let me know. I will be happy to continue this topic on this blog.

Thank you for your time, and see you in the next post 😊
