jQuery is a Monad

January 18, 2009 at 4:53 am 20 comments

It’s said that every Haskell programmer writes their own monad tutorial, and with good reason: once you finally understand the definition and capabilities of a monad, you’ll be eager to try and break the mystique surrounding the concept of monads as a whole. To the outsider, monads are an impenetrable barrier to truly understanding Haskell; they’re cursed with a very unfortunate name, have bizarre syntax, and seem to do a thousand things at once. However, monads aren’t hard to understand when you see them in action.

As such, I present to you what may be the most widely-used monadic library in any language: the jQuery library, designed to bring Javascript back to its roots in functional programming and make AJAX and animations easy. The jQuery object, accessible through the jQuery variable or the $ shortcut, allows you to query or make DOM elements using CSS selectors or XPath queries, as shown below:

$("div"); // all div elements
$("span.moveable") // all spans with the moveable class
$("em,strong"); // all emphasized and strong tags
$("div\[img][3]"); // the third div that contains an image

It may be somewhat alarming, but jQuery all but eliminates the need for instance variables thanks to its method chaining. If I wanted to take all the span elements, fade them in, then set their text to “Alert!”, all without jQuery, I would need instance variables to save the found elements, to keep track of elapsed time, and perform each operation sequentially. In jQuery, it’s much easier:

$("span").fadeIn("slow").text("Alert!");

The returned result of fadeIn is not null, as one might otherwise assume, but the very same jQuery container $("span") upon which it was called. That way, I was able to call the .text("Alert!") method, which likewise returns the same container. Method chaining like this gives an immense dose of power, concision and readability to a previously flabby language. In addition to DOM manipulation, jQuery provides powerful AJAX shortcuts, attractive yet unobtrusive animations, and extensive CSS manipulation.

The Monadic Laws

Now that you have a basic idea of the concepts upon which jQuery is founded, let’s take a look at the three monadic laws. (The concept of monads and the monadic laws were first codified in the branch of mathematics known as category theory – beware, the previous link is dense as hell.)

The first monadic law is that a monad is a wrapper around another type. In Haskell, one has the IO String type, which is returned from functions that read from files, console input, or system calls – IO is a monad that wraps the String data type. jQuery obviously satisfies this condition, as it wraps DOM nodes retrieved through given queries.

The second monadic law is just as simple: all monads must have a function to wrap themselves around other data types. jQuery clearly has ways to apply itself to DOM nodes – you use the querying facilities to traverse the DOM, and if you’re feeling especially saucy, you can use pass the results of document.getElementsByTagName and its siblings to the jQuery object. Haskell refers to this as a type constructor – a function that takes some data and wraps that data inside a new type. (jQuery’s type constructor is its parentheses.)

The third monadic law, and the only one that’s even remotely complicated, is that all monads must be able to feed the value or values that they wrap into another function, as long as that function eventually returns a monad. fadeIn(), text(), and all the other chainable functions are examples of this – they take the elements given inside the jQuery object, perform their function on them, then rewraps them back into the jQuery object and returns them. And don’t think that you’re just limited to the built-in functions on the jQuery object – using the map() function, you can pass an anonymous function that will be called on each DOM element inside the jQuery object. map() will still return the jQuery object upon which it was called.

So, let’s review. Monads are abstract data types that satisfy three conditions:
1) They wrap themselves around other data types
2) They have an operation, confusingly called return, that actually performs the aforementioned wrapping
3) They have an operation called bind that allows to feed the value wrapped inside the monad into another function, as long as the function returns a monad.

Bam. That’s it. Simple – almost so simple as to be useless. But monads are like objects in that though they are conceptually very simple, they are immensely powerful. In Haskell, monads are used as an abstract datatype to represent actions – since they an be chained together, they a perfect fit for traditional imperative programming or code that depends on the outside world. Any keyboard input or file input in Haskell is wrapped inside an IO monad, serving to indicate that this part of the program is dependent on the outside world. By indicating that only certain sections of your programs depend on external, unpredictable input you not only make your debugging easier but also ensure that the rest of your functions depend only on their inputs. If you’re interested in learning about the other ways that Haskell uses monads or learning a stricter definition of monads, check out Jeff Newburn’s All About Monads.

“This is all well and good”, you say, “but how does jQuery’s monadic implementation manifest itself in common jQuery idioms?” Well, I’m glad that you asked.

Cautious Computations

Each language has its own way of dealing with passing a null object to a function that expects a non-null object or sending a message to a null object. Objective-C returns nil, Java throws NullPointerExceptions, and C – well, C segfaults, but what else is new? The jQuery equivalent of this would be trying to manipulate the contents of an empty jQuery object, like so:

$([]).fadeOut().text("THE WORLD HAS BROKEN!");

By calling the jQuery’s type constructor with an empty array as a parameter, we get an empty jQuery object; even though I’m calling fadeOut() and text() on nothing at all, jQuery will fail gracefully rather than spew errors all over the console. Much like Objective-C’s behavior when messaging nil or Ruby’s andand, this allows you to chain a long series of computations that may fail at some point together safely. From a higher-level perspective, this is very similar to Haskell’s Maybe monad, used to represent computations that might fail, such as a hashtable lookup.

State Transformations

When I heard that variables in Haskell could never change, I was horrified. Sure, I knew there are ways to work around this – recursion is the primary way – but I knew that there had to be some corner case where I would need to destructively update variables. It turns out I didn’t need to worry, because one of the most useful monads is the State monad. Not only does the State monad provide a vehicle in which to bind variables like you would in a regular language, but it also provides a useful semantic distinction – the very presence of the State monad in a function’s type implies that it depends on some state. (Now that I think about it, Haskell’s type system alone is more expressive than most languages.)

jQuery can be seen as a state monad too – it encapsulates a set of DOM nodes and allows you to chain stateful computations upon them. There are simple methods to change what is matched – add() adds new elements to the current object, contents() matches all children of the wrapped DOM nodes, and so on and so forth. The andSelf() and end() methods are much more interesting and much more reminiscent of Haskell’s state monad. Let’s take a look at how they work:

$("div.sidebar").find("a").andSelf().addClass('disabled')

In the above snippet, the $(“div.sidebar”) finds a div element with the sidebar class, and the find("a") class matches all links inside the sidebar. Were we to manipulate the jQuery object right now, only the links would be modified – instead, we add andSelf(), which readds the matched div element. We then add the ‘disabled’ class. end() performs the converse of andSelf() – it removes the elements matched by the previous destructive operation:

$("div.sidebar").find("a").addClass('disabled').end().fadeOut()

Conclusions

  1. Monads aren’t esoteric, abstruse computer science – they’re useful.
  2. You probably have used monads but just haven’t realized it.
  3. jQuery is awesome.

And with that, I will go and observe DC descend into delicious chaos.

Entry filed under: code. Tags: , , , .

A Deeply Skeptical Look at C++0x

20 Comments

  • 1. Jed Schmidt  |  January 18, 2009 at 9:38 am

    One correction: $() doesn’t return an empty jQuery object, $([]) does. $() is a shortcut for $(document).

  • 2. floridadeathmetal  |  January 18, 2009 at 4:15 pm

    Interesting read. Didn’t even know what a monad was before. Thx.

  • 3. ak  |  January 18, 2009 at 4:36 pm

    Good read! And a serendipitous find at that, thanks to Delicious.

    I had just read Why Haskell is beyond ready for Prime Time and browsed the Hackage repository to get a feel for what’s going on with Haskell.

    Seeing mentions of of Monads all over the place were a bit startling – I gathered they were some sort of Haskell paradigm/pattern/principle doodad, but didn’t follow up on that. Though interesting, everything seemed quite removed from my day-to-day working stack.

    I love the lofty feel, a better tomorrow today and all that – yet any applicability to my actual process was not so obvious. For all the flexibility and potential for self- and process-improvement we enjoy at the top of the ladder (HTML/JS/CSS), one rung down we’re pretty much tied down to Java and PHP. And I don’t have a problem with that – yes, I too got hooked on the promises of Django, RoR, etc. with their ideas of even more elegance and beauty, paired with all that recovered free time we’d have.

    Diving into one of these usually left one with the impression that you’d go through all that learnin’ only to come out on the other hand beginning to solve all the same problems again, albeit in a new way. It’s like Blu-Ray.. all the hoopla to make the switch, only to find out most movies still suck..

    So where did I land? I get to be the beneficiary of all the hard working people bringing these new ideas to the stack we have in place and improve on. On the PHP side, the efforts and advances of CakePHP and its community have brought an enourmous amount of joy and productivity boosts. As for Java, we are working with a tried and tested yet insanely fast-paced (dare I say, “agile”) self-developed and GPL’d CMS framework. Seeing this power some large international sites in a fast, reliable, and adaptive way makes me shudder to think what we’d be up against if we had to work with servers that could only run straight for about 4 minutes (remember that tidbit?). A love for experimentation certainly doesn’t translate to the more reality-driven workplace easily. So all in all, bring on the new ideas, but pairing each idea with a whole new stack is hardly ever useful in the real world.

    So.. back to your great post – having both new and old ideas float into my stack is most welcome, plus getting to know other mindsets and implementations is always valuable and insightful. And to find my dear jQuery (which I love to pieces) actually has one of the aforementioned lofty doodads at its core is, well, priceless. Did I mention I nearly wept with joy upon seeing the performance graphs of jQuery 1.3′s newly released selector engine, Sizzle? I wonder if the Blu-Ray release of Cool Hand Luke will do the same for me…

  • 4. ak  |  January 18, 2009 at 4:37 pm

    .. I did not actually come out “on the other hand”, sorry.. :)

  • 5. orcmid  |  January 18, 2009 at 4:42 pm

    Nicely done. With lifting you’d have covered how to carry out stateful/transformational operations inside of the development of a functional result (depending on how the side effects are sealed inside the function’s procedure).

    You flipped me from non-interest to serious interest in jQuery. (Hat tip to Phil Windley)

  • [...] jQuery is a Monad It’s said that every Haskell programmer writes their own monad tutorial, and with good reason: once you finally [...] [...]

  • 7. powtac  |  January 18, 2009 at 5:29 pm

    Great explanations! Thanks.

  • 8. Lyndon Commto  |  January 18, 2009 at 5:51 pm

    More jQuery resources at:
    http://www.jquerybasics.com

  • 9. Patrick Thomson  |  January 18, 2009 at 5:56 pm

    Jed: Thanks. I’ve corrected that mistake.

  • 10. DJR  |  January 18, 2009 at 6:31 pm

    Patrick, awesome, you have explained monads very nicely thanks. Good on you for using examples that a lot of us are familiar with. Thanks.
    PS. Hope the chaos was delicious.

  • 11. JQuery is a monad « The other side of the firewall  |  January 18, 2009 at 6:39 pm

    [...] January 18, 2009 at 1:38 pm · Filed under Programming Comments [From JQuery is a monad] [...]

  • 12. mostafa farghaly  |  January 18, 2009 at 6:40 pm

    I never heared of Monad , But really your explanation is great , thank you

  • 13. Michael  |  January 19, 2009 at 2:02 am

    Hmmm… those aren’t the three monad laws. What you’ve described is the structure of a Monad, and in particular, the Haskell-specific structure, not the Category Theoretic structure. Abstractly, a Monad is a functor with two transformations: unit and join (from which Haskell’s bind can be derived), and furthermore adheres to the three laws of left identity, right identity, and associativity.

    I see where you’re going with your post, but you’re not quite there yet. If you want to call something a Monad, be rigorous and accurate, or otherwise make it known that you’re just making a loose comparison.

  • 14. Frank  |  January 19, 2009 at 5:01 am

    Great explanation of Monads. I had no idea. Articles like this make me enjoy the jQuery community even more. BTW – I just found this awesome jQuery cheat sheet for the iPhone. It’s really great. I’ve only had it for a couple days and it’s already making my life a lot easier.

    http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=302090867&mt=8

    Looks like there’s also a CSS Cheat Sheet from the same guys.

    http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=301093674&mt=8

    Mmmm mmmm time saving goodness!

  • 15. Rui Silva  |  January 19, 2009 at 4:07 pm

    Beautiful! Haskell is a language that came from my university course. I use jQuery and i love it! Great post!

    Cheers

  • 16. bob9167  |  January 19, 2009 at 7:49 pm

    Great post. I’m using jquery for two months now and I can’t stop — I’m using it for all my projects :)

  • 17. links for 2009-01-20 « My Weblog  |  January 21, 2009 at 4:04 am

    [...] jQuery is a Monad « Important Shock (tags: haskell javascript) [...]

  • 18. Hacking at 0300 : jQuery and Haskell  |  January 23, 2009 at 4:21 am

    [...] and jQuery helps undress it a bit. Now it turns out that really jQuery is really forcing it to cross-dress in Haskell. I guess I understood Haskell all along! Posted by Danny on Thursday, January 22, 2009, at 10:21 [...]

  • 19. jQuery, Monads, and Functional Programming | SKY ROCK INDIA  |  January 25, 2009 at 4:32 pm

    [...] it deserves a bigger mention than that. Patrick Thomson has written a wonderful description of why jQuery is a monad including a discussion of cautious computation and state transformations. No need to know monads or [...]

  • 20. Mauricio Scheffer  |  January 27, 2009 at 8:02 pm

    Hehe, I was just writing some jQuery code and I thought: “this is a monad! cool, now let’s see if someone has written about it…” (google: jquery monad) “oh crap” :-D


About Me



I'm Patrick Thomson. This was a blog about computer programming and computer science that I wrote in high school and college. I have since disavowed many of the views expressed on this site, but I'm keeping it around out of fondness.

If you like this, you might want to check out my Twitter or Tumblr, both of which are occasionally about code.

Blog Stats

  • 520,243 hits

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: