Elm Language Notes

So I’ve been playing with Elm and I like it quite a bit.

This is some random stuff that I find is worth sharing, in no particular order.

Pipe operator

Elm has, as Elixir, taken the pipe operator from F#.

But contrary to Elixir, the implement both the |> and <| operators. Elixir only implements |>.

Elixir and Elm implement the right-pointing pipe with one important difference. In Elixir the left-value is passed as the first argument to the function while in Elm is the second.

In Elixir:

my_func(first, second)
# could also be written in Elixir as
first |> my_func(second)

In Elm:

my_func first second
-- could also be written in Elm as
second |> my_func(first)

This also means that in Elixir, most modules expect the first parameter to be of the type the module expects, while in Elm is the other way around.

Code Formatting

If you’ve never seen Elm code before, you could think that it has has some unique syntax or indentation requirements.

It turns out, Elm kindle asks you to indent code in a certain way to make git (or whatever) merges and diffs more clear. It has nothing to do with the syntax.

I didnt like it at first, but I have to confess that I agree with their reasons. And now I dont find it as bad as I first thought.

defaults =
  { url = "http://127.0.0.1:5410/render/"
  , width = 400
  , height = 200
  , fontSize = 110
  , from = "-2h"
  , font = "DroidSans"
  , bgcolor = "#ffffff"
  }

If you indent this way and you add/remove from the list, the change as see in a diff will only affect one line.

Partial Application

At first I was confused why the documentation for functions defines its paremeters like

sum: Float -> Float -> Float

instead of, in c-ish:

float div(float numa, float numb);

My head was reading: “sum returns a float, which then returns a float which finally returns a float!”

It made no sense.

Until I realized that partial application is first-class, so you can call sum like:

(sum 1) 2

If you only pass one parameter, and you could!, you will get back a function that accepts the second parameter. If you then pass the second parameter you will get the final result.

You can see partial application used in the next example call of List.map:

-- renderImg expects 2 parameters
renderImg: Address Action -> Chart -> Html
renderImg address chart =
  img [(onClick address) Zoom, src chart.url] []     

-- here we only pass one parameter (address), that will
-- return an anonymous function that will be called by
-- map, effectively passing every element of charts to it, thus
-- passing the second (and missing) parameter.
List.map (renderImg address) model.charts