{
    "componentChunkName": "component---src-templates-blog-post-tsx",
    "path": "/blog/2018-07-03-functional-rephrasing-using-an-async-function-functor/",
    "result": {"data":{"blogPost":{"title":"Functional Rephrasing Using an Async Function Functor","slug":"/blog/2018-07-03-functional-rephrasing-using-an-async-function-functor/","authorNodes":[{"name":"Charles Lowell","slug":"/people/charles-lowell/"}],"markdown":{"html":"<p>One of my favorite things about the <a href=\"https://frontside.com/img/2018/02/19/math-is-just-another-framework.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">the math framework</a> is that it\nhelps you look for (and also find) patterns of composability around\nyou in your programming world. At the time I wrote:</p>\n<blockquote>\n<p>As you start to perceive the common nature in things like Promise, Array, and Observable, you begin to re-perceive all of the objects in your world through this new prism. You ask yourself “Is this a Functor?” and you’re shocked by how often the answer is yes. Plain JS Object? Yes. DOM Element? Yes. Express middleware? Yes. React Component? Also yes.</p>\n</blockquote>\n<p>It turns out that Functors are everywhere, and armed with\n<a href=\"https://github.com/cowboyd/funcadelic.js\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">funcadelic.js</a> at your side, you stand ready to harness their power. In\nfact, just yesterday I found just such a one: The JavaScript\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"language-text\">AsyncFunction</code></a>. And today, I'm going to show you how we can use the\nfine fact that async functions are Functors in order to refactor some\ncode to be more composable. In other words, we'll functionally\nrephrase it as a Functor.</p>\n<p>Let's say we have an async function that fetches a url for us:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">async</span> <span class=\"token keyword\">function</span> <span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">url</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">return</span> <span class=\"token keyword\">await</span> <span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span>url<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>And now we want to assemble a data transformation pipeline around\nit. For argument's sake, let's say our process will look like:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">-> get the data\n-> parse as JSON\n-> normalize the keys in the resulting json\n-> look up the canonical model in a local data store.\n</code></pre></div>\n<p>As a first pass, we could write a transform function that takes the\nurl and applies each of these steps.</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">async</span> <span class=\"token keyword\">function</span> <span class=\"token function\">transform</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">url</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">let</span> response <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> <span class=\"token function\">get</span><span class=\"token punctuation\">(</span>url<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">let</span> data <span class=\"token operator\">=</span> response<span class=\"token punctuation\">.</span><span class=\"token function\">text</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">let</span> json <span class=\"token operator\">=</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">parse</span><span class=\"token punctuation\">(</span>data<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">let</span> normalizedKeys <span class=\"token operator\">=</span> <span class=\"token function\">normalizeKeys</span><span class=\"token punctuation\">(</span>json<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">let</span> model <span class=\"token operator\">=</span> <span class=\"token function\">lookup</span><span class=\"token punctuation\">(</span>normalizedKeys<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">return</span> model<span class=\"token punctuation\">.</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>And if we wanted to stop there, life would go on. However, we could\nalso declare that <code class=\"language-text\">AsyncFunction</code> is a Functor and leverage the\nflexibility that it provides. Here is the definition of the Functor\ninstance for async functions.</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> Functor <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'funcadelic'</span>\n\n<span class=\"token comment\">// AsyncFunction is not currently a global object. :/</span>\n<span class=\"token keyword\">const</span> AsyncFunction <span class=\"token operator\">=</span> Object<span class=\"token punctuation\">.</span><span class=\"token function\">getPrototypeOf</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>constructor\n\nFunctor<span class=\"token punctuation\">.</span><span class=\"token function\">instance</span><span class=\"token punctuation\">(</span>AsyncFunction<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">fn<span class=\"token punctuation\">,</span> asyncFn</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token keyword\">async</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token operator\">...</span>args</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">return</span> <span class=\"token function\">fn</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">await</span> <span class=\"token function\">asyncFn</span><span class=\"token punctuation\">(</span><span class=\"token operator\">...</span>args<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>What this says is: whenever you map a function <code class=\"language-text\">fn</code> over an async\nfunction, what you get is a <em>new</em> async function that just invokes the\nold async function, awaits its return value, and then applies <code class=\"language-text\">fn</code> to\nit before returning.</p>\n<p>Using the <a href=\"https://github.com/cowboyd/funcadelic.js#chaining-api\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">funcadelic chaining syntax</a> this let's us define the\n<code class=\"language-text\">transform</code> method, not as a monolithic function, but as the\ncombination of a bunch of smaller functions.</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> chain <span class=\"token keyword\">as</span> $ <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'funcadelic'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> transform <span class=\"token operator\">=</span> <span class=\"token function\">$</span><span class=\"token punctuation\">(</span>get<span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">response</span> <span class=\"token operator\">=></span> response<span class=\"token punctuation\">.</span><span class=\"token function\">text</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">data</span> <span class=\"token operator\">=></span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">parse</span><span class=\"token punctuation\">(</span>data<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">json</span> <span class=\"token operator\">=></span> <span class=\"token function\">nomalizeKeys</span><span class=\"token punctuation\">(</span>json<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">normalized</span> <span class=\"token operator\">=></span> <span class=\"token function\">lookup</span><span class=\"token punctuation\">(</span>normalized<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">.</span><span class=\"token function\">valueOf</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>We start with the first async function <code class=\"language-text\">get</code>, and then map a plain function\nover it that takes the response and returns its text. The result of\nthat is an async function over which we can then map a plain function\nthat just parses the JSON. The result of that is another async\nfunction over which we can map key normalization, and so on....</p>\n<p>Just as when we declared it explicitly, <code class=\"language-text\">transform</code> is an async\nfunction because the result of mapping an async function <em>always\nreturns another async function</em>. That's <a href=\"https://github.com/cowboyd/funcadelic.js#functor\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">just how Functors work</a>.</p>\n<p>Notice also that for our mapping functions that just invoke single argument\nfunctions, we can even leave out the arguments:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> transform <span class=\"token operator\">=</span> <span class=\"token function\">$</span><span class=\"token punctuation\">(</span>get<span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">response</span> <span class=\"token operator\">=></span> response<span class=\"token punctuation\">.</span><span class=\"token function\">text</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span>parse<span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span>nomalizeKeys<span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span>lookup<span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">.</span><span class=\"token function\">valueOf</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Which ever style you choose, the neat thing is that we're building up\nan async function out of a bunch of regular plain-old JavaScript\nfunctions with nothing async about them. This gives us a lot of\nflexibility if, for example, we want to <em>add a step to the\npipline</em>.</p>\n<p>Let's say that we want to add a de-duping function in\nbetween the key normalization and the lookup from the data store. All\nwe have to do is insert it into our pipeline.</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> transform <span class=\"token operator\">=</span> <span class=\"token function\">$</span><span class=\"token punctuation\">(</span>get<span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">response</span> <span class=\"token operator\">=></span> response<span class=\"token punctuation\">.</span><span class=\"token function\">text</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span>parse<span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span>nomalizeKeys<span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span>dedupe<span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span>lookup<span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">.</span><span class=\"token function\">valueOf</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Pretty neat! But there's one more thing I have to show you, and I\nthink you're going to like it..</p>\n<p>We can use the Functor law which basically says that you can either\nmap each function individually, or you can compose them all together\nand map that function once. In other words:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> map <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'funcadelic'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> pipe <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'ramda'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">let</span> pipline <span class=\"token operator\">=</span> <span class=\"token function\">pipe</span><span class=\"token punctuation\">(</span>\n  <span class=\"token parameter\">response</span> <span class=\"token operator\">=></span> response<span class=\"token punctuation\">.</span><span class=\"token function\">text</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span>parse<span class=\"token punctuation\">,</span>\n  normalizeKeys<span class=\"token punctuation\">,</span>\n  dedupe<span class=\"token punctuation\">,</span>\n  lookup\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> transform <span class=\"token operator\">=</span> <span class=\"token function\">map</span><span class=\"token punctuation\">(</span>pipeline<span class=\"token punctuation\">,</span> get<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n</code></pre></div>\n<p>This is all not to say that there's a single way to do it. Far from\nit! But with the AsyncFunction Functor in your pocket, you've got options on your side!</p>\n<p>Photo by <a href=\"https://unsplash.com/photos/Opit9xvZDP0?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText\">Jason Blackeye</a> on <a href=\"/?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText\">Unsplash</a></p>","frontmatter":{"date":"July 03, 2018","description":"Once you know that they're there, Functors pop up in all kinds of surprising places. Here we take a simple exploration of how the JavaScript async function construct is actually a Functor and how we can use that for great good.","tags":["functional-programming","functor","funcadelic","TIL","javascript","typeclasses"],"img":{"childImageSharp":{"fixed":{"src":"/static/5c83db51eae5499a9c56557f45581b9a/a7715/2018-07-03-functional-rephrasing-using-an-async-function-functor_starry-night.jpg"}}}}}}},"pageContext":{"id":"e678036d-50c0-5ba0-b78d-555bac45c861"}},
    "staticQueryHashes": ["1241260443"]}