Skip to content

Instantly share code, notes, and snippets.

@ahaym
Created May 25, 2022 05:25
Show Gist options
  • Save ahaym/a5e36b5b454247234bca2c1ec27bd76b to your computer and use it in GitHub Desktop.
Save ahaym/a5e36b5b454247234bca2c1ec27bd76b to your computer and use it in GitHub Desktop.
// Yoneda states that
// (1) f a
// is isomorphic to:
// (2) forall b. (a -> f b) -> f b
//
// You can read this as "an interface that lets me run any function on an 'a' and get its result is isomorphic to having the a itself.
// The f here is a functor, for this example we can remove generality and say `f a` is "an async computation that returns an a".
//
// So here's (1) if JS allowed me to just call async functions without handlers:
function appendFiles(file1, file2) {
contents1 = fs.readFile(file1);
contents2 = fs.readFile(file2);
return contents1 + contents2
}
// So appendFiles is (file, file) -> f string.
// Here's (2), which is actually how they do it in (old) node js:
function appendFiles(file1, file2, continuation) {
fs.readFile(file1, function(err_, contents1) {
fs.readFile(file2, function(err__, contents2), {
let err = ...
return continuation(contents1 + contents2);
}
}
}
// Here appendFiles is (file, file) -> (forall b. string -> f b) -> f b
// So 'string' was transformed precisely to its Yoneda embedding!
// Actually, in newer node, we can even go back from (2) to (1) with async/await, which is really just a less general version of Haskell do notation:
async function appendFiles(file1, file2) {
contents1 = await fs.readFile(file1);
contents2 = await fs.readFile(file2);
return contents1 + contents2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment