Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Monads in JavaScript?

How would an example JavaScript code look like that uses Monad? I'm asking because understanding Monad is much clearer if I can see a code example (and JavaScript being a simple, functional language it could be the best language to use to learn it).

like image 806
Tower Avatar asked Dec 28 '11 12:12

Tower


1 Answers

I would start by writing your own monad in JavaScript. The list monad is a great place to start; I find it by far the most useful. Simply define functions which do the following:

  1. Create a list of one given item (call this mreturn).
  2. Create an empty list (call this mzero).
  3. Append one list to another (call this mplus).
  4. Apply a function to transform every element in a given list (call this map).
  5. "Flatten" a list of lists into a simple list by concatenating the lists (call this join).

This defines what's known as an "additive monad" (mzero and mplus form the "additive" part). Play around to see what interesting things you can do using only these functions to operate on lists. For example, you can compute the list of all even numbers on a schoolkid's multiplication table like so:

var nums = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
var even_products = join(map(join(map(nums, function (x) {
        return map(nums, function(y) { return x * y })
    })),
    function (x) { if (x % 2 == 0) { return mreturn(x) } else { return mzero() } }
));

Alternatively, combine map and join together as a single function defined as function bind(l, f) { return join(map(l, f)) }. bind can be used instead of map and join and is used more often in e.g. Haskell. The same exercise above can then be written:

var nums = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
var even_products = bind(
    bind(nums, function (x) {
        return bind(nums, function (y) { return mreturn(x * y) })
    }),
    function (x) { if (x % 2 == 0) { return mreturn(x) } else { return mzero() } }
);

Finally, you may want to incorporate these functions as part of a new list prototype (or whatever JavaScript has that passes for classes these days), so you can instead write the jQuery-esque:

var nums = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
var even_products = nums
    .bind(function (x) { return nums.bind(function (y) { return mreturn(x * y) }) })
    .bind(function (x) { if (x % 2 == 0) { return mreturn(x) } else { return mzero() } });
like image 124
Chris Pacejo Avatar answered Nov 04 '22 15:11

Chris Pacejo