Skip to content

Instantly share code, notes, and snippets.

@masaeedu
Created July 15, 2018 11:38
Show Gist options
  • Save masaeedu/5cfd4eac4a6f1d0e1efdfc5cb9bbf237 to your computer and use it in GitHub Desktop.
Save masaeedu/5cfd4eac4a6f1d0e1efdfc5cb9bbf237 to your computer and use it in GitHub Desktop.
Using the state monad for RNG
// A simple pseudorandom number generator
// http://indiegamr.com/generate-repeatable-random-numbers-in-js/
// :: type Seed = Int
const PRNG = {
// :: Seed -> Seed
next: s => (s * 9301 + 49297) % 233280,
// Generate a number between 0 and 1
// and increment the seed
// :: Seed -> (Float, Seed)
random: s_ => {
const s = PRNG.next(s_)
const f = s / 233280
return [f, s]
}
}
// Implement the State monad
// :: type State s a = s -> '[a, s]
const State = (() => {
// :: a -> State s a
const of = x => s => [x, s]
// :: (a -> State s b) -> State s a -> State s b
const chain = f => m => {
return s => {
const [a, s_] = m(s)
return f(a)(s_)
}
}
// These are basically the same for all monads,
// you can more or less skim them
// :: (a -> b) -> State s a -> State s b
const map = f => chain(x => of(f(x)))
// :: (a -> b -> c) -> State s a -> State s b -> State s c
const lift2 = f => mx => my => chain(x => map(y => f(x)(y))(my))(mx)
// Now we get to the interesting operations for
// stateful computations
// get is a stateful computation that simply
// sets the result of the computation to the
// current state
// :: s -> State s s
const get = s => [s, s]
// put updates the state to some chosen value
// :: x -> State x ()
const put = x => _ => [undefined, x]
return { of, chain, map, lift2, get, put }
})()
// :: Int -> Int -> State Seed Int
const randomInt = min => max =>
State.map(f => min + Math.round((max - min) * f))(PRNG.random)
// Now let's do a stateful computation
const r1 = randomInt(1)(5)
const r2 = randomInt(2)(4)
const r3 = State.lift2(x => y => x * y)(r1)(r2)
const initialPRNG = 3
console.log(r3(initialPRNG))
// => [4, 50657]
// We can also run the same computation with a different initial seed
console.log(r3(15))
// => [8, 57869]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment