 ```
/*
by

Cratylus

in windows fire up a command shell and run

this is my take on what monads are, if i'm wrong  let me know :)

this shows how to create state transformers -  ie functions which modify state and pass it along for further computation

this is just to present the concept of a monad as an aid (?) to understanding ( at leasts my own )

imperative languages like javascript don't _need_ monads because they already have state built in

a monad in this case is basically a function ftom a state to a pair consisting of the result of the computation and the new state :
viz:     monad  = function from states to pairs of (result,state)

so to actually grab our result of a computation, we would do     finalresult =    monad(startstate)   <---- the first element of the pair

bind is a function that allows us to combine the results of one monad and feed it in to another one
bind "secretly" passes the state of the computation
to make bind easier to read  we define two projection functions from pairs to the first and second elements of the pair

mreturn just allows us to intialise a monad with a value

references :

ive just taken Oleg Kiselyov's scheme monads and translated them into javascript

check out Douglas Crockford's clever javascript page too

monads are actually more general mathematical entities

google for monad category theory to find out more

*/

function State(x,y) {
//simple state object  - imagine x and y are "registers" for example
this.x = x;
this.y = y;
// this is just fluff
this.describe =  describe;
}

function describe() {
// just fluff - change this if you're not using windows
WScript.echo("x value = " + this.x.toString() + "  y value = " + this.y.toString() );
}

function makepair(a,s) {
// just an array to hold the result and a state object

return  [a,s];
}

function getstate(pair) {
return pair;
}

function getresult(pair) {
return pair;
}

function mreturn(a) {
return function (s) {
return makepair(a,s);
};
}

function bind(m,f) {
return function (oldstate) {
// m is a function of a state to a pair
pair =  m(oldstate);
// we grab the state from the pair
newstate = getstate(pair);
// we grab the result of the m computation which has been placed in
// the result position of the pair
result = getresult(pair);
// we apply our function f to this result, which gives us
// a new computation (i.e.  a new monad : another function which  takes a state to a pair )
// finally we apply this function to the new state to get another computation
};
}

// notice that the "new" word in the makepair function  --  we are actually creating  a new state object each call :)

var incx = function(val) {
return function(state) {
return makepair(null,new State(state.x + val,state.y));
};
}

var incy = function(val) {
return function(state) {
return makepair(null,new State(state.x,state.y + val));
};
}

// first we just cook up a start state
var startstate = new State(0,0);

// here is a simple state transformer  function which adds 21 to a number, keeping the state constant

function foo(val) {
return function(state) {
return makepair(val + 21,new State(state.x,state.y));
};
}

//to illustrate the monad return law:       return x >>= f      =   f x        NB.    f x is itself a state transformer function :)

// mreturn just gives us a value to work with
WScript.echo("Illustrating the monad return law");
WScript.echo("foo(21) in the start state")
var result =  foo(21)(startstate);
WScript.echo(result);
WScript.echo("return 21 >>= foo");
var returncomputation = bind(mreturn(21),foo);
WScript.echo(returncomputation(startstate));

/* we can build up complex state transformations by using bind
our example corresponds to the imperative program:
incx 10
incy 12
incx 100

given our state State = (0,0)

we expect that the final state should be  (110,12)

note that we do not use the val parameter fed in to the functions here, because we are not using the results of previous computations
the result null is returned by each incx or incy function , but we could make it return a value here  - i'll write this up later
hideous huh?
*/
var program =  bind(bind(bind(mreturn(null),function (val) {return incx(10);}),function (val) {return incy(12);}),function (val) {return incx(100);});