Khoo Yit Phang

Collecting my ideas and musings about programming

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

with 2 comments

I’ve just released a new version of Arrowlets which finally implements all the basic arrow combinators. Where then (a nicer alias of next1) 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(fxgfx).

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.

About these ads

Written by Khoo Yit Phang

November 3, 2008 at 10:54 pm

Posted in Arrowlets

2 Responses

Subscribe to comments with RSS.

  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


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: