Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I may be misunderstanding you, but from your description, that more describes functors than it does monads. The difference being that in a monad, the `someFunc` you pass in is responsible for creating a new context (of the same monad type).

Pretending that javascript is immutable, I think it would probably look something more like

    contextObj = monadBox(myObj)
    // someContextReturningFunc gets myObj as its argument from contextObj and generates newContextObj
    newContextObj = monadBind(contextObj, someContextReturningFunc)
    newNewContextObj = monadBind(newContextObj, someOtherContextReturningFunc)
    ...
To make this more concrete, let's take the Maybe monad/functor in javascript and compare them. The Maybe monad is described by johnpmayer elsewhere here.

    // Creating maybe "contexts"
    maybeNothing = {maybe: "nothing"}; // maybeMonad holding nothing
    maybeJust = function(x) { return {maybe: "just", just: x} }; // create a maybeMonad holding a (the '[a]' in the picture)

    // Monadic bind
    function maybeBind(maybeMonad, f) {
      // maybeMonad is '[a]' in the picture
      if (maybeMonad.maybe === "just") {
        return f(maybeMonad.just); // expects f to return another maybeMonad '[b]'
      } else {
        return maybeNothing; // also '[b]' but the b value doesn't really exist
      }
    }

    // Functor map
    function maybeMap(maybeMonad, f) {
      // maybeMonad is '[a]' in the picture
      if (maybeMonad.maybe === "just") {
        return maybeJust(f(maybeMonad.just)); // expects f to return a value without any maybe stuff ('a -> b')
        // notice that the monad wrapping remains separate from f
      } else {
        return maybeNothing;
      }
    }

    // Functor examples
    //////

    // possible values of 'f', note that maybe is not involved at all
    function addOne(x) { return x + 1; }

    // usage
    console.log(maybeMap(maybeJust(1), addOne)); // returns maybeJust(2)
    console.log(maybeMap(maybeNothing, addOne)); // returns maybeNothing


    // Monad examples
    //////
    
    // possible values for 'f', notice x is what was contained in the maybe (not the maybe itself) and the return is a maybe
    function maybeAddOneIfOdd(x) { return (x % 2 == 0) ? maybeNothing : maybeJust(x + 1); };
    function maybeAddThree(x) { return maybeJust(x + 3); };   

    // usage
    console.log(maybeBind(maybeJust(1), maybeAddThree)); // returns maybeJust(4)
    console.log(maybeBind(maybeJust(1), maybeAddOneIfOdd)); // returns maybeJust(2)
    console.log(maybeBind(maybeBind(maybeJust(1), maybeAddThree), maybeAddOneIfOdd)); // returns maybeNothing (due to 4 being even)
    console.log(maybeBind(maybeBind(maybeJust(2), maybeAddOneIfOdd), maybeAddThree)); // returns maybeNothing because the first bind returned nothing

    // and of course, composition
    function maybeMultiplyThree(x) { return maybeJust(x * 3); }
    function maybeMultiplyThreeThenAddOneIfOdd(x) {
      return maybeBind(maybeMultiplyThree(x), maybeAddOneIfOdd);
    }

    console.log(maybeBind(maybeJust(1), maybeMultiplyThreeThenAddOneIfOdd)); // returns maybeJust(4)
    console.log(maybeBind(maybeJust(2), maybeMultiplyThreeThenAddOneIfOdd)); // returns maybeNothing
Edit: added some extra examples and comments


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: