Skip to content

Instantly share code, notes, and snippets.

@thoradam
Created March 5, 2020 15:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save thoradam/7362431b78e3fe92bd28ae71b3167b4e to your computer and use it in GitHub Desktop.
Save thoradam/7362431b78e3fe92bd28ae71b3167b4e 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(),
})
@hedefalk
Copy link

hedefalk commented Mar 5, 2020

Ugh!

@hedefalk
Copy link

hedefalk commented Mar 5, 2020

Nice!!

@hedefalk
Copy link

hedefalk commented Mar 5, 2020

I think I can definitely live with those yield*. Better than fp-ts pipe's!

@hedefalk
Copy link

@thoradam Did you continue any on this stuff? I'm still intrigued :) I just revisited fp-ts and io-ts and noticed he had somewhat better do-notation that I didn't find last time I looked:

https://gcanti.github.io/fp-ts/guides/do-notation.html

But there's something really cool here when stuck in ts…

@thoradam
Copy link
Author

@hedefalk No I didn’t take this further, not writing any TS anymore ^_^ Another thing I looked into at the time was overloading async/await, but unfortunately TS fixes it to Promise. I had looked at the fp-ts do notation but I think it’s way too noisy :S

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment