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!