Typescript - Implementing State Monad from HaskellWiki Example

Posted on August 8, 2018

I’ve been learning about the State monad lately, and I’ve been looking for examples for which I can try out my new found knowledge. I usually do this by implementing it in another language, in this case Typescript. I found this example from the HaskellWiki site. As the comments say in the Haskell code, getNext will add 1 to the state, and return -1 to the state as the computed value. inc3 then advances the state three times.

type MyState = Int
 
valFromState :: MyState -> Int
valFromState s = -s

nextState :: MyState -> MyState
nextState x = 1 + x
 
type MyStateMonad  = State MyState 
 
-- this is it, the State transformation.  
-- Add 1 to the state, return -1 to the state as the computed value.
getNext ::   MyStateMonad  Int
getNext = state  (\st -> let st' = nextState(st) in (valFromState(st'),st') )
 
-- advance the state three times.
inc3 :: MyStateMonad Int
inc3 =  getNext >>= \x ->
        getNext >>= \y ->
        getNext >>= \z ->
        return z

main = do
  print (evalState inc3 0) -- -3
  print (runState inc3 0) -- (-3, 3)

With imperative programming and mutation this would be translated to declaring a variable with an initial value then incrementing that value by mutating that variable with the += operator.

The Haskell code above translates to Typescript like this. The nomenclature that the Javascript/Typescript FP communities have for the bind (>>=) operator is either chain, flatMap, or mergeMap. fp-ts chose chain.

import { State } from "fp-ts/lib/State";

type MyState = number;

const valFromState = (m: MyState): number => -m;
const nextState = (m: MyState): MyState => 1 + m;

type MyStateMonad<S> = State<MyState, S>;

const getNext = new State<number, number>(st => {
  const st_ = nextState(st);
  return [valFromState(st_), st_];
});


const inc3 = getNext.chain(x => getNext.chain(y => getNext));

console.log(inc3.eval(0));
console.log(inc3.run(0));

I’m looking into using the StateT monad transformer in implementing UI states such as transitioning from one UI state to the next, and etc. Wish me luck!