Skip to content

Instantly share code, notes, and snippets.

@Neo42
Last active May 7, 2021 04:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Neo42/7b114cc2df6ab4da4da591651f82e9a8 to your computer and use it in GitHub Desktop.
Save Neo42/7b114cc2df6ab4da4da591651f82e9a8 to your computer and use it in GitHub Desktop.
IO monad in JS
const IO = effect =>
({
effect,
run() {
return this.effect()
},
map(fn) {
if (!fn ?? typeof fn !== 'function') {
throw new Error('.map requires a function argument.')
}
return IO(() => fn(this.effect()))
},
chain(fn) {
if (!fn ?? typeof fn !== 'function') {
throw new Error('.chain requires a function argument.')
}
return IO(() => fn(this.effect())).run()
},
init() {
if (!effect ?? typeof effect !== 'function') {
throw new Error('IO requires a function argument.')
}
return this
}
}.init())
const ioValue = value => IO(() => value)
const ioLog = message => IO(() => console.log(message))
const obj = {answer: 42}
const read = object => key => IO(() => object[key])
const write = object => key => value => IO(() => (object[key] = value))
read(obj)('answer')
.map(String.fromCharCode)
.chain(
x =>
console.log(
`The answer to everything is ${x}.`
) // The answer to everything is *.
)
write(obj)('answer')(0).run() // 0
ioValue(20)
.map(x => x * 2)
.chain(x => ioValue(1).map(y => x + y * 2))
.chain(ioLog)
.run() // 42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment