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
= -s
valFromState s
nextState :: MyState -> MyState
= 1 + x
nextState 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
= state (\st -> let st' = nextState(st) in (valFromState(st'),st') )
getNext
-- advance the state three times.
inc3 :: MyStateMonad Int
= getNext >>= \x ->
inc3 >>= \y ->
getNext >>= \z ->
getNext return z
= do
main 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";
= number;
type MyState
const valFromState = (m: MyState): number => -m;
const nextState = (m: MyState): MyState => 1 + m;
<S> = State<MyState, S>;
type MyStateMonad
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!