Skip to content

Instantly share code, notes, and snippets.

@hedefalk
Forked from thoradam/io.ts
Created December 15, 2021 17:03
Show Gist options
  • Save hedefalk/4c48a6313946a302385624cb57dfeb7b to your computer and use it in GitHub Desktop.
Save hedefalk/4c48a6313946a302385624cb57dfeb7b to your computer and use it in GitHub Desktop.
Pure TypeScript
// 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