Google
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.

Published

08 Jul 2011

Tags