doThingOne(); doThingTwo()
... you get to pick what happens during the semicolon depending on which Monad you happen to be working with.For example, like praptak mentioned, maybe during every semicolon you can evaluate the failure state of your program and decide not to continue. I.E., "Maybe" the execution worked, and "Maybe" I have a valid computation at this point, but "Maybe" not!
The power here is that while you are really operating in this context with an implicit possibility of having failure, you can program as if each step succeeded. So now we can string together a whole sequence of possibly-failing computations, and create a bigger possibly-failing super-computation that error checks under the hood.
If you desugar everything from the State monad, than you can see, that the state 'c' is an explicit argument, which is hidden in the "sugared" version.
import Control.Monad.State.Lazy
type Counter = State Int
-- using the State monad and the do notation
increment :: Counter ()
increment = do
c <- get
put $ c + 1
-- using the State monad and desugar the do notation
increment_ :: Counter ()
increment_ = get >>= \c -> put $ c + 1
-- desugar 'get'
get_ = \c -> (c, c)
-- desugar 'put'
put_ c = \_ -> ((), c)
-- desugar >>=
bind_ a b = \c -> let (result, c') = a c in (b result) c'
-- "desugar" the State monad
increment__ = get_ `bind_` \c -> put_ $ c + 1Pretending 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