Last active
May 7, 2021 04:05
-
-
Save Neo42/7b114cc2df6ab4da4da591651f82e9a8 to your computer and use it in GitHub Desktop.
IO monad in JS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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