Combining Stateful Computations with Stateful Monads

One of the most amazing features of State is that it can be used to combine multiple stateful computations that depend on a fixed-type state.

To understand how to combine variable stateful computations, lets first create a simple function called compute in the index.js file. This function takes in a number and returns a State Number of Number with Number as the state and the resultant.

const compute = number =>

State.of(number)

Here, we have taken in a number as the input, but in order to get it into the state and resultant, State has given us a construction helper called of . of will take any type and give it to us as state and resultant.

To see if this has worked, write a log statement as shown below:

log(compute(100).runWith(200));

Run the node command in the terminal and you will get the output as Pair(100,200) . This means that the resultant value is 100 while the state value is 200.

If you want to modify the resultant, you can use the map function to lift a function over the the resultant. Let’s use the add function from the helpers.js file to modify the value of the resultant. Rewrite the compute function as shown below:

const compute = number =>

State.of(number)

.map(add(2))

With this, you will get the output as 102.

We can also add the value of the state with the resultant. For this, we have a method called chain . Let’s try it out!

Inside the compute function, replace the .map method with a call to the .chain and pass it a function that will take the resultant as the input.

Inside the State constructor, there is a helper called get that we will use to grab the state. Make sure that it is extracted from the state as shown below:

const {get} = State

We will then use get along with chain to add the resultant with the state.

const compute = number =>

State.of(number)

.chain(a => get(add(x)))

Run the node command, and see what output you get in the terminal.

We can further improve the above function by creating a better, separate function that will take a number and return the result of calling get with number partially applied to add .

const addState = number =>

get(add(number))

const compute = number =>

State.of(number)

.chain(addState)

Till now, we have seen how we can modify the resultant. Now lets take look at how we can modify the state as well. Lets create another function that will essentially increment the value of the state.

Inside the helpers.js file, create a new function called increment .

const increment = add(1)

Then import this function in to the index.js file.

const {add, inc} = require('./helpers.js');

Also extract the modify function from the State .

const {get, modify} = State

Then use modify and inc to create a function that will increment the value of state by 1, and chain that function to compute as shown below.

const incState = () =>

modify(inc) const compute = number =>

State.of(number)

.chain(addState)

.chain(incState)

Run the node command to get the output as 201.

But if you take a look at the resultant, you will see that it has been replaced with a unit () .

Let’s take care of this issue. First, we need to allow a number to be taken in as the input to our function. Then, we need to get the number into our resultant. But we can’t do it with the map as it expects a function and not a number.

crocks has a special combinator called constant that we can use here.

const constant = require('crocks/combinators/constant');

Let’s use it inside the incState function as shown below.

const incState = number =>

modify(inc)

.map(constant(n))