Last active
October 11, 2018 15:42
-
-
Save cowboyd/795a58a9f4e5280602b47270dafdfe46 to your computer and use it in GitHub Desktop.
Funcadelic typeclass implementations for AsyncFunction
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
/** | |
* There's some pretty awesome low-level composition that you can do with async functions: | |
* Check out funcadelic! https://github.com/cowboyd/funcadelic.js | |
*/ | |
import { Functor, Semigroup, Monoid } from 'funcadelic'; | |
const AsyncFunction = (async function() {}).constructor; | |
/** | |
* It's a Functor! | |
* `map` returns a new async function that awaits the | |
* result of the old async function and then applies `fn` to it. | |
*/ | |
Functor.instance(AsyncFunction, { | |
map(fn, asyncFn) { | |
return async (...args) => fn(await asyncFn(...args)); | |
} | |
}) | |
/** | |
* It's a Semigroup! | |
* `append` takes two async functions, f and g, and returns a new async function | |
* that awaits the result of g, and then awaits the result of f invoked with the result of g. | |
* In a nutshell: function composition for async functions. | |
*/ | |
Semigroup.instance(AsyncFunction, { | |
append(f, g) { | |
return async (...args) => await f(await g(...args)); | |
} | |
}) | |
/** | |
* Yup! monoid too. In this case, the zero or empty value is just the | |
* async identity function. | |
*/ | |
Monoid.instance(AsyncFunction, { | |
empty() { | |
return async x => x; | |
} | |
}) | |
/** | |
* Monad alert! flatMap invokes awaits the result of asyncFn, then | |
* applies `fn` to the result. `fn` can return a new asyncFunction, | |
* in which case, flatMap will await its return (effectively replacing itself) | |
* Otherwise, the result is the result. | |
*/ | |
Monad.instance(AsyncFunction, { | |
flatMap(fn, asyncFn) { | |
return async function(...args) { | |
let result = fn(await asyncFn(...args)); | |
if (result instanceof AsyncFunction) { | |
return await result(...args); | |
} else { | |
return result; | |
} | |
} | |
} | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment