I saw this tweet on my time­line the other day..

image

which reminded me again to look at Elm and I’ve spend the last week or so get­ting myself immersed with this won­der­ful lit­tle lan­guage built around the idea of func­tional reac­tive pro­gram­ming.

My first impres­sions of Elm so far have been very pos­i­tive, there are some gen­uinely inter­est­ing things here, such as its Record and Sig­nal types and its inter­ac­tive debug­ger which is heav­ily influ­enced by Bret Victor’s work.

 

The Basics

Syn­tac­ti­cally, Elm looks like many func­tional lan­guage (and Python) out there – no curly brack­ets, white­space mat­ters, etc. – which is per­haps unsur­pris­ing as there’s seems to be a strong Haskell influ­ence here.

 

Tuples

Tuples are enclosed in paren­the­ses and sep­a­rated by comma (,) – e.g. ( 4, “3” ) is a tuple of the inte­ger 4 and the string “3”.

You can also use the helper func­tions (,) („) („,) … etc. to con­struct tuples with the required num­ber of items.

image

 

Records

At first glance Elm’s record type looks very sim­i­lar to F#’s record type:

  • both are light­weight labelled data structure
  • both sup­port pat­tern matching
  • fields are immutable (but F# sup­ports optional mutability)
  • both sup­port copy-and-update seman­tics to cre­ate a new record based on an exist­ing record
  • both sup­port poly­mor­phic func­tions (though in F# it’s more idiomatic to use mem­bers instead)

How­ever, upon closer inspec­tion you find some inter­est­ing addi­tions with Elm, most notably:

  • exten­si­bil­ity – besides the copy-and-update seman­tic, you can also add and remove fields at the same time
  • records uses struc­tural typ­ing – a func­tion 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 com­posed together

 

Have a look at my last post to see a more detailed run-down of the sim­i­lar­i­ties and dif­fer­ences between records in F# and Elm.

 

Alge­braic Data Structure

Elm sup­ports alge­braic data struc­tures (i.e. F# dis­crim­i­nated unions), there are a num­ber of built-in alge­braic types such as the Maybe type. You can also define your own alge­braic types using the data keyword.

image

 

F# Pipes

It’s also nice to see F#’s pipes make an appear­ance in Elm and that Elm’s cre­ators are recep­tive to adopt­ing F#’s func­tional com­po­si­tion oper­a­tors « and » too, if adopted I really think they can make code that com­poses func­tions more read­able and intuitive.

image

 

Pat­tern Matching

Elm sup­ports the case..of syn­tax (another exam­ple of its Haskell her­itage) for pat­tern match­ing against vari­ables as you can see from the snip­pet above.

Elm doesn’t have when guards in its pat­tern match­ing syn­tax yet, but you can work around this by using the multi-way if expres­sions for now, which actu­ally reads like pat­tern match clauses rather than the tra­di­tional if-elif-elif-else.

image

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

image

 

Anony­mous Functions

Elm uses the same syn­tax as Haskell to define anony­mous functions.

image

 

Cur­ry­ing

As you’d expect, Elm sup­ports currying.

image

The stan­dard library also has two helper func­tions – curry and uncurry – to help you change how argu­ments are passed to a func­tion, which comes in handy sometimes.

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

 

let..in syn­tax

Like many other func­tional lan­guages (Haskell, F#, etc.), in Elm the last expres­sion of a func­tion pro­vides its return value and whilst F# has moved away from the let..in syn­tax from its own OCaml roots, Elm still uses the let..in syntax.

You can spec­ify mul­ti­ple vari­ables within one let clause, e.g.

image

And you can also define inner func­tions in the same way too:

image

 

JS Interop

Interop with Javascript is pro­vided 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 Sig­nals (which is Elm’s equiv­a­lent of Rx’s observ­ables) and the lan­guage (along with its stan­dard libraries) gives you a very dif­fer­ent way of think­ing about GUI devel­op­ment to the tra­di­tional DOM based approaches. If you are famil­iar with Rx (or RxJs, the Javascript port of the Rx API) or func­tional reac­tive pro­gram­ming* in gen­eral then you should feel right at home here.

Elm’s stan­dard library comes with a num­ber of built-in sig­nals – mouse posi­tions, clicks, win­dow dimen­sions, timer events, etc. From these built-in sig­nals you can then com­pose and map over them, the built-in Sig­nal library pro­vides quite a num­ber of func­tions to make life easy there.

 

Lift func­tions

You can use the lift func­tions (lift, lift2, lift3, … lift8) to apply a nor­mal func­tion over sig­nals. In Rx you’d do this with Observable.Select, but the way you can com­bine sig­nals together using the short­hand oper­a­tors <~ and ~ is really quite elegant.

For instance, you can pass the sig­nals of your mouse posi­tion and the coor­di­nate of your clicks into a func­tion like this:

And here is what the code above generates:

Pretty sim­ple, huh?

 

Merging/combining sig­nals

You can use the merge, merges or com­bine func­tions from the Sig­nal stan­dard library to con­cate­nate mul­ti­ple sig­nals of the same type into one uni­fied sig­nal. This is equiv­a­lent to Rx’s Observable.Concat operation.

This comes handy when you have mul­ti­ple sources of inputs of the same kind, or when you use alge­braic data type to help unify input sig­nals of dif­fer­ent kinds.

Take the Mis­sile Com­mand game below for instance, the game loop fol­lows the sim­ple pat­tern of: action –> state tran­si­tion –> redraw updated state. How­ever, there are three dif­fer­ent kinds of input that would trig­ger state transition:

  1. frames – to draw the game at 50 FRS means every 20ms we need to move the mis­sile along a cer­tain dis­tance along its path as dic­tated by its speed
  2. player actions – when the player clicks on the screen we should launch a new mis­sile towards the coor­di­nate where the user clicked
  3. enemy mis­siles – every x sec­onds we need to launch a ran­dom num­ber of enemy missiles

Each type of input has a dif­fer­ent set of para­me­ters asso­ci­ated with them, uni­fied by a sin­gle alge­braic data type.

Sig­nals rep­re­sent­ing each of these input types can then be merged together with the merge func­tion and passed into the main game tran­si­tion logic.

 

In addi­tion, the Sig­nal library also pro­vides a set of use­ful func­tions for com­pos­ing sig­nals, includ­ing foldp, count, keepIf, dropIf, keep­When, and sam­pleOn. Again, all of these can be mapped directly to Rx exten­sion methods.

In fact, all the capa­bil­i­ties of work­ing with sig­nals I have seen in Elm can be found in Rx and by exten­sion, in C#, F#, Java, Javascript and Dart thanks to the wide­spread reach of the Rx API and the effort by the devel­oper com­mu­nity to adopt it.

How­ever, because Rx exist as a library in those lan­guages, it doesn’t force you to fun­da­men­tally change the way you view UI devel­op­ment because you always have a way out when­ever things get uncom­fort­able (which should be often, if you’re chal­leng­ing your­self to go out­side your com­fort zone). In Elm, how­ever, there’s no other way, so you have to think ‘reac­tive’ all the way through. From a prac­ti­cal point of view this might sound restric­tive, but there’s really no bet­ter way to learn the func­tional reac­tive par­a­digm than to fully immerse and com­mit your­self to it.

 

The Debug­ger

If you have been fol­low­ing Bret Vic­tor’s work in recent years (which amongst oth­ers have inspired projects such as Light­Table, Khan academy’s UI design as well as Elm’s online debug­ger), you might have had to repeat­edly scrape pieces of your brain from the walls thanks to Bret’s super awe­some demos.

I rec­om­mend giv­ing 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 capa­bil­i­ties in action.

 

The Not So Good stuff

  • The lan­guage is still very young so expect lots of break­ing changes and bro­ken exam­ples from around the inter­net as it evolves. Per­son­ally, I think this is a good thing, it’s bet­ter for the lan­guage to learn and evolve away from its early mis­takes than to for­ever live with the sins of its youth.
  • IDE tool­ing is lack­ing. Whilst the online edi­tor and debug­ger can pro­vide hints (i.e. func­tion sig­na­tures and a link to the online doc for the func­tion, see below) for func­tions and types from the stan­dard libraries, they don’t work on user-defined func­tions and types. You can also just use any text edi­tor such as Notepad++ or Sub­lime Text that gives you syn­tax high­light­ing (Haskell high­light­ing usu­ally works pretty well) but I usu­ally look for much more sup­port from my devel­op­ment envi­ron­ment and see­ing Bret Victor’s work only raises my expec­ta­tions and Elm’s online debug­ger is a decent first step.

image

  • If you’re devel­op­ing with the online debug­ger then be sure to save your changes reg­u­larly, to a source con­trolled file prefer­ably. As the debug­ger exe­cutes your code it col­lects events along the way, which is how it enables this awe­some time-travelling capa­bil­ity 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 down­side being that if it has col­lected a fair num­ber of events it can hang/crash the browser and you lose your unsaved changes along the way. Hope­fully that’s a painful les­son you won’t have to learn the hard way.
  • There are a fair amount of guided tuto­ri­als for the basic things, but once you start to get into the intermediate/advanced top­ics you’re mostly left to work out how to do things based on avail­able exam­ples that are barely com­mented and those auto-generated docs for libraries really don’t do the read­ers jus­tice. This is com­mon for new lan­guages, I have had the same expe­ri­ence with Dart too despite Dart being much more mature and have a big­ger com­mu­nity around it (and not to men­tion hav­ing a com­pany like Google behind it).

 

Mis­sile Command

Finally, to aid my learn­ing process, I put together a sim­ple imple­men­ta­tion of “Mis­sile Com­mand” which was fun to do and helped give me a sense of direc­tion when try­ing to fig­ure out what I can and can­not do in Elm.

I have writ­ten this in a way that’s per­haps more ver­bose than the offi­cial exam­ples, with lots of type anno­ta­tions to make up for the lack of sup­port from the online editor/debugger. Even so, the source code came in at less than 250 lines, which is really encour­ag­ing, imag­ine the level of pro­duc­tiv­ity a more com­pe­tent Elm devel­oper is able to achieve!

The source code is avail­able on Github here, you can copy the con­tent of main.elm into the Elm online edi­tor to try it out.

 

 

* on the topic of reac­tive pro­gram­ming, I came across this talk by Erik Mei­jer, the father of Rx, titled Dual­ity and the end of Reac­tive and it’s well worth a watch. With­out going into too much detail and rob­bing you of the joy of mak­ing your own dis­cov­er­ies and con­clu­sions from it, my key take­away from the talk came from Erik’s clos­ing remark:

Reac­tive is Dead, long live com­pos­ing side effects.

Now, I don’t think Erik is telling us to stop using Rx or the reac­tive par­a­digm that he has done so much to pop­u­lar­ize, but to shift our focus from the act of doing them (com­pos­ing signals/observables and then writ­ing code that reacts to them) to the why – which is to help us ratio­nal­ize side effects and com­pose them, and mak­ing the implicit rela­tion­ships between side effects explicit.

 

Related Read­ing

Erik Mei­jer – dual­ity and the end of reac­tive <- (must watch)

Elm’s time-travelling debugger

Elm’s sig­nals

Elm’s exten­si­ble records

Aca­d­e­mic paper – Exten­si­ble records with scoped labels

Mis­sile Com­mand (demo)

Mis­sile Com­mand (source code)

Con­trast­ing F# and Elm’s record types

F# – record types vs classes

Dart – emu­lat­ing alge­braic data type

Udi Dahan – Mak­ing roles explicit

Bret Vic­tor – Invent­ing on Principle

Bret Vic­tor – Stop Draw­ing Dead Fish

Bret Vic­tor – Media for Think­ing the Unthinkable

Share

Hav­ing spent some time this week with Elm I have seen plenty of things to make me like it, a more in-depth review of my expe­ri­ence with Elm so far is in the works but for now I want to talk about Elm’s record type and how it com­pares with F# record type which us F# folks rely upon so often. At first glance, there are a lot of sim­i­lar­i­ties between the two, but upon closer inspec­tion you’ll find some notable differences.

 

F#

In F#, to cre­ate a record you first have to declare its type, and the idiomatic F# way is to use records as light­weight data con­tain­ers but you can option­ally add ‘mem­bers’ (i.e. prop­er­ties or meth­ods) to your record types too.

Whilst fields are immutable by default, they can be made muta­ble if you explic­itly mark them with the muta­ble key­word. Whilst this is not an encour­aged prac­tice the option is there for you if you need it, usu­ally as an opti­miza­tion to avoid the GC over­head of using the copy-and-update oper­a­tion (under the hood F#’s records are com­piled to class types so they’re heap allo­cated and there­fore incurs allo­ca­tion and col­lec­tion cost), or because you need to interop with C#.

Advan­tages of using records over classes include the abil­ity to use pat­tern match­ing and that they use struc­tural equal­ity seman­tic. Given their role as light­weight data con­tain­ers, like tuples, is the sen­si­ble choice in most cases but you can still over­ride this behav­iour if you need to.

Whilst F# record types can imple­ment inter­faces, they can­not be inher­ited from, a fact that you can argue for or against. Per­son­ally I’m on the ‘argue for’ camp as it gives me future guar­an­tee of safety and if I need to sup­port vari­ance I will intro­duce inter­faces and/or use com­po­si­tion instead.

 

Elm

In Elm, a record can exist on its own with­out you hav­ing to first define a type for it. Defin­ing a type merely cre­ates an alias to help make your code more read­able and give you some sta­tic safety where it’s needed.

Elm doesn’t have classes but its records allow poly­mor­phic func­tions to be defined as part of the record. How­ever, these are not the same as F# record’s instance mem­bers as there is no this or self key­words in Elm (because Elm’s cre­ators con­sider it an extremely bad prac­tice to mix data and logic, which I imag­ine most func­tional pro­gram­mers will agree).

Unsur­pris­ingly, Elm’s records can be pat­tern matched, but one caveat I found is that as far as I can tell there’s no way to cap­ture two records with the same field into two dif­fer­ent local vari­ables (see exam­ple below).

 

So far we have seen that Elm’s records are pretty sim­i­lar to their F# coun­ter­parts, where things get inter­est­ing is the exten­si­bil­ity options you have with Elm’s records.

Exten­si­ble Records

On top of the clone-and-update oper­a­tions (using the | label <- value syn­tax) you can also:

  • add new fields using the = oper­a­tor, e.g. { x | species = “Jade Dragon” } adds new species field with the value “Jade Dragon”
  • remove fields by using the minus oper­a­tor, e.g. { x – age } removes the age field from x when cloning

 

Com­posi­ble Record Types

Type aliases defined using the { x | label : type } syn­tax (like Named and Aged in the above exam­ple) can be com­posed together using a some­what strange syn­tax, e.g. Name(Aged {}) which says that the record must con­tain all the fields defined in both Named and Aged. The inner most { } in this case rep­re­sents an empty record, you can spec­ify bespoke labels and asso­ci­ated types there or use a type alias that is defined using the { label : type } syn­tax, like the Char­ac­ter type alias we defined in the above example.

 

Struc­tural Typing

Finally, Elm’s records sup­port struc­tural typ­ing which allows func­tions to accept any record that has the required fields, this gives you the ben­e­fit of dynamic languages.

In F#, whilst you don’t need to explic­itly spec­ify the type of the record when pat­tern match­ing (e.g. let show­Name { Name = name } = …), the type infer­ence process will still choose a type for you so you’re sta­t­i­cally bound to a par­tic­u­lar type. You can, how­ever, sup­port struc­tural typ­ing in a sim­i­lar way using sta­t­i­cally resolved type para­me­ters which also works on nor­mal class types but you lose the abil­ity to use pat­tern match­ing in the process, and I always find their syn­tax a lit­tle clumsy so wher­ever pos­si­ble I would use inter­faces instead.

 

Related Read­ings

F# – Record types vs classes

F# – Ref­er­en­tial equal­ity for Record types

F# per­for­mance test – structs vs Records

F# – sta­t­i­cally resolved type parameters

F# – XmlSe­ri­al­izer, Record types and [CLIMutable]

F# – Seri­al­iz­ing F# Record types

AOP – string intern­ing with Post­Sharp on F# record types

Elm – Exten­si­ble Records

Research paper – Exten­si­ble records with scoped labels

Share

Since I’ve been exper­i­ment­ing with Sen­try and hack­ing around in Dart again lately, so what bet­ter way is there to com­bine these two activ­i­ties than to write a Dart client for Sentry?

That said, there is already a Javascript client library for Sen­try, which via the dart:js library you can prob­a­bly save your­self some code by writ­ing a wrap­per around the Javascript library instead. But I chose to write the client from scratch because:

  1. it’s more fun
  2. you can take advan­tage of Dart’s sup­port for sta­tic type checking
  3. you can make use of Dart’s iso­lates (think F# mail­box or Erlang processes, iso­lates is Dart’s imple­men­ta­tion of Carl Hewitt’s actor model) to abstract over mak­ing con­cur­rent requests and han­dling retries, etc.
  4. wrap­ping the Javascript library means hard depen­dency on the Javascript library being present, which means you won’t be able to use it on the server side
  5. it’s more fun!

 

Update 05/07/2014 : I had pre­vi­ously stated that raven-js had depen­den­cies on jQuery, ember, etc. that was incor­rect. As they were in fact raven-js plu­g­ins for those frame­works (as stated in its Plu­g­ins doc­u­men­ta­tion page here) and the raven-js itself doesn’t have any dependencies.

 

And the result is a small (~600 LOC) Dart library called raven_dart, that allows you to cap­ture generic mes­sages or excep­tions as events in Sen­try. The most basic usage would look like this:

Oper­a­tional params can be used to cus­tomize the behav­iour of cap­tureMes­sage and cap­ture­Ex­cep­tion, such as adding tags, or other meta­data to go along with the events.

Fol­low­ing the offi­cial guide­lines on writ­ing a Sen­try client, the library supports:

  • DSN con­fig­u­ra­tion via con­struc­tor argument
    • null means disabled
  • Grace­ful fail­ure handling
    • fall­back to log­ging to con­sole when Sen­try is disabled
    • retry on error (except for HTTP sta­tus codes 400, 401, 403, and 503)
    • con­fig­urable max no. of retries
    • expo­nen­tial delay when retrying
    • tem­porar­ily dis­able if Sen­try is unavail­able (503)
  • Sup­port for tagging
    • com­mon tags can be pro­vided in the client constructor
    • addi­tional tags are sup­plied for each event
    • when com­mon and event-specific tags over­lap, both are sent as part of the event
  • Non-blocking event submission
    • events are sent to avail­able iso­lates in round-robin fash­ion, whom then process them asyn­chro­nously and concurrently
    • con­fig­urable level of con­cur­rency per core which deter­mines num­ber of iso­lates run­ning at the same time
  • Basic data sanitization/scrubbing
    • credit card number-like fields are scrubbed
    • Sen­try key and secrets are scrubbed
    • Val­ues that look like pass­words or secrets are scrubbed

 

Please give it a try and let me know what you think, if you find any bugs or have feed­backs in gen­eral, feel free to add them to the issues page.

 

Related Links

raven_dart home­page

raven_dart on pub.dartlang.org

Libraries for C# and F# for eas­ier inte­gra­tion with Sentry

Emu­lat­ing F#’s dis­crim­i­nated unions (aka alge­braic data types) in Dart

Emu­lat­ing enums in Dart

Take­aways from Hewitt, Mei­jer and Szyperski’s talk on the Actor model

Share

DISCLAIMER : as always, you should bench­mark against your pay­load and use case, the bench­mark num­bers I have pro­duced here is unlikely to be rep­re­sen­ta­tive of your use cases and nei­ther is any­body else’s bench­mark numbers.

You can use the sim­ple test har­ness I cre­ated and see these exam­ple code to bench­mark against your par­tic­u­lar payload.

 

Binary Seri­al­iz­ers

All seri­al­iz­ers are updated to the cur­rent lat­est version.

image

image

Ver­sions tested:

Protobuf-net 2.0.0.668
Mes­sagePack 0.1.0.2011042300
FsPick­ler 0.9.5-alpha
Fil­bert 0.2.0
Json.Net 6.0.3
Flu­o­rineFx 1.2.4

 

JSON Seri­al­iz­ers

FastJ­son­Parser (which only sup­ports dese­ri­al­iza­tion and comes under the System.Text.Json name­space) was added to the mix, all other seri­al­iz­ers are updated the cur­rent lat­est version.

image

image

Ver­sions tested:

Jil 1.5.0
ServiceStack.Text 4.0.22
Json.Net 6.0.3
fastJ­son 2.1.1.0
Mon­goDB Drive 1.9.1
System.Json 4.0.20126.16343
System.Text.Json 1.9.9.1
JsonFx 2.0.1209.2802
Jay­Rock 0.9.16530
Share

Here at Gamesys social team, we’re rethink­ing our cur­rent approach to log­ging in gen­eral, from both server and client’s per­spec­tive. Hav­ing looked at many dif­fer­ent alter­na­tives (it was a lit­tle hard to imag­ine how crowded a space log aggre­ga­tion and visu­al­iza­tion is..) one of the ser­vices which we have decided to exper­i­ment with is Sen­try.

Sen­try is a fairly sim­ple ser­vice, with an easy to use API and straight for­ward to inte­grate with, espe­cially if you already have a client library (the Sen­try doc refers to them them as Ravens) for your lan­guage of choice. On the .Net side of things, you have a lit­tle library called SharpRaven.

As for inte­gra­tion, using cus­tom log4net appen­der such as this one is obvi­ously a good way to go, but you still need to imple­ment the try-catch-log pat­tern every­where though, unless you’re happy for these excep­tions to bub­ble all the way up to the app domain and catch them there. And when I see imple­men­ta­tion pat­terns I see oppor­tu­ni­ties to auto­mate them with Post­Sharp!

C# cus­tom attributes

If you grab the SharpRaven-Contrib pack­age from Nuget you’ll have access to a pair of cus­tom attrib­utes – Raven­Lo­gEx­cep­tion and Raven­Lo­gEx­e­cu­tion­TimeAt­tribute – when you open the SharpRaven name­space. For example,

The attrib­utes does what they say on the tin, Raven­Lo­gEx­cep­tion cap­tures and logs excep­tion infor­ma­tion as errors to Sen­try whilst Raven­Lo­gEx­e­cu­tion­Time mon­i­tors exe­cu­tion time of your meth­ods and logs any method exe­cu­tion that took longer than your given thresh­old as warn­ings to Sen­try.

For F# how­ever, whilst the attrib­utes would still work for meth­ods, chances are you will be spend­ing most of your time work­ing and com­pos­ing func­tions instead and these attrib­utes won’t help you there. So for F# I decided to do some­thing slightly different.

F# work­flows

Thank­fully, in F#, we have com­pu­ta­tion expres­sions* (aka work­flows) which already power lan­guage fea­tures such as async work­flows and sequence comprehensions.

Using the work­flows defined in the SharpRaven-ContribFs pack­age you can cre­ate blocks of code where:

  • any unhan­dled excep­tions are logged as Error in Sen­try
  • if the block of code takes longer than the spec­i­fied thresh­old to exe­cute, it’ll be logged as a warn­ing in Sen­try

and your code remains unchanged, you sim­ply wrap them in { }:

Of course, you can also just cre­ate wrap­per func­tions to achieve the same results, but I find that using work­flows in this case makes for more read­able code. Another good alter­na­tive is to use a Maybe monad, which I won’t go into too much detail here as Scott Wlaschin has a great expla­na­tion for this already.

 

As always, the source code for both libraries are avail­able on github, and if you find any issues feel free to report them via the issues page.

 

* if you’re inter­ested in learn­ing more about com­pu­ta­tion expres­sions, I highly rec­om­mend Scott Wlaschin’s series on his F# for Fun and Profit blog, it’s by far the most com­pre­hen­sive and easy to under­stand set of arti­cles I have seen.

 

Links
Share