Notes on Elm

Nov 2, 2016

I recently got interested in the Elm programming language. A little while ago I started reading the PureScript docs and then later started learning Haskell. However I'm generally much more focused on frontend development and could never really see myself using either of those languages for much.

Elm has most of the awesome functional programming features of Haskell. It also has a lot of similarities with Redux and can actually be used to create real-world applications.

Here are some of my rough notes from reading through the Elm docs. I also implemented most of the examples from the docs, with my own modifications, in this repo.

Basic syntax

The Elm Architecture

Basically identical to Redux:

The view has type Model -> Html Msg which means that the generated HTML can output Msg values which automatically get fed into the update/model cycle for you (when initialising the app with main = Html.beginnerProgram { model = model, view = view, update = update })

HTML is basically generated with constructors named after the elements followed by a list of props then a list of children.

Project setup

npm i -g elm
elm package install
# Then open up http://localhost:8000/ for a pretty neat UI

Playing with the counter example

Something I don't understand:

I wrote this function to abstract away the creation of a button style:

buttonStyle : Model -> Attribute
buttonStyle model = style [ ("color", if model == 0 then "red" else "black") ]

And elm-reactor kept complaining with the following:

-- TOO FEW ARGUMENTS ------------------------- Main.elm

Type Html.Attribute has too few arguments.

39| buttonStyle : Model -> Attribute
Expecting 1, but got 0.

Removing the type works fine and loading it up in the repl tells me the type is the following:

<function> : number -> Html.Attribute a

I don't currently know what the a argument passed to the Html.Attribute type is doing...

Edit: After further experimentation, I think that Html.Attribute accepts one argument (to make it a generic type or whatever that's called in Elm). If that argument starts with a lower-case character then it is a generic type variable. However the actual type that it needs to match with in this case is the Msg type (because the attributes can potentially be handlers which return messages I guess).

Form example


For producing effects, your model should return a tuple of the new model plus an effect command. Use Cmd.none for an empty command.

Just wrote out the basic dice program from scratch without looking at anything for reference. Seems relatively straightforward. Apparently Sub and Cmd appear to be always available and they both have a .none property to do nothing.

Difference between type and type alias:

Http fetching seems okay, if a tad verbose:


Modules expose stuff at the top of the file:

module Counter exposing (Model, Msg, init, update, view)

In the above example, external code cannot instantiate a value of type Msg because it only has access to the Msg type and not the type constructors that make it up.

More notes on types

How to use in the real world


Then create ports with the following syntax:

port check : String -> Cmd msg

port suggestions : (List String -> msg) -> Sub msg

The syntax is a bit weird but the basic idea is that you use the first port and provide it with a string value. This then returns a command and when that command is passed to Elm, it notifies the JavaScript subscriber on that port with that string value.

The second type of port is given a function that can interpret whatever JavaScript gives it and returns a message. After being given a processing function, it returns a subscription which is passed to Elm and will process anything given on that port and return a message which gets dispatched to the update cycle.

Most JSON-like values can be transferred and there are various rules to prevent incorrect things getting in (if you try to pass something wrong from JavaScript it will throw an error before even reaching Elm).