My adventure with Elm @ NCrafts

Yan Cui - MY ADVENTURE WITH ELM from NCRAFTS Conferences on Vimeo.

with accompanying slides here:

My adventure with Elm @ Lambda Days 2015

Lambda Days 2015 - Yan Cui - My adventure with Elm from Erlang Solutions on Vimeo.

Elm and Myo playing together

I haven’t been able to stop playing around with my Myo armband since I got my hands on it this week. In truth it’s ruined a few of my plans for the weekend, but boy it’s been fun trying to get the Myo working with various apps and games.

Elm has also piqued my interest lately, so what better way to play with the Myo than to build a game in Elm that is best played using gestures? And along comes Thunder Cow, a light-hearted game where you use the fist and fingersSpread postures to start and stop a moving arrow. The goal is to time your release so that the arrow stops in the red zone.

Embedded image permalink

To play using the Myo armband you also need to add this Lua script into your Myo Script Manager. After you’ve added the script, head over here to give it a go.

The Elm source code for the game is available here. There is no native support for sound in Elm, so I had to resort to using Elm’s JS interop capabilities to invoke Javascript functions to play the mp3 files.

Elm – building a version of Snake in under 100 lines of code

It’s been a little while since I last spent time with Elm, and since Elm 0.13 was recently announced so what better time to get my Elm hat back on and see what’s new.

There’s a new-look online debugger which looks prettier than before:

image

but more important than that, is the new Elm Reactor command line tool which powers both the online debugger. With the Elm Reactor you can run your own time-travelling debugger locally and as you edit your Elm source files you can watch your application update in real-time while retaining the ability to go back in time by play back previous events.

There’s also a new command line package manager – Elm Get – which gives you the ability to easily add community Elm libraries to your project, or to publish your own libraries to the Elm Public Library. Overall it works very similar to the how Dart-pub works and whilst I haven’t published any libraries myself it seems a straight forward affair.

There are a couple of small breaking changes in the core language, and it’s great to see that F#’s functional composition operators (<< and >>) have been adopted and released in this version!

 

Now that I’ve caught up on the changes, I put together a simple implementation of Snake, and to my pleasant surprise the whole thing came in at less than 100 LOC although admittedly not the easiest 100 LOC I’ve ever written. I had to really think about what I’m doing (which is a good thing), the lack of IDE support occasionally gets in the way, and I find the error message hard to read sometimes (although it’s much better formatted when you work against Elm Reactor running locally.

If you’ve got a few minutes to kill, why not give it a go:

image

and feel free to check out the source code on Github.

 

Links

Elm Reactor – Time Travel made Easy

Elm 0.13 – Architecture Improvements

Elm startup project

Elm-Snake project page

Elm – functional reactive dreams + missile command

I saw this tweet on my timeline the other day..

image

which reminded me again to look at Elm and I’ve spend the last week or so getting myself immersed with this wonderful little language built around the idea of functional reactive programming.

My first impressions of Elm so far have been very positive, there are some genuinely interesting things here, such as its Record and Signal types and its interactive debugger which is heavily influenced by Bret Victor’s work.

 

The Basics

Syntactically, Elm looks like many functional language (and Python) out there – no curly brackets, whitespace matters, etc. – which is perhaps unsurprising as there’s seems to be a strong Haskell influence here.

 

Tuples

Tuples are enclosed in parentheses and separated by comma (,) – e.g. ( 4, “3” ) is a tuple of the integer 4 and the string “3”.

You can also use the helper functions (,) (,,) (,,,) … etc. to construct tuples with the required number of items.

image

 

Records

At first glance Elm’s record type looks very similar to F#’s record type:

  • both are lightweight labelled data structure
  • both support pattern matching
  • fields are immutable (but F# supports optional mutability)
  • both support copy-and-update semantics to create a new record based on an existing record
  • both support polymorphic functions (though in F# it’s more idiomatic to use members instead)

However, upon closer inspection you find some interesting additions with Elm, most notably:

  • extensibility – besides the copy-and-update semantic, you can also add and remove fields at the same time
  • records uses structural typing – a function can accept records of any kind so long they have the required fields (e.g. whoAreYou { name } = … takes any record that has a name field)
  • record type aliases can be composed together

 

Have a look at my last post to see a more detailed run-down of the similarities and differences between records in F# and Elm.

 

Algebraic Data Structure

Elm supports algebraic data structures (i.e. F# discriminated unions), there are a number of built-in algebraic types such as the Maybe type. You can also define your own algebraic types using the data keyword.

image

 

F# Pipes

It’s also nice to see F#’s pipes make an appearance in Elm and that Elm’s creators are receptive to adopting F#’s functional composition operators << and >> too, if adopted I really think they can make code that composes functions more readable and intuitive.

image

 

Pattern Matching

Elm supports the case..of syntax (another example of its Haskell heritage) for pattern matching against variables as you can see from the snippet above.

Elm doesn’t have when guards in its pattern matching syntax yet, but you can work around this by using the multi-way if expressions for now, which actually reads like pattern match clauses rather than the traditional if-elif-elif-else.

image

Elm also supports pattern matching against tuples, records and lists, etc. in much the same way as you’ve seen in F# or Haskell, for instance, you can pattern match against a record using the { fieldName1, fieldName2, … } syntax:

image

 

Anonymous Functions

Elm uses the same syntax as Haskell to define anonymous functions.

image

 

Currying

As you’d expect, Elm supports currying.

image

The standard library also has two helper functions – curry and uncurry – to help you change how arguments are passed to a function, which comes in handy sometimes.

  • curry : ( ( a, b ) –> c ) –> a –> b –> c
  • uncurry : ( a –> b –> c ) –> ( a, b ) –> c

 

let..in syntax

Like many other functional languages (Haskell, F#, etc.), in Elm the last expression of a function provides its return value and whilst F# has moved away from the let..in syntax from its own OCaml roots, Elm still uses the let..in syntax.

You can specify multiple variables within one let clause, e.g.

image

And you can also define inner functions in the same way too:

image

 

JS Interop

Interop with Javascript is provided via ports, which I haven’t played around with much, but you can read all about it here.

 

The Good stuff

In Elm, much of what you do revolves around Signals (which is Elm’s equivalent of Rx’s observables) and the language (along with its standard libraries) gives you a very different way of thinking about GUI development to the traditional DOM based approaches. If you are familiar with Rx (or RxJs, the Javascript port of the Rx API) or functional reactive programming* in general then you should feel right at home here.

Elm’s standard library comes with a number of built-in signals – mouse positions, clicks, window dimensions, timer events, etc. From these built-in signals you can then compose and map over them, the built-in Signal library provides quite a number of functions to make life easy there.

 

Lift functions

You can use the lift functions (lift, lift2, lift3, … lift8) to apply a normal function over signals. In Rx you’d do this with Observable.Select, but the way you can combine signals together using the shorthand operators <~ and ~ is really quite elegant.

For instance, you can pass the signals of your mouse position and the coordinate of your clicks into a function like this:

And here is what the code above generates:

Pretty simple, huh?

 

Merging/combining signals

You can use the merge, merges or combine functions from the Signal standard library to concatenate multiple signals of the same type into one unified signal. This is equivalent to Rx’s Observable.Concat operation.

This comes handy when you have multiple sources of inputs of the same kind, or when you use algebraic data type to help unify input signals of different kinds.

Take the Missile Command game below for instance, the game loop follows the simple pattern of: action –> state transition –> redraw updated state. However, there are three different kinds of input that would trigger state transition:

  1. frames – to draw the game at 50 FRS means every 20ms we need to move the missile along a certain distance along its path as dictated by its speed
  2. player actions – when the player clicks on the screen we should launch a new missile towards the coordinate where the user clicked
  3. enemy missiles – every x seconds we need to launch a random number of enemy missiles

Each type of input has a different set of parameters associated with them, unified by a single algebraic data type.

Signals representing each of these input types can then be merged together with the merge function and passed into the main game transition logic.

 

In addition, the Signal library also provides a set of useful functions for composing signals, including foldp, count, keepIf, dropIf, keepWhen, and sampleOn. Again, all of these can be mapped directly to Rx extension methods.

In fact, all the capabilities of working with signals I have seen in Elm can be found in Rx and by extension, in C#, F#, Java, Javascript and Dart thanks to the widespread reach of the Rx API and the effort by the developer community to adopt it.

However, because Rx exist as a library in those languages, it doesn’t force you to fundamentally change the way you view UI development because you always have a way out whenever things get uncomfortable (which should be often, if you’re challenging yourself to go outside your comfort zone). In Elm, however, there’s no other way, so you have to think ‘reactive’ all the way through. From a practical point of view this might sound restrictive, but there’s really no better way to learn the functional reactive paradigm than to fully immerse and commit yourself to it.

 

The Debugger

If you have been following Bret Victor’s work in recent years (which amongst others have inspired projects such as LightTable, Khan academy’s UI design as well as Elm’s online debugger), you might have had to repeatedly scrape pieces of your brain from the walls thanks to Bret’s super awesome demos.

I recommend giving this page a good read to see how it works and how Elm makes it possible.

Here’s a short demo video to show its time-travelling capabilities in action.

 

The Not So Good stuff

  • The language is still very young so expect lots of breaking changes and broken examples from around the internet as it evolves. Personally, I think this is a good thing, it’s better for the language to learn and evolve away from its early mistakes than to forever live with the sins of its youth.
  • IDE tooling is lacking. Whilst the online editor and debugger can provide hints (i.e. function signatures and a link to the online doc for the function, see below) for functions and types from the standard libraries, they don’t work on user-defined functions and types. You can also just use any text editor such as Notepad++ or Sublime Text that gives you syntax highlighting (Haskell highlighting usually works pretty well) but I usually look for much more support from my development environment and seeing Bret Victor’s work only raises my expectations and Elm’s online debugger is a decent first step.

image

  • If you’re developing with the online debugger then be sure to save your changes regularly, to a source controlled file preferably. As the debugger executes your code it collects events along the way, which is how it enables this awesome time-travelling capability to go back in time to see the effect of your changes as you make them. With the Auto-Update option turned on you get to see your changes reflected right away which is really nice, the downside being that if it has collected a fair number of events it can hang/crash the browser and you lose your unsaved changes along the way. Hopefully that’s a painful lesson you won’t have to learn the hard way.
  • There are a fair amount of guided tutorials for the basic things, but once you start to get into the intermediate/advanced topics you’re mostly left to work out how to do things based on available examples that are barely commented and those auto-generated docs for libraries really don’t do the readers justice. This is common for new languages, I have had the same experience with Dart too despite Dart being much more mature and have a bigger community around it (and not to mention having a company like Google behind it).

 

Missile Command

Finally, to aid my learning process, I put together a simple implementation of “Missile Command” which was fun to do and helped give me a sense of direction when trying to figure out what I can and cannot do in Elm.

I have written this in a way that’s perhaps more verbose than the official examples, with lots of type annotations to make up for the lack of support from the online editor/debugger. Even so, the source code came in at less than 250 lines, which is really encouraging, imagine the level of productivity a more competent Elm developer is able to achieve!

The source code is available on Github here, you can copy the content of main.elm into the Elm online editor to try it out.

 

* on the topic of reactive programming, I came across this talk by Erik Meijer, the father of Rx, titled Duality and the end of Reactive and it’s well worth a watch. Without going into too much detail and robbing you of the joy of making your own discoveries and conclusions from it, my key takeaway from the talk came from Erik’s closing remark:

Reactive is Dead, long live composing side effects.

Now, I don’t think Erik is telling us to stop using Rx or the reactive paradigm that he has done so much to popularize, but to shift our focus from the act of doing them (composing signals/observables and then writing code that reacts to them) to the why – which is to help us rationalize side effects and compose them, and making the implicit relationships between side effects explicit.

 

Related Reading

Erik Meijer – duality and the end of reactive <- (must watch)

Elm’s time-travelling debugger

Elm’s signals

Elm’s extensible records

Academic paper – Extensible records with scoped labels

Missile Command (demo)

Missile Command (source code)

Contrasting F# and Elm’s record types

F# – record types vs classes

Dart – emulating algebraic data type

Udi Dahan – Making roles explicit

Bret Victor – Inventing on Principle

Bret Victor – Stop Drawing Dead Fish

Bret Victor – Media for Thinking the Unthinkable