-
-
Save hedefalk/4c48a6313946a302385624cb57dfeb7b to your computer and use it in GitHub Desktop.
Pure TypeScript
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
// Did you know JavaScript has pure functions*? | |
// *: just add asterisks! | |
/** | |
* Describes a computation that requires `E` to produce an `A`. Has to be run | |
* to do anything. | |
* | |
* We could also do something like: | |
* `type Async<E,A> = Generator<void,Promise<A>,E>` | |
*/ | |
type IO<E,A> = Generator<void,A,E>; | |
/** | |
* The random effect 🎰 | |
*/ | |
interface Random { | |
random(): number | |
} | |
/** | |
* The logging effect 📝 | |
*/ | |
interface Log { | |
log(msg: any): void | |
} | |
function* random(): IO<Random, number> { | |
console.log('running random'); | |
// `yield` here fetches the `E` | |
return (yield).random(); | |
} | |
function* log(msg: any): IO<Log, void> { | |
console.log('running log'); | |
(yield).log(msg); | |
} | |
// Look Haskell, I'm pure! λ | |
{ | |
random(); | |
log('complete silence 😶') | |
} | |
function unsafeRun<E,A>(io: IO<E,A>, e: E): A { | |
let res; | |
do { | |
// Ignoring errors 🚨 | |
res = io.next(e) | |
} while (!res.done) | |
return res.value as A; | |
} | |
function* main() { | |
// We can use `yield*` like `<-` in Scala and Haskell | |
yield* log("i'm going to log something random"); | |
let rn = yield* random(); | |
yield* log(rn); | |
} | |
main() // Still pure 🚔 | |
// TypeScript somehow magically infers `E` to be `Log & Random` | |
// Here we could pass in mocks for testing 🧪 | |
unsafeRun(main(), { | |
log: (msg) => console.log(msg), | |
random: () => Math.random(), | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment