Khoo Yit Phang

Collecting my ideas and musings about programming

New release of Arrowlets: now with `pair` (***), `split` (&&&), `bind` and `join`

I’ve just released a new version of Arrowlets which finally implements all the basic arrow combinators. Where `then` (a nicer alias of `next`1) expresses sequential composition—i.e., connect the output of f into the input of g—the combinators `pair` (***) and `split` (&&&) express parallel composition—i.e., running f and g on the same input and outputting the combined result:

• `f.pair(g)` takes a `Pair(x, y)` as input, runs f on x and g on y respectively, and combines the outputs into a `Pair(fx, gy)`;
• `f.split(g)` takes any input x, runs both f and g on x, and combines the outputs into a `Pair(fx, gx)`.

In previous releases of Arrowlets, arrowlets can be run in parallel, but they are not easy to synchronize as they run independently of each other. Using `pair` and `split` makes it much easier to perform synchronization, since they will wait for their constituent arrowlets to complete before outputting the combined result.

Collecting outputs

Oftentimes I need to keep the results from an earlier arrowlet in addition to that from the most recent arrowlet in a sequence. Two new combinators—`bind` and `join`—are useful for this purpose: they are similar to `then`, but will combine the input and the output in a `Pair`:

• `f.bind(g)` takes the input x, runs f on x, runs g on the `Pair(x, fx)` and outputs its result;
• `f.join(g)` takes the input x, runs f on x, runs g on the output fx and combines the outputs into a `Pair(fx, gfx)`.

JavaScript `Function`, `Tuple` and `Arr`

If you haven’t yet noticed, all the new combinators above uses `Pair` objects, which is simply a tuple with two values (a tuple can be thought of as a collection of values). While arrows in Haskell can be naturally defined with pair tuples, it is a problem in JavaScript which has no notion of tuples! So, this release of Arrowlets introduces `Tuple` objects as well as `Pair` objects (which are instances of `Tuple` with additional methods `fst` and `snd`), with support for pattern-matching.

However, introducing tuples leads to compatibility issues with existing JavaScript functions which do not understand `Tuple` objects. Since one of my design goal for Arrowlets is to be as compatible as possible with existing JavaScript code, I spent a great while trying to bridge the mismatch between two different usage of functions:

• tuple-aware functions that take a single tuple argument (e.g., for defining arrow combinators);
• standard JavaScript functions which take any number of arguments (and can be called with more or less arguments than declared).

JavaScript doesn’t have Haskell’s sophisticated type system, so it is not possible to detect these two usage automatically. So, the solution I’ve come up with is to explicitly distinguish between these two usage of functions, and call them differently when the input is a tuple:

• tuple-aware functions are explicitly created as `Arr(function(tuple) { ... })`, and are called with the tuple as the only argument (somewhat resembles `arr` in Haskell);
• standard JavaScript functions are declared normally as `function(x, y, ...) { ... }`, but are called with a flattened representation of the tuple as the argument list. E.g., `(function() { return Tuple(1,2,Tuple(Tuple(3,100),4,5)); }).then(Math.max)` will output `100. `

So far, this seems to me like the most intuitive way to use standard JavaScript functions with Arrowlets. I might revisit this issue in the future: I wonder if there is a way to define combinators in terms of records (JavaScript objects) instead of tuples?

Next up…

At this point, I need a testing framework for Arrowlets, but from my cursory survey, it seems that most JavaScript-based unit-testing framework aren’t adequately equipped to handle the asynchronous nature of Arrowlets. It occurs to me that with support for exceptions, Arrowlets itself makes a nice basis for a unit-testing framework, so that’s my plan for the next release.

I hope you enjoy this latest release of Arrowlets, and please use the comments to let me know of any issues!

P.S. I can’t quite figure out why Firefox/Tracemonkey takes 6x as long as WebKit/Squirrelfish Extreme to complete my matrix multiplication example. Any ideas why?

1 Thanks to Andrew Davey for this suggestion.

Written by Khoo Yit Phang

November 3, 2008 at 10:54 pm

Posted in Arrowlets

2 Responses

1. Hi,

Is there any progress with Arrowlets?

I’m currently writing some “real-world” applications with Flapjax, and have came up with a pattern which is abstracted out using, guess what, arrows! (well, a specific arrow actually)

I have a pair (Dom, EventStream) and a few combinators (first, second, bimap) which I use to ease composition.

Well, I’m trying out a different approach now. But having a solid theoretical foundation would be great in any case.

Also, I would like to know when Arrowlets are more applicable than Flapjax. Can you elaborate?

Artyom Shalkhakov

July 31, 2009 at 8:07 am

2. Hi Artyom, glad to hear that you’ve found arrows useful There hasn’t been too much work on Arrowlets recently, but we have a new paper on our website that includes a comparison with Flapjax.
Basically, Arrowlets and Flapjax have complementary designs: Arrowlets is control-flow oriented whereas Flapjax is data-flow oriented. Arrowlets maps particularly well to state machines and I think it’s easier to adopt in existing JavaScript applications.

Khoo Yit Phang

August 2, 2009 at 8:01 pm