jQuery is just a browser API

[Update] Thanks to Charlie in the comments for pointing me to jQuery’s $.fn.proxy method.

Developers have traditionally used JavaScript for relatively simple DOM manipulations and XHR, but as more functionality moves to the client, the techniques used by those developers have been slow to evolve. One consequence of this slow evolution is systems comprised entirely of jQuery and a series of nested event bindings. While jQuery is an extremely effective browser API, hiding the clumsy and often bug ridden out of the box equivelants, developers need effective solutions for organizing and reusing their code.

Nested Closures

Relegating code to event bindings breaks down in even very simple situations for a few important reasons. First the state that’s closed over is often hard to track and bindings can easily be shadowed.

(function( $ ) {
  function other() {
    // ...
  }

  function header() {
    //...
  }


  $(".bar").click(function() {
    var header = $( "header" );

    // ...
  });
})( jQuery );

Developers altering the click callback are required to know all the bindings in the current and parent scopes or face the possibility of attempting something unfortunate like using the invocation operator on a jQuery object. Second the inclusion of the state in each callback is implicit which means everything in the enclosing scope is carried with the callback. This is the beauty of the closure when used properly, but here it only adds complexity and possibly memory bloat. Third, and most importantly, the code tied up in the functions and callbacks is entirely unusable outside that context.

Objects Not Functions

As far as alternatives go, it is possible to write JavaScript in a functional style. Sadly JavaScript lacks many language features that make functional programming easy and elegant. Partial application, pattern matching, tail call optimization, and simple composition are all missing. It’s also a style of programming that is unfamiliar to the vast majority of front end developers. For now objects appear to be the best means of code reuse and organization where JavaScript is concerned.

With that in mind there are a number of options worth considering. Many JavaScript libraries provide a class system to emulate similar systems in other languages. MooTools is a prime example in that it’s Class constructor supports classical inheritance, mixins, and more. This approach has the obvious benefit of being relatively familiar to developers without a lot of JavaScript experience and if you prefer to work with the DOM via jQuery you can even discard the MooTools DOM API with the download builder.

Additionally a lot of client side software involves state management between JavaScript objects and some DOM representation. Libraries like Backbone and Sproutcore provide models in one form or another that can act as a class replacement. As Yehuda Katz pointed out in his presentation “Getting Truth Out of the DOM”, attempting to manage complex state between the the DOM and JavaScript is best left to an existing solution. Taken with the need to better organize an application these libraries can be invaluable.

Finally, you can use the (gasp) prototype system provided by JavaScript. The aversion to JavaScript’s object model appears to be an unfortunate side effect of the overall lack of experience with the language, but by creating a constructor and then defining methods on it’s prototype you can group, organize, and reuse common functionality quite easily1. Even when choosing another solution, neglecting to understand JavaScript at this level is an unfortunate misstep.

Operating under the assumption that jQuery will remain the primary means of interacting with the DOM for most developers it’s necessary to address binding context (ie this) as it becomes necessary when using object methods as arguments to higher order functions (eg event handlers).

jQuery and Function.prototype.bind

One conspicuous absence from jQuery is a helper for function context binding jQuery’s answer for context binding is the $.proxy method. That is, it provides a way to guarantee the value of this during the invocation of a given function. this becomes important very quickly in even simple attempts to reconcile DOM events with code organization through objects. Here we’ll build a library agnostic version.

function AlertArea( $domElement ){
  // bind to the instances onCloseClick
  $domElement.find( "div.close" ).click(this.onCloseClick);

  // if the alert area has text on creation show it
  if( $domElement.text() ) {
    $domElement.show();
  }

  // track the dom element for
  this.$domElement = $domElement;
}

AlertArea.prototype.onCloseClick = function() {
  // BOOM!!!
  this.$domElement.hide();
};

In this example when the constructor is invoked with some jQuery wrapped DOM object, if that object has text, it’s displayed. It also binds the prototype method onCloseClick to clicks on child elements matching the div.close selector. The problem here is that this in onCloseClick won’t be the AlertArea object when the click event is triggered but rather the DOM element on which the event was triggered (a feature of jQuery). To guarantee the this value upon invocation a binding function is required.

function bindContext(newThis, fn) {
  return function() {
    fn.apply(newThis, arguments);
  };
}

This function takes as arguments a context (newThis) and a function (fn). It then creates a new function that, when invoked, will use the apply method of the original function to invoke it with the new context. More commonly this is defined on the function prototype.

Function.prototype.bind = function(newThis) {
  var self = this;

  return function() {
    self.apply(newThis, arguments);
  };
};

With that in place the this value of the onCloseClick method can be guaranteed by altering the click binding

// bind to the instances onCloseClick

$domElement.find( "a.close" ).click(this.onCloseClick.bind(this));

The fact that jQuery lacks this core function is telling. It isn’t attempting to facilitate your code organization because that’s not what it’s for. I like to think that at least part of jQuery’s success is due to it’s focus on a very specific set of problems, but that leaves the developer to choose their preferred method of code organization. Sadly many developers fail to take that step though it can easily be accomplished with JavaScript’s prototype system.

Getting Comfortable With this

A simple library for managing textareas should serve to illustrate how the prototype system is an easy win over nested closures both early on and as application complexity grows. We’ll start with the more common approach:

$( "textarea" ).each(function(i, elem) {
  var $textArea = $(elem);

  function grow(){
    var scrollHeight = $textArea[ 0 ].scrollHeight,
        clientHeight = $textArea[ 0 ].clientHeight;

    if ( clientHeight < scrollHeight ) {
      $textArea.height(scrollHeight + 20);
    }
  }

  function limitWarn() {
    if( $textArea.val().length > 10 ) {
      $textArea.css( 'background-color', 'red' );
    }
  }

  $textArea.keyup(grow).keyup(limitWarn);
  $(window).load(grow).load(limitWarn);
});

For all textarea elements in the DOM the grow and limitWarn functions are bound to keyup for user input and $(window).load for text included in the markup. grow does a simple calculation to determine if the text exceeds the textarea’s rendered height and then increases it where necessary. limitWarn changes the background color of the textarea when the content length exceeds a given threshold. Already there are three references bleeding into grow and limitWarn (ie, i, elem, and limitWarn/grow). Now, the equivalent using the prototype system.

function TextArea( $textArea, limit ){
  var grow = this.grow.bind(this),
      limitWarn = this.limitWarn.bind(this);

  $textArea.keyup(grow).keyup(limitWarn);
  $(window).load(grow).load(limitWarn);

  this.$textArea = $textArea;
  this.limit = limit;
}

TextArea.prototype.grow = function() {
  var scrollHeight = this.$textArea[ 0 ].scrollHeight,
      clientHeight = this.$textArea[ 0 ].clientHeight;

  if ( clientHeight < scrollHeight ) {
    this.$textArea.height(scrollHeight + 20);
  }
};

TextArea.prototype.limitWarn = function() {
  if( this.$textArea.val().length > this.limit ) {
    this.$textArea.css( 'background-color', 'red' );
  }
};

$("textarea").each(function(i, elem) {
  new TextArea( $(elem), 10 );
});

The only additional overhead is the function context bindings2, typing TextArea and prototype, and the instantiation. The upshot is a purpose built constructor where the each closure served before and a very specific portal through which state contained in the object is accessed (this).

Now consider another developer working on the same project needs to manage textareas in a different context with a minor alteration. The closure based solution requires something of an overhaul, but the TextArea prototype can remain nearly untouched while it’s repurposed elsewhere.

function DialogWarnTextArea( $textArea, limit, $dialog ) {
  TextArea.apply(this, arguments);

  this.$dialog = $dialog;
}

DialogWarnTextArea.prototype = new TextArea();

DialogWarnTextArea.prototype.limitWarn = function() {
  if( this.$textArea.val().length > this.limit ) {
    this.$dialog.text("Too much text!").show();
  }
};

A few things to take note of. First, an application of the original TextArea constructor to this in the DialogWarnTextArea constructor makes sure the original attributes are set up properly (ie limit and $textArea). You can think of this as an explicit super.

TextArea.apply(this, arguments);

Second, assigning the prototype to a new instance of TextArea places the methods and attributes defined on it’s prototype in the chain above those defined (later) on the DialogWarnTextArea prototype. This is referred to by most JavaScript developer’s as “prototypal inheritance” for the way it emulates method/attribute lookup in languages with classical inheritance3.

DialogWarnTextArea.prototype = new TextArea();

Third, defining a limitWarn attribute on the DialogWarnTextArea prototype means that objects created with the DialogWarnTextArea will use that definition since it appears earlier in the prototype chain.

DialogWarnTextArea.prototype.limitWarn = function() {
  if( this.$textArea.val().length > this.limit ) {
    this.$dialog.text("Too much text!").show();
  }
};

Last, we need to handle the case where the TextArea constructor is invoked with the new operator to set a prototype (ie, without arguments) which constitutes our only alteration to the TextArea code.

function TextArea( $textArea, limit ){
  if( !arguments.length ) return;
  // ...
}

It should also be pointed out that there are a few items worth refactoring (3 arg and the limitWarn boolean operation) but the changes are at least palatable and mostly non-invasive. In stark contrast, achieving the same functionality without the prototype system requires moving the grow function into a parent scope, gathering the target from the event object passed to grow as an event handler, and creating another each loop over the second set of textareas.

function grow( event ){
  var $textArea = $(event.target),
      scrollHeight = $textArea[ 0 ].scrollHeight,
      clientHeight = $textArea[ 0 ].clientHeight;

  if ( clientHeight < scrollHeight ) {
    $textArea.height(scrollHeight + 20);
  }
}

$( "textarea.other" ).each(function( i, elem ) {
  var $textArea = $(elem);

  function limitWarn() {
    if( $textArea.val().length > 10 ) {
      $("#dialog").text("Too much text!").show();
    }
  }

  $textArea.keyup(grow).keyup(limitWarn);
  $(window).load(grow).load(limitWarn);
});

Also unfortunate is that grow has lost context for the reader, it relies entirely on the fact that the event.target will behave like a textarea. Ultimately this is really about getting any reusability at all with the added bonuses of sane state access and a limit on the enclosed bindings. Using closures alone to manage scoping concerns simply collapses where reuse is concerned.

Slow Progress

My fear, and the motivation for this post, is that developers are not turning quickly enough to libraries and language constructs, be they MV* frameworks or plain old prototypes, which are crucial to building more complex client side applications. For nearly any application that must be maintained, even those with a minimum of client side code, developer’s should look to move beyond the simple scoping semantics of the jQuery event callback and leverage the code organization and reuse features that JavaScript and its libraries have to offer.

  1. One of the best examples I’ve found is Google’s closure library. Whatever you may think of the library itself, the code is really nice to look through.
  2. Underscore.js provides a nice facility for binding all methods on an object to that object context (_.bindAll), though it requires explicit inclusion of methods defined on the prototype
  3. You can learn more about prototypal inheritance from Douglas Crockford and Yehuda Katz

You got your type class in my jQuery: Applicative Functors

Previously we saw how jQuery’s $() can behave like Haskell’s Functor typeclass, when it wraps raw DOM objects and how provides its own version of fmap ($.map) for lifting functions into that wrapper to work with those DOM objects. In this post I’ll explain Haskell’s Applicative typeclass, how it’s slightly different from the Functor, and demonstrate how defining functions on $.fn behaves in a similar fashion to the Applicative function pure.

The article assumes you’ve read the previous post and that you have some basic understanding of what it means to define a function on jQuery’s $.fn object (docs for reference).

Applicative Functors

To start, the Applicative typeclass in Haskell requires that instances also be Functors. Practically speaking this means that any Applicative type actually builds on top of it’s Functor by requiring an extra function and an operator, pure and <*>. This is important because it tells us that we’re still working with contexts, the stuff in them, and getting operations inside to work on the stuff in them.

class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b

Continuing with our practice of renaming types for clarity lets alter the definition a bit

pure :: a -> applicative(a)
(<*>) :: applicative(a -> b) -> applicative(a) -> applicative(b)

and being that any Applicative is also a Functor

pure :: a -> functor(a)
(<*>) :: functor(a -> b) -> functor(a) -> functor(b)

pure is relatively simple. From the type a -> applicative(a) you can see that its a function that takes some type a, wraps/lifts it into the Applicative, and hands that Applicative instance back. In the previous article on the Functor we didn’t discuss how the data a or b got wrapped inside a Functor in Haskell. We took for granted the fact that the value would be wrapped because it was easy to illustrate in Javascript. This means that instances of a Functor might need to expose some way to do the wrapping or users have to create a function for that purpose outside the requirements of the Functor type class. In the case of Applicatives pure is a function that does the wrapping1.

Next, the infix operator <*>. Its type signature looks a little bit like fmaps:

fmap :: (a -> b) -> f a -> f b
(<*>) :: f (a -> b) -> f a -> f b

The only difference is that the first argument f (a -> b) is a function wrapped inside the Applicative context, where fmap takes a raw function and does the wrapping for you. You can probably imagine how pure is used with <*>, it wraps functions and data in the Applicative and then <*> is used to apply those wrapped functions to the wrapped data.

Javascript’s this

Before we get started in demonstrating the jQuery analogue to the Applicative Haskell type class, we need to talk about this.

Because we’re drawing analogies with pure functional programming, where arguments are always defined explicitly, and our jQuery analog will reference it as a replacement for arguments in the type class type signatures, we’re going to think of this as an implicit parameter. This isn’t too much of a stretch given that for any function/method invoked via Function.prototype.call and Function.prototype.apply, it’s actually explicit.

A simple example

var foo = function(first, second){
  console.log(first);
  console.log(second);
  console.log(this);
};

foo.call("wow", 1, 2);
// -> 1
// -> 2
// -> [object]

foo.apply("wow", [1, 2]);
// -> 1
// -> 2
// -> [object]

The only issue with thinking this way is that this is treated as an object and not simply passed through as a parameter would be, though this doesn’t affect our discussion. The important part to get for the rest of the article is that, just because it isn’t declared as an argument, doesn’t mean that this can’t behave like one during invocation.

jQuery

To define our jQuery analog for the Applicative we have to implement the two functions from the Haskell type class. First pure and then the operator <*>. Luckily, once we sort out pure, the extra operator mostly sorts itself out.

Since pure wraps things in the Applicative, functions or data, and we already have a way to wrap the data, HTMLElements, with the jQuery $() function, all we really need to do is figure out how to get functions into the Applicative so they can operate on wrapped HTMLElement data. Your initial reaction might be to use the same wrapping function for HTMLElements and functions but in jQuery $(function(){}) is a callback for DOM ready so we’ll need to find something else. For reference the type signature of the function we’re looking for in Haskell would be

foo :: (a -> b) -> f (a -> b)

or in terms of the Applicative

foo :: (a -> b) -> applicative(a -> b)

The first argument is a function from a to b and the return type is a function from a to b, presumably the same one, wrapped in the Applicative. Obviously pure does just that since the type of a in its type signature pure :: a -> applicative(a) can be a function (a -> b).

Lets look at how functions defined on $.fn behave to see if that might suggest anything:

// definition
$.fn.clearIds = function(){
  $.map(this, function(e){
    e.id = "";
    return e;
  });

  return this;
};

// invocation
$( "div" ).clearIds();

Looking at the clearIds invocation it certainly appears that its been defined/lifted/wrapped to work with the $() wrapper/Applicative, but you’ll notice that this inside the function body is a set of $() wrapped HTMLElements that must be mapped over and not the HTMLElements themselves. Assuming this as an implicit first parameter the type of the clearIds definition when translated back to Haskell would be something like:

clearIds :: $(a) -> $(b)

or in terms of the Applicative

clearIds :: applicative(a) -> applicative(b)

This should make perfect sense for anyone thats written a jQuery plugin meant to chain with other plugins or jQuery builtins. It takes a $() wrapped set of elements and returns the same so the next plugin method can operate on them.

While it does sort of resemble the function wrapped into the Applicative, applicative(a -> b), that we’re looking, it is different. If you spotted the map call inside the clearIds definition you’ll have noticed that the function references the id attribute directly from each HTMLElement. That function

function(e){
  e.id = "";
  return e;
}

has the type signature that we want to emulate, namely (a -> b), or more concretely (HTMLElement -> HTMLElement). If we can abstract the map call and the return of the mutated this we’ll end up with a function that takes a function (a -> b) and results in a function that can work with the Applicative. Lets do that now:

$.pure = function(fromAToB){
  return function(applicative){
    return $.map(applicative, fromAToB);
  };
};

That’s more like it. $.pure takes a simple function fromAtoB, meant to work with the raw HTMLElements wrapped inside the Applicative $(). The type signature is a bit off (a -> b) -> (f a -> f b), but lets take a look at the corresponding implementation of <*>, here referred to as ap to see if we’ve captured the spirit of the applicative.

$.fn.ap = function(applicativeFn){
  return applicativeFn(this);
};

ap will take the result of a call to $.pure, and uses it to alter the implicit parameter this which is $() wrapped HTMLElements. Including the this parameter the type signature is

$.fn.ap :: (f a -> f b) -> f a -> f b

which is is pretty close to what we're looking for

(<*>) :: f (a -> b) -> f a -> f b

when you consider that the descrepancy in the first argument is dictated by how functions defined on $.fn have to operate.

The end result will look something like this for our clearIds example above:

var clearIds = $.pure(function(e){
  e.id = "";
  return e;
});

$( "div" ).ap(clearIds);

Here we've got all the necessary peices to fulfill the type requirements for both pure and <*>. $.pure does the wrapping for functions that operate on the elements of our jQuery Applicative, $() does the wrapping of the elements themselves (eg $( "div" )), and the ap method does the application of the lifted function to the HTMLElements. Thus the ap method defined on the $.fn object is our <*> opperator from Haskell so long as the method defined on the jQuery object has been created using $.pure!

A New JQuery Plugin Helper

We've fulfilled the requirements of the Applicative type class and derived a useful helper as a consquence, but asking the user to manage the results of the $.pure is clumsy. A simplification might take the form

$.pure = function(fnName, fromAToB){
  $.fn[fnName] = function(){
    return $.map(this, fromAToB);
  };
};

with a definition and invocation for our clearIds example

$.pure('clearIds', function(e){
  e.id = "";
  return e;
});

$( "div" ).clearIds();

Here, the pattern of mapping a function of (a -> b) into the jQuery context is done as before by $.pure, but the storage is done on the jQuery $.fn object not by the user. As a consequence, we can simply invoke a function of fnName directly on the jQuery object as a substitute for ap, <*>. It deviates from the type signatures of the Applicative function definitions from Haskell but it captures their spirit while making the pattern much more user friendly.

Notes

  1. Applicatives and Functors can expose their data constructors for the purpose of wrapping data as well. Its up to the author of the data type to determine whether they want to expose that functionality or force the user to use pure. The difference between exposed and private data constructors becomes important when discussing IO and other monads in Haskell.

You got your type class in my jQuery: Functors

I have previously described practical applications of common functional programming concepts in earlier posts: Rack’s Middleware and Vagrant’s Middleware. Next in this series I’ll cover how jQuery’s design leverages abstractions similar to Haskell’s better-known type classes: Functor, Applicative, and Monad. It draws heavily from Brent Yorgey’s Typeclassopedia from [PDF] The Monad Reader 13 (which was essential for my own understanding), and supplements it with examples from Javascript and jQuery.

The only pre-requisite is a functioning knowledge of Javascript, jQuery.map and in later posts jQuery.fn.

To start: Functors.

Functors

Haskell’s Functor typeclass can be thought of as a way to define context. More specifically, it defines a type to behave as a context or wrapper for data into which operations can be “lifted” to work with the unwrapped/uncontextualized data.

Lets take a close look at the definition, and don’t worry, the salient parts will be explained:

class Functor f where
fmap :: (a -> b) -> f a -> f b

We can safely ignore the first line for the purposes of our discussion.

fmap :: (a -> b) -> f a -> f b

fmap is a function, but this is not the implementation, only a blueprint for what it should do. This code tells the developer that any actual implementation of fmap requires two arguments and must return a single value.

The first argument (a -> b) is a function that accepts an a (something of type a), and returns a b (something of type b). a and b could be any types at all (Int, String, Boolean, etc). The fact that each is represented by a different letter means that they could be the same type or a different type.

The second argument, f a, is special and forms the basis for our discussion about Functors in jQuery. Remember that a could be any type that we want. That’s simple enough, but what is the f that precedes the a in this case? The fact that it’s written as f can at first be a little confusing, because it looks like it might be a function. It’s not. Lets change it for clarity.

fmap :: (a -> b) -> functor a -> functor b

That at least makes it clear that the f is meant to describe some relationship between a and a functor. Lets take it a bit further:

fmap :: (a -> b) -> functor(a) -> functor(b)

This seems to get at the central purpose of the functor: to wrap other data.

Finally, the functor(b) on the far right is the return value of fmap, which is also data of type b wrapped up in a functor.

Taken all together you can see that the first argument, a function that takes one argument of type a and returns something of type b, will most likely be operating on the a that’s inside the second argument functor(a). Getting that a out of the functor(a) and handing it off to the function (a -> b) is what fmap does.

Here’s what the equivalent might look like if we built our own Functor, a function to interact with the values inside it, and invoked fmap with both.

// a function that works with a and returns b
var fromAtoB = function(a){
  var b = a.alter();
  return b;
};

// fmap uses fromAtoB to alter the value of a in the functor instance
var functorWrappingB = fmap(fromAtoB, new Functor(a));

// we can see that functorWrappingB is a Functor
console.log(functorWrappingB instanceof Functor); //true

The sample fromAtoB function takes an a, performs some operation on it, and returns the resulting b, which again could be the same type or different. Again, this is only an example, fromAtoB and consequently any function we use in it’s place could do whatever it wants with the a it receives so long as it returns the altered value. With fmap‘s first argument, the function fromAtoB, in place all that’s left is to provide a Functor object from which the a will be extracted and handed off to fromAtoB. Inside fmap, the return value of fromAtoB will be put back inside a new Functor object and returned.

Finally, lets looks at what an fmap definition might look like in Javascript so that the way it operates on the Functor will be entirely clear.

var fmap = function(fromAToB, functorWithA){
  var a, b;

  // get the value inside the functor object
  a = functorWithA.getInternalValue();

  // send that value into our function
  b = fromAToB(a);

  // put the value back into a functor object and return
  return new Functor(b);
};

As we’ve explained, it pulls the a out of the functorWithA, gives that to fromAtoB and then puts the result b back into a new Functor. The shape or context is always going to be a Functor regardless of whats inside.

jQuery

Interestingly, one of the jQuery’s most important functions , jQuery / $ itself, is based on a pattern similar to a Functor. Remember that instead of altering native HTMLElement objects to add methods and helpers (like Prototype does), jQuery wraps them and provides access to those objects in a safe, browser agnostic fashion.

$( "div" )

That’s just a bunch of HTMLDivElements wrapped up in the jQuery object. So what if you want to work with the underlying HTMLDivElements? As a developer familiar with jQuery you might do something like:

$( "div" ).map( function( i, elem ){
  // do something with the HTMLElement
  return elem;
});

In short we’ve taken a function and “lifted” it into the jQuery object context to get at the underlying HTMLDivElements. After performing the alteration we can return the element back to map and it will handle putting the element into its jQuery object wrapper, just like fmap.

If thats not quite clear enough, you can achieve the same result with the following:

$.map($("div"), function( elem ) {
  // do something with the element
  return elem;
});

Really the only difference between $.map and fmap is that jQuery “Functor” is the first argument to $.map and the function that will operate on the values inside it is the second argument. The argument order is just swapped.

Sample Usage

One of the primary uses for a Functor context/wrapper is control. While jQuery provides direct access to the underlying data (array index notation) in addition to the $.fn.map function, this pattern is easy to leverage when you want to control or manipulate access to data.

For example, if you wanted to prevent manipulation of an element while visible, e.g. a modal dialog, you might define a HiddenFunctor. fmap in this case would only execute the function on the dialog element when a.is(“:visible”) is false.

var HiddenFunctor = function(a){
  var a = a, self = this;

  self.fmap = function(fromAtoB){
    var b;

    // if a is visible skip the action
    b = a.is(":visible") ? a : fromAtoB(a);

    // re-wrap
    return new self.constructor(b);
  };

  self.hide = function(){
    a.hide();
    return self;
  };
};

The constructor prevents access to the wrapped element a outside the instance of the HiddenFunctor by using a constructor local variable and fmap as a closure. When fmap is invoked it checks if the element is visible and if it is, it does not invoke the passed/lifted function. You’ll also see that hide has been included because a function mapped into the functor to hide the element would not execute in the case where it had already been shown.

var functor = new HiddenFunctor( $("#dialog") ),

    show = function( $dialog ){
      return $dialog.show();
    }, 

    destroy = function( $dialog ){
      return $dialog.remove();
    };

// visible dialog cannot be destroyed
functor
  .fmap(show)
  .fmap(destroy)
  .hide()
  .fmap(destroy);

Here a new HiddenFunctor object is created with a reference to the #dialog. The first fmap with destroy doesn’t alter the dialog because it’s in the visible state, but after hiding it the second destroy removes the element from the page.

By using the Functor pattern to control alteration of the wrapped data based on visibility, we’ve abstracted away from the actions taking place on the underlying object and what the object might actually be while focusing on the task of making sure the user isn’t presented with broken content.

Haskell

With any luck the concept of getting your functions into the jQuery object or HiddenFunctor contexts, should look strikingly similar to the more general Functor from Haskell. In jQuery’s case, the jQuery object is our context, our Functor like object, and the map function is the fmap we use to get into that context to alter the values inside ( HTMLElements).

We can now go back and substitute some fictional types in the fmap type signature to show what fmap would look like if we were building jQuery in Haskell. Assuming the substitution of $ for jQuery we can even plug this back into our fmap type signature:

fmap :: (HTMLElement -> HTMLElement) -> $(HTMLElement) -> $(HTMLElement)

Again, that’s not a valid type signature, but the important part is that you see, jQuery or $ is wrapping something, in this case an HTMLElement, and fmap lets you operate on the thing being wrapped in an identical fashion to $.map.

And the valid version:

class JQFunctor JQuery where
fmap :: (HTMLElement -> HTMLElement) -> JQuery HTMLElement -> JQuery HTMLElement

Further Reading

[update] Its important to note, as some folks have already, that the Functor laws form an important part of their structure preserving properties. For a bit more information on them and why they’re important you can view the Learn You a Haskell section on the topic, or for more detail you can check out the wikibook entry on Functors and Hask objects.

In the next post I’ll show how extending jQuery’s $.fn object results in a behavior similar to the pure function described in McBride and Paterson’s Applicative Programming with Effects. From that we’ll derive a simple abstraction to make creating chainable jQuery plugins faster and easier to reason about.

If this post has piqued your interest in Haskell, or you want to learn about how lists in Haskell behave like Functors (interesting given that the result of $() behaves like a list as well) please take the time to look through some of these links.

  1. Learn You a Haskell: Functors
  2. [PDF] Monad Reader 13: Typeclassopedia
  3. Haskell Wiki: Applicative Functors

Special thanks to both Tim Goh (@keyist) and Mitchell Hashimoto (@mitchellh) for their feedback on the article.

Snap setup from scratch the Vagrant way

A large group of web developers, otherwise ambivalent to Haskell, have recently found reason to learn the language thanks in part to the Snap web framework. Its really no surprise given Haskell’s brilliance as an all purpose programming language and the effort the Snap team has put into providing great documentation. For those interested in exploring what it can do, the quickstart guide will get you up and running with snap in a few quick commands:

$ cabal update
$ cabal install snap
$ mkdir project
$ cd project
$ snap init

This, of course, will only work if you’ve already installed the Haskell Platform. Depending on your operating system and experience level this can be tedious if not challenging. With that in mind and my preference for using virtual machines when building web servers I’ve created a few Chef cookbooks for use with Vagrant that will hopefully make setting up and using Snap painless.

Setting up Vagrant

If you aren’t already familiar with Vagrant, it’s a virtual machine management tool for developers. Used in conjunction with Chef or Puppet provisioning tools, you can go from zero to a fully functioning, complex (reads multiple vm/server configuration) web application in one command. Among other things it helps to manage and standardize application dependencies, such as the Haskell Platform, by sequestering them inside a virtual machine where they can’t collide on the host. If your skeptical about the time investment involved here, I promise, once you try it you’ll never want to go back.

You can find detailed directions on installing Vagrant and its dependencies in the getting started documentation. Aside: take note of all the awesome documentation being thrown around here!

Getting the project skeleton

First up you’ll need to grab the the skeleton, which contains everything necessary for creating the vm. You can do this by cloning the git repository or by downloading a tar from github:

$ git clone git://github.com/johnbender/snap-skeleton.git

or

$ wget http://github.com/johnbender/snap-skeleton/tarball/master

After cloning/untaring you can rename the project directory, in which case you’ll need to replace snap-skeleton in the following commands with whatever you choose.

$ cd snap-skeleton
$ vagrant up

Following the the up command you’ll have to wait about 10 to 20 minutes depending on your internet connection for the platform to download and compile inside the vm. Once that’s complete your snap skeleton directory will now be lifted into the virtual machine as an nfs shared folder so that you can start working on your Snap application. Its here that we can rejoin the Snap getting started guide with two differences. The `cabal update` has been performed for us during the vm creation and when we want to run snap or cabal commands we’ll need to get inside the vm with `vagrant ssh` ( its important to note that you do NOT have to edit your haskell source in the vm as its in a shared directory with the host ).

$ vagrant ssh
vagrant@vagrantup:~$ cd /vagrant
vagrant@vagrantup:~$ snap init
vagrant@vagrantup:~$ cabal install
vagrant@vagrantup:~$ vagrant -p 8000
Initializing Heist/Impl... done.
Initializing Timer/Timer... done.
Listening on http://0.0.0.0:8000/

You’ll also notice that application built from the initial snap source is named after its parent directory, which in the vm is /vagrant, the mount point for the project directory on your host machine. Changes made in this directory from the host side will obviously be available inside the vm and vice versa. You can now view the “it works” page at http://33.33.33.10:8000.

Vagrant workflow

Now that you’ve got a nice new virtual machine and everything necessary to dive into a new Snap application you’ll need to know a few simple vagrant commands to save you some time. First and foremost all Vagrant commands must be run from within the project directory where the Vagrantfile resides. With that in mind, you’ve already seen the `up` command but if you want to get rid of your vm, a quick

$ vagrant destroy

will clean up for you. Keep in mind though that this means you’ll have to start from scratch again when you want to play around with snap. Next, you can suspend and resume your vms with:

$ vagrant suspend
$ vagrant resume

Also of note are the provision and reload commands

$ vagrant provision
$ vagrant reload

If you decide you want to alter the cookbooks and recipes provided with the skeleton you can use the provision command to run chef solo for you. Alternately if you want to bounce the vm and run the cookbooks again you can use reload. With those commands in hand, lets make a small alteration to the files created by Snap’s init and see how this all fits together. Open up Site.hs in your favorite text editor. It should be at /host/path/to/snap-skeleton/src/Site.hs and find the following snippet at the bottom:

echo :: Application ()
echo = do
    message <- decodedParam "stuff"
    heistLocal (bindString "message" (T.decodeUtf8 message)) $ render "echo"
  where
    decodedParam p = fromMaybe "" <$> getParam p

If you’re not yet very familiar with Snap the echo handler takes the `stuff` get parameter and echo’s it back to you. Lets change that so it ignores the get parameters:

echo :: Application ()
echo = heistLocal (bindString "message" "Vagrant + Snap => amazing") $ render "echo"

Alright, having edited the echo handler the application needs a recompile. First open up terminal at the snap-skeleton directory root then hop into the vm to compile and start the app:

$ vagrant ssh
vagrant@vagrantup:~$ cd /vagrant
vagrant@vagrantup:~$ cabal install
vagrant@vagrantup:~$ vagrant -p 8000
Initializing Heist/Impl... done.
Initializing Timer/Timer... done.
Listening on http://0.0.0.0:8000/

To see the alteration hit http://33.33.33.10/echo/foo. Generally you’ll want at least one terminal logged into the vm while you’re working. When you’re done playing around just drop out of the vm and suspend it:

vagrant@vagrantup:~$ exit
$ vagrant suspend

The next time you want to start hacking just get to the snap-skeleton directory and fire up the vm with a `resume`.

Altering Your VM

The Vagrantfile thats included in the root of the snap-skeleton ( /path/to/snap-skeleton/Vagrantfile ) provides a couple of important configuration options to take note of and a quick overview of its structure will be useful.

Vagrant::Config.run do |config|
  config.vm.box = "base"
  config.vm.network("33.33.33.10")
  config.vm.customize do |vm|
    vm.name = "Snap"
    vm.memory_size = 768
  end

  config.vm.provision :chef_solo do |chef|
    chef.cookbooks_path = "cookbooks"
    chef.add_recipe "project"
    chef.json.merge!({ :ghc_version => '6.12.3',
                       :haskell_platform_version => '2010.2.0.0'})
  end
end

First, if you named the base box that you downloaded something other than base ( “lucid32″ for example ) you can configure that by changing the value assigned to config.vm.box

config.vm.box = "base"

The ip thats defined is for the host network and the customization block allows you to change the attributes of the vm. Of particular note, if you want to change the name to better represent your project you can do that here.

config.vm.network("33.33.33.10")

config.vm.customize do |vm|
  vm.name = "Snap"
  vm.memory_size = 768
end

The last and most important configuration is for the provisioning tool, Chef.

config.vm.provision :chef_solo do |chef|
  chef.cookbooks_path = "cookbooks"
  chef.add_recipe "project"
  chef.json.merge!({ :ghc_version => '6.12.3',
                     :haskell_platform_version => '2010.2.0.0'})
end

The provisioner used here is Chef Solo which can, for more advanced users, be replaced with Chef Server or Puppet (see documentation). The first setting is the directory where the Chef cookbooks, that will be used to install and set up the vm, reside. The second is the name of the project recipe, which you are welcome to change as you get more comfortable with Chef.

chef.add_recipe "project"

The default recipe in the projects cookbook handles the inclusion of the rest of the coobooks ( cabal, haskell-platform, and apt). If you change the value here, you must change the directory accordingly in cookbooks:

$ ls cookbooks
apt  cabal  haskell-platform  project  README.md

Last but not least is the configuration passed to the Chef recipes. In this case I’ve defined the necessary versions for the current release of the haskell platform. In the future should these fall out of date they’ll be easy to change!

chef.json.merge!({ :ghc_version => '6.12.3',
                   :haskell_platform_version => '2010.2.0.0'})

Contributing to jQuery Mobile

UPDATE: I’ve updated the vagrant branch used below to support the newest version of Vagrant.

This is more substantial version of the lightning talk I gave at LA RubyConf last Saturday. If you’re a Vagrant user already, this will be familiar. If not, don’t worry, you’re about to get a quick introduction to its power as a tool for web development. If you have any questions feel free to comment or find me on twitter @johnbender.

Vagrant

jQuery Mobile is set up to use php for serving the docs and tests, both of which you will need in order to start hacking on the library. Instead of installing apache and mod_php on your workstation though, we’re going to build a vm using Vagrant that will serve it up.

First you’ll need to install VirtualBox and Vagrant which is covered in glorious detail by Mitchell’s documentation. If you’re questioning the time investment at this point I can promise you that its worth it. Vagrant will change the way you look at web development.

Clone and build

The next step is to fork and clone the jQuery Mobile repo

$ git clone git@github.com:yourgithandle/jquery-mobile.git
$ cd jquery-mobile

add my fork as a remote

$ git remote add geewilikers https://github.com/johnbender/jquery-mobile.git

track the branch with the Vagrant configuration

$ git fetch geewilikers
$ git branch --track vagrant geewilikers/vagrant
$ git checkout vagrant

make sure to add a base box from which to build our JQM virtual machine

$ vagrant box add base http://files.vagrantup.com/lucid32.box

and then fire that sucker up!

$ vagrant up

About 2 to 5 minutes later, depending on your connection speed, you should be able to hit the docs site served by your brand new vm. You can also view some tests.

Making changes

So now that the site is running how do you make changes? What do you do with this new branch? What does the workflow look like?

Its actually quite simple. Vagrant lifts the project directory into the virtual machine as a “shared folder” ( it actually mounts the folder with NFS because VirtualBox’s shared folders have extremely poor performance for complex file structures ). This means you can edit any files you like locally and the changes will be represented immediately in the vm. Just make sure that you checkout master first and use the vagrant branch any time you want to run a vagrant command.

For example, if you wanted to fix a typo in the docs and had just finished building the vm:

$ git branch
  master
* vagrant
$ git checkout master
... hack hack ...
$ git add .
$ git commit -m "changed the docs to be more awesome"

There’s no need to stay on the vagrant branch, its only necessary when you want to interact with vagrant. For example if you wanted to suspend the vm after finishing some work:

$ git checkout vagrant
$ vagrant suspend

When you want to start working again, just resume the suspended vm:

$ vagrant resume
$ git checkout master

And that pretty much covers the workflow. If you ever want to go rooting around in the vm itself, which in this case I find to be a rare occurrence, you can simply ssh in:

$ vagrant ssh

In the worst case where your vm just doesn’t seem to be working at all, just destroy it and rebuild it from scratch.

$ vagrant destroy
$ vagrant up

Pull requests

Now that its dead easy to make changes to JQM and you’re ready to dive in and help out, where’s the best place to start?

As of this writing the team is focusing on bug fixes and testing. Feature requests are being moved to a backlog for post beta/1.0 consideration as we focus on platform support and stability. That means if you want to contribute your best bet is to find an unclaimed issue ( ie one that isn’t tagged with a person’s name ), in the issues list on github and try your hand at a fix.

Once you’re happy with your solution submit a pull request and … wait. We’re doing our best to get to all the pull requests but we get a fair amount and you might have to wait a couple days to get a response while we sort through them.

To speed the process along there are a couple important things you can do:

1. Rebase!

If/When your pull request branch falls behind master don’t merge – rebase! By rebasing and resolving the conflicts you make the application of your commits to the existing master much easier for the reviewer.

First thing you’ll want to do is add the original git repo

$ git remote add jqm git://github.com/jquery/jquery-mobile.git

Then you can fetch the latest from the original jqm and rebase your changes on top of it

$ git fetch jqm
$ git branch
* master
  vagrant
$ git rebase jqm/master
... resolve conflicts ...

2. Separate white space/refactor commits

If you want to add in a quick refactor, like renaming a variable, or cleaning up some white space keep it in a seperate commit from the bug fix/feature. That way the reviewer doesn’t have to fight to separate the important changes from the rest.

3. Test

This really cannot be over emphasized. If you fix a bug please add a test for it. In this way we can guarantee that there aren’t any regressions in the future as the project makes changes and improvements. Just take a gander at the other tests to see what they should look like and dive right in. Even better, if you want to learn the library, just start writing tests for whats already there, you’ll be making a huge contribution to the stability of the code base.

Contributing to other projects

The most important part of all, which I didn’t get enough time to talk about at the conference, is that you don’t have to be a rocket scientist or hacker extraordinaire to contribute in a big way to an open source project you’re interested in. How do I know this, you may ask? Because I’m neither one of those things.

Sadly, I spent a lot of time on the outside looking in, thinking “I’d just be making trouble” or “I doubt I’d have any meaningful impact even if they did accept my submission”. If you tend to think on the same level, stop. Go fix a bug. Go write a test. Don’t let the fear of someone rejecting your submission stop you from trying in the first place.

Even if it doesn’t get accpeted, take the feedback to heart, get better, and try again. Good projects will have a polite and helpful response for you if they don’t think your fix is quite ready to be merged in. As someone who reviews pull requests I know that the most important asset the project has is its contributors and users. I see it as my most important job to make sure they know we appreciate all their hard work. ( credit to Yehuda Katz’s talk, and many discussions with Mitchell Hashimoto for those ideals).

Dive right in

Hopefully if you were on the fence about contributing to JQM or any other oss project this was the nudge you needed to give it a try. Open source is dead if people don’t jump in to contribute and make it better, so I hope to see your pull request in our queue sometime soon!

Haskell and Vagrant’s Middleware

As a follow up to my last post on middleware and monads I’ll be going over how the Warden class, as implemented inside Vagrant, uses concepts derived from some of the basic monad combinators to achieve a rescuable middleware stack. As before, this article assumes you have some knowledge of the Haskell language and middleware as defined in the Rack specification/Pep 333. Also, if you’ve never heard of Vagrant you can check out the documentation and some press.

Quick Recap

For a full treatment of the similarities between function composition and Rack middleware please see the previous article.

Function composition and the method call chain created when defining a middleware stack are strikingly similar. Each middleware is called from the previous with the environment object as the only argument. Borrowing from previous examples

app = Rack::Builder.new do
  use Rack::Upcase
  use Rack::Reverse

  run lambda { |env| [200, { 'Content-Type' => 'text/html' }, 'Hello World'] }
end

Which, once its made its way down the call “request” chain, takes the psuedo-code-form:

Rack::Reverse#call <- Rack::Upcase#call <- Proc#call

So, aside from the exposure to external state, and being informed about the subsequent middleware during the initialization it actually looks very much like function composition in haskell

reverse . upcase . \env -> (200, [("Content-Type", "text/html")], "Hello World!")

It boils down to function chaining with a common argument, namely env. However, if a guarantee on error handling is important, PEP 333 doesn’t have much to offer. In contrast, taking function composition and making use of a different combinator in place of the (.) composition operator provides an opportunity for error handling abstraction. From the previous article

reverse <=< upcase <=< head <=< \env -> Right (200, [("Content-Type", "text/html")], "")

By lifting the functions into the Either monad and using the monadic composition operator <=<, error condition handling is abstracted outside of the functions operating on the env. The Warden class inside Vagrant was implemented to provide similar functionality by inserting itself into the Vagrant middleware call stack.

Warden

Vagrant, being a command line application unlike Rack, requires different things of its middleware. Particularly when it comes to error handling. For example, when running `vagrant up` it duplicates a base virtual machine. If for some reason there’s an issue during this process its best not to leave 500mb+ virtual disk files lying around.

Prior to the introduction of the middleware Warden, each middleware would call its own cleanup method and either return back up the call chain when a problem was encountered or mark the env with an error. This meant that each middleware had to contain its own logic for error checking the environment and for dealing with those errors appropriately.

class MiddlewareExample
  def initialize(app, env)
    @next_app = app
  end

  def call(env)
    @next_app.call(env)

    # was the environment tagged with an error by
    # middleware farther down the stack?
    if env.error?
      fixit
    end
  end

  def fixit
    #cleanup
  end
end

To improve on this situation the Warden class was introduced to act, in a similar fashion to the <=< operator, as a middle man inserted by the Builder class. The only requirement (one met before the Warden was created thanks to Mitchell’s diligence with well factored code) being that each middleware wishing to perform some cleanup action must implement a separate cleanup method, recover, which the Warden would call when necessary.

class MiddlewareExample
  def initialize(app, env)
    @next_app = app
  end

  def call(env)
    @next_app.call(env)
  end

  def recover
    #cleanup
  end
end

If the example was a pre-Warden Vagrant middleware, the @next_app instance variable would have been an instance of the next middleware. With Warden its actually an instance of the Warden class. To use the illustration from earlier:

Rack::Reverse#call <- Rack::Upcase#call <- Proc#call

Which becomes:

Warden#call <- Rack::Reverse#call <- Warden#call <- Rack::Upcase#call <- Warden#call <- Proc#call

Swapping the monadic composition operator (<=<) into the pseudo-code call chain for the Warden instance makes the inspiration a bit clearer.

<=< Rack::Reverse#call <=< Rack::Upcase#call <=< Proc#call

Implementation

To create the modified middleware stack the Builder class first sends all the middleware classes, lambdas, and procs into the Warden initializer to be finalized (instantiated or wrapped in the case of a lambda/proc):

def initialize(actions, env)
  @stack = []
  @actions = actions.map { |m| finalize_action(m, env) }
end

Next the Builder class calls the Warden instance just as it would normally call the first middleware and the Warden instance tracks which middleware have been run:

def call(env)
  return if @actions.empty?

  begin
    # Call the next middleware in the sequence, appending to the stack
    # of "recoverable" middlewares in case something goes wrong!
    raise Errors::VagrantInterrupt.new if env.interrupted?
    @stack.unshift(@actions.shift).first.call(env)
    raise Errors::VagrantInterrupt.new if env.interrupted?
  rescue

    # Something went horribly wrong. Start the rescue chain then
    # reraise the exception to properly kick us out of limbo here.
    begin_rescue(env)
    raise
  end
end

Lets break this down a little so its clear how this method does the middleware management in the midst of the interupt handling code.

  @stack.unshift(@actions.shift).first.call(env)

@actions.shift pulls the first middleware off the front of the uncalled array and @stack.unshift pushes it onto the front of the rescuable middleware array. Calling first on the result of unshift, the new mutated list, returns the current action which is subsequently called.

  raise Errors::VagrantInterrupt.new if env.interrupted?

The interrupt checks happen on both sides of the middleware management code to handle interrupts before and after calls to the middleware. Any other exceptions raised during the course of execution by the middleware are obviously caught in the same manner and when they are the begin_rescue method is invoked. Here the Warden will begin walking back up the stack of already executed middleware, starting with the most recent, calling the recover method on those that define it:

def begin_rescue(env)
  @stack.each do |act|
    act.recover(env) if act.respond_to?(:recover)
  end
end

While the Warden has added some complexity to the traditional middleware stack the call method on the Warden instance provides a central place to catch exceptions and and begin the rescue process.

But where are the Monads?

The implementation of the Warden class is distinctly imperative. Still, the basic premise of inserting something, be it a combinator or non-middleware instance, between otherwise normal method/function calls remains intact. Its an important addition of functionality without intruding on the original purpose of each middleware. Better still, and much like the Either monad, the Warden “combinator” has imbued the call stack with the chance to recover from a bad state while defining a simple way for the middleware to participate in that process. In fact this one change in Vagrant resulted in several hundred lines of code removal by refocusing each call method definition back towards its original purpose.

Learning from Haskell

Anyone who follows Haskell can see that its fortunes are rising in “the real world”. Still, you might be forgiven for thinking its goals too lofty and learning curve too steep for taking the time to learn it. For my part the Warden implementation in Vagrant has been a clear example of what can be gained from spending time learning Haskell. The analogs between function composition and middleware were evident when talking with Mitchell about his middleware implementation in Vagrant. Viewed from that perspective it was natural to look for other techniques and abstractions guided by function composition and combinators that might provide interesting benefits where middleware “composition” was concerned.

My goal for the next article will be to build a middleware implementation in Haskell that reflects the same rescue-able behavior. Then I hope to compare its implementation to existing Rack-like software such as Hack and Wai.

Middleware, Composition, and Monads

This article pre-supposes that you have some basic knowledge of Haskell, Rack/PEP 333, and middleware.

Middleware

Middleware, as a plugin architecture for creating custom web stacks, is an amazing tool (the fact that it makes web servers interchangeable is equally important but not useful for this discussion). By simplifying and standardizing the interface used by middleware to communicate, web developers have been given an easy way to compose and reuse nicely sized chunks of functionality. Interestingly the pattern itself is general enough that it applies just as well to pluggable architectures outside of the web stack as evidenced by recent additions of similar functionality to Vagrant. In fact if you stand back a bit further, just far enough to look past object oriented underpinnings, it starts to look a lot like function composition which many consider to be the pinacle in abstractions for software reuse.

composition

To illustrate the similarities with function composition lets define a simple Rack app with some middleware borrowed from an introductory tutorial on Rack middleware.

# A sample rack app
app = Rack::Builder.new do
  use Rack::Upcase
  use Rack::Reverse

  run lambda { |env| [200, { 'Content-Type' => 'text/html' }, 'Hello World'] }
end

The middleware used here modify the response in the manner you would expect. As long as they both forward the request environment down the stack they are afforded the opportunity to manipulate the response provided, first, by the endpoint and then by any subsequent middleware. Now something similar, though simpler, in Haskell:


import Data.Char
import Prelude hiding (reverse)
import qualified Data.List as List

type Response = (Int, [(String, String)], String)

run = reverse . upcase . \env -> (200, [("Content-Type", "text/html")], "Hello World!")

reverse :: Response -> Response
reverse (s, h, body) = (s, h, (List.reverse body))

upcase :: Response -> Response
upcase (s, h, body) = (s, h, (List.map toUpper body))

-- *Main> run ()
-- (200,[("Content-Type","text/html")],"!DLROW OLLEH")
-- *Main>

There obviously isn’t any environment forwarding performed here, but the response manipulation is virtually the same. Both the Rack middleware and the composed functions form a pipeline of functionality bound by the common expectation of an HTTP response type in the form of a triple. As long as whatever you’re building is able to manipulate that triple it can be used at any stage in the pipeline or in any other pipeline with the same expectation. But this basic composition, a wonderful tool though it is for creating reusable and generic software, still leaves some issues unresolved.

Errors

When building your own Rack middleware there are a couple of ways you can go about handling errors or problematic states. First, you can simply return an error response, thereby alerting the outside world to problems immediately. Alternatively you can attach error information to the environment and allow subsequent middlwares to decide what they would like to do and then possibly modify the response when one is returned. Both options leave something to be desired because there are no guarantees or contracts around error handling. To illustrate lets address the first scenario, see how it maps to function composition and then attempt to improve it.

To do this we’ll add another bit of middleware into our stack, one that has a condition under which it cannot operate and must report a failure. We’ll call it Rack::Head, and it will attempt to trim the response body down to its first character.

module Rack
  class Head
    def initialize app
      @app = app
    end

    def call env
      status, headers, body = @app.call env

      if body.empty?
        [500, headers, "Head cannot operate on an empty string"]
      else
        [status, headers, [body.first]]
      end
    end
  end
end

Now, if the endpoint’s response body is changed to be an empty string this new middleware will have to report its failure to those above it in the stack.

app = Rack::Builder.new do
  use Rack::Upcase
  use Rack::Reverse
  use Rack::Head

  run lambda { |env| [200, { 'Content-Type' => 'text/html' }, ''] }
end

Unfortunately there is no guarantee the middleware above Rack::Head won’t just replace, alter, or in this case reverse the response body making the error response hard to read or non-existent. This, I believe, is an intentionaly flexible design choice leaving what to do with errors in the hands of middleware authors. Looking back to Haskell we get a similarly unfortunate result with pure function composition:

run = reverse . upcase . head . \env -> (200, [("Content-Type", "text/html")], "")

head :: Response -> Response
head (s, h, "") = (s, h, "Head cannot operate on an empty string")
head (s, h, body) = (s, h, [List.head body])

-- *Main> run ()
-- (200,[("Content-Type","text/html")],"GNIRTS YTPME NA NO ETAREPO TONNAC DAEH")
-- *Main>

Here the application accounts for the fact that head is unable to operate on an empty list, an error message replaces the response body, and is subsequently mangled. The application could let head throw its empty list exception, though thats less than optimal as well. It appears that simple composition has reached the limits of its usefulness in error handling and some other tactic is required.

Maybe

While Rack, in its current form, doesn’t have any alternatives to offer when it comes to error handling, Haskell has some interesting tools that might provide some insight. The first, and most oft cited, is the Maybe monad. When used in conjunction with the monad instance of Maybe, functions can continue to use composition, if in a slightly altered form, without much additional overhead for the developer while the pipeline is imbued with the ability to “short circuit” when something untoward occurs1.

import Control.Monad

run = reverse <=< upcase <=< head <=< \env -> Just (200, [("Content-Type", "text/html")], "")

reverse :: Response -> Maybe Response
reverse (s, h, body) = Just (s, h, (List.reverse body))

upcase :: Response -> Maybe Response
upcase (s, h, body) = Just (s, h, (List.map toUpper body))

head :: Response -> Maybe Response
head (s, h, "") = Nothing -- (s, h, "Head cannot operate on an empty string")
head (s, h, body) = Just (s, h, [List.head body])

-- *Main> run ()
-- Nothing
-- *Main> 

There are 3 changes to the original. First, an import of Control.Monad makes the Maybe Monad instance available. Second, the dot composition operator has been replaced with the monad composition operator (<=<). Third, the type of (<=<) is

(<=<) :: (Monad m) => (b -> m c) -> (a -> m b) -> a -> m c

so we are required to wrap our Response with one of the two Maybe value constructors (Maybe is the m in the type signature). If this seems convoluted, just remember that the type of the regular composition operator (.) is

(.) :: (b -> c) -> (a -> b) -> a -> c

and the only real difference is that we’re required to wrap the result in the Maybe monad.

The last is the key to how the head function can prevent the other middleware from altering its error response. The monadic composition operator (<=<) is built on the monadic bind operator, (>>=) which is defined in the Monad instance for Maybe:

instance Monad Maybe where
    return         = Just
    fail           = Nothing
    Nothing  >>= f = Nothing
    (Just x) >>= f = f x

The key is that when Nothing is passed as the first argument to (>>=) the result will always be Nothing. Consequently we can say the same about (<=<) as the only extra work that it does on top of the bind operator is some type unwrapping. So! by making sure to wrap the return result in the Maybe monad with the Just data constructor, or Nothing data constructor if there is a failure, the plumbing for managing errors (ie “short circuiting” ) is handled in the (<=<) operator.

run = reverse <=< upcase <=< head <=< \env -> Just (200, [("Content-Type", "text/html")], "")

-- *Main> run ()
-- Nothing
-- *Main>

run2 = reverse <=< upcase <=< head <=< \env -> Just (200, [("Content-Type", "text/html")], "Hello World!")

-- *Main> run2 ()
-- Just (200,[("Content-Type","text/html")],"H")
-- *Main>

Great! We’ve established a way to prevent the other middleware from futzing with the error, but lets make one small change so that our pipeline can report something more useful than Nothing while continuing to short circuit.

import Control.Monad.Error

reverse :: Response -> Either String Response
reverse (s, h, body) = Right (s, h, (List.reverse body))

upcase :: Response -> Either String Response
upcase (s, h, body) = Right (s, h, (List.map toUpper body))

head :: Response -> Either String Response
head (s, h, "") =  Left "Head cannot operate on an empty string"
head (s, h, body) = Right (s, h, [List.head body])

run = reverse <=< upcase <=< head <=< \env -> Right (200, [("Content-Type", "text/html")], "")

-- *Main> run ()
-- Left "Head cannot operate on an empty string"
-- *Main>

run2 = reverse <=< upcase <=< head <=< \env -> Right (200, [("Content-Type", "text/html")], "Hello World!")

-- *Main> run2 ()
-- Right (200,[("Content-Type","text/html")],"H")
-- *Main>

The only thing thats changed here is that Either has replaced Maybe as our Monad of choice. It should come as no surprise that its defined in Control.Monad.Error, and it has two data constructors just like Maybe; Left for signaling failure and Right for signaling success. As a result we can include a message for the operator of the function to give them some helpful debugging information without worrying about another function farther up the line meddling!

Closing

Next time I’d like to take the concepts we’ve applied here to our Haskell “middleware” and show how abstracting the error handling in a Builder class like Rack’s can provide benefits for use in something like Vagrant. Most of all I hope that this might provide some clarity around why function composition, and by extension middleware, is a really nice patterns for creating modular software.

Notes

1. Functions composed in the Maybe monad, as in the example, don’t actually short circuit. They have to run through each composition but as you can see from the Maybe Monad instance they don’t execute the function itself.

2. Replacing our Response whole sale with a Left String is really only useful for illustration in this case. It would be better to at least use Either Response Response, and provide an errorResponse function that takes a string and sets the status and headers properly.