A Haskell FFI calling convention for Javascript

Haskell’s Foreign Function Interface (FFI) predefined calling conventions do not match well with Javascript’s object oriented features. In particular selecting a field of an object using dot notation (like o.f) and using an object as an array using brackets (like o[i]) do not have a natural counterpart in Haskell or the default calling conventions supported by the FFI interface. So, here are some examples of how Javascript is accessed in UHC via its jscript calling convention:

From within a browser the document representation can be accessed via the global variable document, the foreign entity "document" translates to a reference to this variable. The type of the document is defined as an opaque type, it can thus only manipulated via Javascript. Writing a string to the document is done by invoking the method write on a document. The foreign entity "%1.write()" specifies that from all arguments the first one is used as the receiver of the method write. The parenthesis () specify that a call has to be made, passing all arguments except those referred to explicitly by means of %<nr>, where <nr> >= 1 refers to argument <nr>. If an entity is omitted as in alert it defaults to "<functionname>()" where <functionname> is the name of the foreign function being defined.

Function documentWrite does not accept a String but a JSString instead, defined to be the platform dependent representation of Strings, converted to and from String with corresponding conversion functions.

stringToJSString forces its argument to be fully evaluated and then converts it to a Javascript String.

There is choice whether to put document in the IO monad or not, depending whether this global object itself will ever be assigned a new value or not. Not being a Javascript DOM wizard wrapping in IO seems to be the safest bet.

Given these functions a minimal Hello World web program thus is:

main = alert $ stringToJSString "Hi there!"

As this would pop up an alert box, an alternative Hi is the following program which writes to the document instead:

A NodeList is not an array, but behaves like an array: we can ask for its length and retrieve an element by index. It is not an array itself, so modelling it as such in Haskell would be incorrect. However, by allowing import entities to use Javascript array notation we circumvent this limitation and the Javascript array interface can still be used easily.

Finally, this minimal interface to DOM can be used to retrieve and print info about an element in an html document:

5 Responses to A Haskell FFI calling convention for Javascript

DOM programming would seem to be modelled by STM. JavaScript interpreters in browsers (and many outside them) are single-threaded; so there is never any danger of concurrent update of a structure during the “check” phase right before a transaction to the DOM is committed.

So, it boils down to putting everything in the IO monad, as all fields of an object (except the readonly ones) can then be modified by another thread, no way around it. Which is somewhat of a pity as it does not improve readability.