<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Akshay's blog</title>
    <link>https://ediblemonad.dev/blog</link>
    
    <item>
  <guid>/blog/2025-07-26-ed-it.html</guid>
  <title># A case for ed</title>
  <link>https://ediblemonad.dev/blog/2025-07-26-ed-it.html</link>
  <comments>https://ediblemonad.dev/blog/2025-07-26-ed-it.html</comments>
  <pubDate>2025-07-26</pubDate>
  <description>
    <![CDATA[<h2 id="a-case-for-ed">A case for ed</h2>
<p>Can you say that you <strong>truly</strong> understand the tools you
use?</p>
<p>Text editors like vscode (or any other web browser as a text editor
things) or an IDE like intellij, are a russian doll for layers of
abstractions that you're meant to accept as a whole and never think
about. With something like vscode, there's the editor itself, all the
integrations that it comes with, the browser behind the scenes that
renders everything, some electron magic that connects that browser
internals to your system, whatever nodejs does, etc.</p>
<p>But as a programmer, that feeling is something that I've grown very
uncomfortable with. Which is partly why I've always gravitated towards
tools that are simple and let me break that abstraction and build around
it. The cost of that choice is of course that you have to trade off some
convinience to do this either as a one time investment to set it up or a
continuous cost if it's not very easy to use.</p>
<h4 id="prompt-driven-programming-before-ai">Prompt-driven programming
before AI</h4>
<p>Back in the day when people thought we'd have flying cars by the year
2025, the primary way to interact with a computer was through a teletype
interface. Not a fancy terminal emulator that allows displaying images
or one that asks you to sign-up with your email address to use your
terminal, just a regular ol' teletype terminal.</p>
<p>So an obvious choice to write code within this environment was an
editor that took commands for editing text and applied those commands on
the file. One such solution was a line-wise text editor called <a
href="https://linux.die.net/man/1/ed">ed</a>.</p>
<p>The way you edit text in ed is using commands in a repl interface
that operate on lines. You can
<strong>d</strong>elete/<strong>i</strong>nsert/<strong>a</strong>ppend/<strong>c</strong>hange/<strong>m</strong>ove/cop<strong>y</strong>
lines. If you want to change something inside a line you can use the
<strong>s</strong>ubstitute command <code>s/pattern/replacement/</code>.
There is also the <strong>g</strong>lobal command which applies one of
the other commands over all lines that match the given pattern. People
familiar with vim will already be familiar with a lot of these
commands.</p>
<h4 id="influence">Influence</h4>
<p>Not going into details of the history because if you can read this,
you can read wikipedia. But I can give you a lazy, poorly-researched
summary which is all you'll remember from wikipedia anyway.</p>
<ul>
<li>At first, there was <code>qed</code> which inspired
<code>ed</code></li>
<li>Then some dude said "want more" and went ahead and made
<code>ex</code></li>
<li>Then <code>ex</code> got a visual mode which became
<code>vi</code></li>
<li>Then came <a
href="https://en.wikipedia.org/wiki/Stevie_%28text_editor%29">stevie</a>,
a fork of vi for Atari ST</li>
<li>Then <code>vi</code> got <strong>im</strong>proved when stevie got
forked as <code>vim</code></li>
<li>Then finally we get the cool kid, neovim (<a
href="https://neovim.io/charter/">fork of vim</a>)</li>
<li>Also a side-note, almost all text editors come with a vi-mode as a
result of this chain of influence</li>
</ul>
<p>But that's not all</p>
<ul>
<li><code>sed</code> is essentially <code>ed</code>'s line-based editing
operations on streaming data (<strong>s</strong>tream
<strong>ed</strong>itor).</li>
<li><code>grep</code>'s name comes from a specific ed
<strong>g</strong>lobal command <code>g/re/p</code> which prints
everything that matches a given <strong>re</strong>gular
expression.</li>
<li>theres probably more things to add here but leaving this here
because I felt uncomfortable making a list of 2 items</li>
</ul>
<h4 id="modern-ux">Modern UX</h4>
<p>Having developed a lot of different user interfaces in my career,
I've come to the conclusion that modern user interfaces are designed for
idiots. Not saying, those interfaces are only used by idiots but they're
designed for the lowest common denominator of technologically inept.</p>
<blockquote>
<p>This button called 'Move to trash' will move your file to trash. If
you hover over it, it'll also show you a tooltip saying that it will
move your file to trash. Clicking on it will show you a dialog box
asking if you're absolutely sure that you want to move the file to
trash. If you click yes and then you realize that you want the file
back, you can go to the trash folder and restore it.</p>
</blockquote>
<p>Just <code>rm -rf</code> it, you pussy.</p>
<p>This is done not because, it's necessary but because the people
behind the tool pictured you as the worst case scenario of a user. They
imagined a user so incompetent with tech that they can't be trusted with
something they own. This reasoning is what then branches into a
justification for the lack of ownership with a lot of modern technology
but I'll leave some of this rambling to your imagination.</p>
<h4 id="simplicity">Simplicity</h4>
<p>I've always found ed to be quite elegant. Not because it's a good
tool to use but because of a very specific feeling associated with using
tools like this. Tools that are so simple that you feel like you
completely understand the underlying mechanics of it and not just as an
abstraction. You don't need a hand-wavy explanation for how it works. It
is obvious at first glance. There are a small set of primitives you
learn (commands in case of ed) and you know everything about how to use
the tool, how it works, and how to very accurately predict it's
behavior. If it breaks, it must've been a bit flip because a tool that
simple just can't break.</p>
<p>It's a breath of fresh air from all the high-level nonsense that
we've been fed all our lives in the 21st century that we learn to never
question and accept on faith. Not that far from religion, the way we
treat all the systems around us.</p>
<p>Like using a hammer. You look at it and you understand it. You don't
have to plug it into a wall. There's no installing updates to improve
security of the hammer. There's no sending usage data to some server in
the background to allow the hammer company to "improve" the tool.
Ignoring the quite likely kickstarter project doing those things, it's a
hammer. You hit things with it..</p>
<p>Most popular tools we use now are wrapped in so many layers of
abstraction that we are completely disconnected from the tools we rely
on. This trend is not acceptable to me.</p>
<h4 id="fun">Fun</h4>
<p>One of the biggest case I could make to try ed is that it's just fun.
It's an editor that feels very technical to use and provides enough
constraints to turn the experience of editing text into a turn-based
strategy game. You execute a few commands one after another, without
knowing if the edits are all correct and then you print the contents
inside ed and you feel the rush of getting it right! Or the
disappointment of forgetting to account for the added line in a previous
command.</p>
<h4 id="ai">AI</h4>
<p>We've sort of come full circle now. Prompts to edit text is back but
with the thickest layer of abstraction the world has every seen.</p>
<ul>
<li>You prompt it to make some edits, and it does that magically (among
other things).</li>
<li>You review the code (or don't if you're <em>really</em>
vibing).</li>
<li>You add it to your version control system (or don't if you're vibing
extra hard).</li>
<li>That's it. Do we really need a step here called "effort"?</li>
</ul>
<p>I cannot put into words worthy of a prompt to chatgpt, how extremely
unappealing this is to me.</p>
<p>Writing code and interacting with a computer in general has never
been a means to an end for me. That is the point. I write code because I
like writing code. Outsourcing that would be extremely pointless.</p>
<h4 id="inconclushun">Inconclushun</h4>
<p>Idk. Simple tools are fun. Bye.</p>
]]>
  </description>
</item>
<item>
  <guid>/blog/2023-02-13-ts-types-runtime.html</guid>
  <title># TypeScript's type-system as a runtime</title>
  <link>https://ediblemonad.dev/blog/2023-02-13-ts-types-runtime.html</link>
  <comments>https://ediblemonad.dev/blog/2023-02-13-ts-types-runtime.html</comments>
  <pubDate>2023-02-13</pubDate>
  <description>
    <![CDATA[<h2 id="typescripts-type-system-as-a-runtime">TypeScript's type-system
as a runtime</h2>
<blockquote>
<p>Disclaimer: The following content is not very informative</p>
</blockquote>
<p>Where were you on the night of 20th January? ANSWER ME, YOU FUCK! Not
a talker, yeah? No problem. You'll talk eventually. They all do.</p>
<p>We have an overwhelming amount of evidence that suggests that you
were the one responsible for turning typescript's type system into it's
own purely functional programming language. What kind of a sick, twisted
man, does that? You're gonna be spending a lot of time behind bars for
this.</p>
<p>The reports suggest that you can even read/write files, perform basic
io and even interop with js from it?</p>
<p>Take a look at some of the crime scene photos.</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode typescript"><code class="sourceCode typescript"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="im">export type</span> main <span class="op">=</span> [</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  PutStringLn<span class="op">&lt;</span><span class="st">&#39;Greetotron 6000 initializing...&#39;</span><span class="op">&gt;,</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>  PutString<span class="op">&lt;</span><span class="st">&#39;Your name? &#39;</span><span class="op">&gt;,</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>  Bind<span class="op">&lt;</span>ReadLine<span class="op">,</span> <span class="op">&lt;</span>name <span class="kw">extends</span> <span class="dt">string</span><span class="op">&gt;</span>() <span class="kw">=&gt;</span> PutStringLn<span class="op">&lt;</span><span class="vs">`Hello, </span><span class="sc">${</span>name<span class="sc">}</span><span class="vs">`</span><span class="op">&gt;&gt;,</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>  PutString<span class="op">&lt;</span><span class="st">&#39;Your purpose in life? &#39;</span><span class="op">&gt;,</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>  Bind<span class="op">&lt;</span>ReadLine<span class="op">,</span> HandleResponse<span class="op">&gt;,</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>  PutStringLn<span class="op">&lt;</span><span class="st">&#39;Bye bye&#39;</span><span class="op">&gt;,</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>]</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a><span class="co">// Equivalent to `HandleResponse :: string -&gt; Effect ()`</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a><span class="kw">interface</span> HandleResponse <span class="kw">extends</span> Kind1<span class="op">&lt;</span><span class="dt">string</span><span class="op">,</span> Effect<span class="op">&gt;</span> {</span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span><span class="op">:</span> Do<span class="op">&lt;</span>[</span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>    PutStringLn<span class="op">&lt;</span><span class="vs">`Interesting that you believe &quot;</span><span class="sc">${</span><span class="kw">this</span>[<span class="st">&#39;input&#39;</span>]<span class="sc">}</span><span class="vs">&quot; is your purpose. Hmmmm...`</span><span class="op">&gt;,</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>    PutStringLn<span class="op">&lt;</span><span class="st">&#39;Judging harshly...&#39;</span><span class="op">&gt;,</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>    PutStringLn<span class="op">&lt;</span><span class="st">&#39;Saving response...&#39;</span><span class="op">&gt;,</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>    WriteFile<span class="op">&lt;</span><span class="st">&#39;./response.txt&#39;</span><span class="op">,</span> <span class="kw">this</span>[<span class="st">&#39;input&#39;</span>]<span class="op">&gt;,</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>  ]<span class="op">&gt;</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
<p>Do you feel any remorse for the victims you've affected? I hope you
get the chair for this.</p>
<p>We also found the murder weapon on the crime scene -
<code>npx tsr run ./somefile.ts</code>. Not just that, it says here you
built the weapon yourself using <code>ts-morph</code> as a wrapper
around the typescript compiler. Did you use the source file as your
runtime representation of memory, you piece of shit?! But, we're getting
a bit ahead of ourselves here.</p>
<p>Let's get to the motive which is the only piece of the puzzle we're
missing. Why would a mediocre software developer suddenly go postal and
make something like this? Did someone pay you to do this? Is that what
this is about? Money? Naah. This was a little more personal than that. I
have a theory for why you did it. And it's as simple as it gets. You're
a sick man who enjoys watching people cringe and suffer. Is that what
this blog post is about? More cringe?</p>
<p>We've even figured out how you smuggled all the results of the io
back into the program. It was a result node, wasn't it? A stray object
that you injected properties into, you sick fuck. Was that your runtime
representation of memory? You just used the randomly generated property
name to access the result in your effects.</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode typescript"><code class="sourceCode typescript"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> __$result <span class="op">=</span> {</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  <span class="st">&#39;90sd9...&#39;</span><span class="op">:</span> { output<span class="op">:</span> <span class="st">&#39;Result of computation&#39;</span> }</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
<p>Another thing that's been bugging me is,</p>
<h4 id="why-is-the-effects-api-monadic">Why is the effects api
monadic?</h4>
<p>Was it because you wanted all operations on the results represented
in the type tree so you could manipulate it?</p>
<p>You disgust me. In my 20 years on the force, I've never met a man as
disturbed as you. Don't bother pleading insanity here though. This was
calculated. No one is going to buy it.</p>
<h4 id="remember-your-hacky-attempts-at-first-class-functions">Remember
your hacky attempts at first class functions?</h4>
<p>We have it in our custody and it's talking like a parrot. Telling us
everything we need to know about your sick experiments!</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode typescript"><code class="sourceCode typescript"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">interface</span> Greet <span class="kw">extends</span> Kind1<span class="op">&lt;</span><span class="dt">string</span><span class="op">,</span> <span class="dt">string</span><span class="op">&gt;</span> {</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span><span class="op">:</span> <span class="vs">`Hello, </span><span class="sc">${</span><span class="kw">this</span>[<span class="st">&#39;input&#39;</span>]<span class="sc">}</span><span class="vs">!`</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>}</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> msg <span class="op">=</span> Apply<span class="op">&lt;</span>Greet<span class="op">,</span> <span class="st">&#39;EdibleMonad&#39;</span><span class="op">&gt;</span> <span class="co">// : &#39;Hello, EdibleMonad!&#39;</span></span></code></pre></div>
<p>Yeah, we got you now, you bastard!</p>
<p>You weren't satisfied with this tho, were you? You wanted your
first-class functions to be inline. You needed it. So you made your
runtime recognize lambda functions as first-class functions.</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode typescript"><code class="sourceCode typescript"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> main <span class="op">=</span> Bind<span class="op">&lt;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>  ReadFile<span class="op">&lt;</span><span class="st">&#39;./file.txt&#39;</span><span class="op">&gt;,</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>  <span class="op">&lt;</span>T <span class="kw">extends</span> <span class="dt">string</span><span class="op">&gt;</span>() <span class="kw">=&gt;</span> PutStringLn<span class="op">&lt;</span>T<span class="op">&gt;</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span></span></code></pre></div>
<p>But this is where you fucked up. You couldn't generalize this as a
pattern because typescript doesn't work like that. Typescript doesn't
support higher kinded types, dumbass! So you settled for only allowing
this pattern inside <code>Bind</code> and <code>Try</code>. You flew too
close to the sun, Icarus and it lead us straight to you.</p>
<p>You're done, buddy. This case is as good as closed so you might as
well confess.</p>
<h4 id="alright-alright-i-confess">Alright! Alright! I confess!</h4>
<p>It was me who did it. I made the runtime that turns typescript types
into a purely functional programming language! I did it because I
fucking wanted to! And I enjoyed every second of it!</p>
<p>I saw people making things that defied all logic, like an <a
href="https://github.com/judehunter/ts-asm">assembly interpreter</a>
within the typescript type-system. I knew if I wanted to make it do
something more, I'll need a runtime! That's when I came up with my
master plan.</p>
<p>I don't regret a thing! I've made my mark on the world even if that
mark is a piss stain on the side of the street.</p>
<hr />
<blockquote>
<p>Akshay was charged with cringe and sentenced to death by lethal
injection. It was later discovered that this wasn't all that big of a
deal and completely blown out of proportion.</p>
</blockquote>
<p>Ok bye</p>
]]>
  </description>
</item>
<item>
  <guid>/blog/2021-03-01-effect-handlers.html</guid>
  <title># Designing effects as data structures</title>
  <link>https://ediblemonad.dev/blog/2021-03-01-effect-handlers.html</link>
  <comments>https://ediblemonad.dev/blog/2021-03-01-effect-handlers.html</comments>
  <pubDate>2021-03-01</pubDate>
  <description>
    <![CDATA[<h2 id="designing-effects-as-data-structures">Designing effects as data
structures</h2>
<p>You gotta teach your effects some manners.</p>
<p>We work with effects everyday, but those rascals have a habit of
running around loose in our programs. I'm not saying it's just bad
parenting but we have to draw the line at some point.</p>
<p>Look at pure functions, they are so disciplined and obedient. They
never get into any trouble. You ask them a question, they give you an
answer. That's what you expect from good code. If you find out that your
function, while giving you the answer, also went ahead and made 5 api
calls, thats a good sign that your code needs some disciplining.</p>
<hr />
<h4 id="lets-implement-a-linked-list">Let's implement a linked list</h4>
<p>I swear this is relevant and not a plot to make you learn DSA
again.</p>
<pre class="reasonml"><code>type rec myList&lt;&#39;a&gt; = Nil | Cons(&#39;a, myList&lt;&#39;a&gt;)

let ls = Cons(5, Cons(20, Cons(-28, Nil)))</code></pre>
<p>That is a simple <strong>linked list</strong> implemented in <a
href="https://rescript-lang.org/">rescript</a>. <code>Nil</code> marks
the end of the list and every element before it contains an item of that
list and the rest of the list. They know how to stand in a straight line
like good students.</p>
<p>But, this is an <strong>eager list</strong> since all items of the
list already exist on the time of its creation. For what we're working
on today, eager lists won't be enough. We need our list to be
<em>lazy</em>. We can turn that into a <strong>lazy linked list</strong>
by replacing the rest of the list with a function returning the rest of
the list like so -</p>
<pre class="reasonml"><code>type rec lazyList&lt;&#39;a&gt; = Nil | Cons(&#39;a, unit =&gt; lazyList&lt;&#39;a&gt;)

let ls = Cons(5, () =&gt;
  Cons(20, () =&gt;
    Cons(512, () =&gt;
      Nil)))</code></pre>
<p>This makes it so the rest of the linked list doesn't exist till the
function is called. This is helpful if you wanted to create an
<strong>infinite list</strong>.</p>
<pre class="reasonml"><code>let rec fibonacci = (a, b) =&gt; Cons(b, () =&gt; fibonacci(b, a + b))

let rec take = (ls, n) =&gt; switch (n, ls) {
  | (_, Nil) | (0, _) =&gt; Nil
  | (n, Cons(value, next)) =&gt; Cons(value, () =&gt; next()-&gt;take(n - 1))
}

let rec forEach = (ls, fn) =&gt; switch ls {
  | Nil =&gt; ()
  | Cons(value, next) =&gt; {
    fn(value)
    next()-&gt;forEach(fn)
  }
}

fibonacci(0, 1)-&gt;take(20)-&gt;forEach(Js.log)</code></pre>
<p><code>fibonacci</code> returns a lazy list of all the numbers in
Fibonacci series starting with <code>a</code> and <code>b</code>. We
then use the <code>take</code> function to ignore the list after the
first <code>20</code> items. <code>forEach</code>, then goes through the
new list till the 20 items and logs each one out.</p>
<p>This is very helpful for <strong>modeling continuous
sequences</strong> of data without consuming all the space it may
need.</p>
<p>Everything we've played with so far has been <em>simple</em> and
<em>pure</em>. Unlike those disobedient effects passing notes to each
other, non-deterministically. Oh I hate them so much.</p>
<hr />
<h4 id="can-effects-be-more-like-that">Can effects be more like
that?</h4>
<p>Close your eyes. No, seriously, close them. This is important. Now,
imagine a world where all your effectful code could just be designed as
<em>data structures</em>! Are your eyes still closed? Good. Something as
simple as a linked list that describes all the effectful logic in your
code. Writing tests will become fun! Everything would be so much
simpler. All of our life's problems would just disappear.</p>
<p>Well, today's yo... Oh you can open your eyes now. Sorry. Well,
today's your lucky day!</p>
<p>We will turn your ill-mannered effects into well behaved pure data
structures.</p>
<hr />
<h4 id="impure-effect-more-like-code-neglect-amirite-please-clap">Impure
effect? More like code neglect, amirite? Please clap</h4>
<p>Kids, please turn in your assignment from last week. I hope you all
implemented
<code>appendStringToFile: string =&gt; string =&gt; string</code> that
appends a string to a file and returns the new contents, given the
imaginary synchronous functions
<code>readFile: string =&gt; string</code> and
<code>writeFile: string =&gt; string =&gt; ()</code> for doing file
IO.</p>
<pre class="reasonml"><code>let appendStringToFile = (fileName, logLine) =&gt; {
  let contents = readFile(fileName)
  writeFile(contents ++ logLine)
  readFile(fileName)
}

let newLogContents = appendStringToFile(fileName, &quot;\nSome text&quot;)</code></pre>
<p>Oh my god, Timmy! Is that imperative and impure function calls in
your notebook? That's it. To the principals office! Now!</p>
<p>Now let's try to think of a way to do this that's not an absolute
nightmare to test. What if we just made a data structure out of it?</p>
<p>Let's try turning each of those statements into variants that can be
linked together lazily.</p>
<pre class="reasonml"><code>type rec fileEff&lt;&#39;a&gt; =
  | ReadFile(string, string =&gt; fileEff&lt;&#39;a&gt;)
  | WriteFile(string, string, unit =&gt; fileEff&lt;&#39;a&gt;)
  | Return(string)

let appendStringToFile = (fileName, logLine) =&gt;
  ReadFile(fileName, contents =&gt;
    WriteFile(fileName, contents ++ logLine, _ =&gt;
      ReadFile(fileName, newContents =&gt;
        Return(newContents))))</code></pre>
<p>You can read <code>Something(a, b, c =&gt; fileEff&lt;'a&gt;)</code>
as an operation <code>Something</code> that takes <code>a</code> and
<code>b</code> and returns a <code>c</code>.</p>
<p>If you squint hard enough, you'll find that this is very similar to
the <strong>lazy list</strong> data structure we implemented earlier.
You have the last item <code>Return</code>, and each item before it is a
description of an effect.</p>
<p>This is similar to how programming languages have <strong>Abstract
Syntax Trees (AST)</strong> that describe the syntax of the language
which then goes through the <strong>interpreter</strong> to be executed.
Just like ASTs, to get our code working, we need to write an interpreter
to evaluate our data structure and produce effects.</p>
<pre class="reasonml"><code>let rec interpreter = eff =&gt; switch eff {
  | Return(contents) =&gt; contents
  | ReadFile(fileName, getNext) =&gt;
    readFile(fileName)-&gt;getNext-&gt;interpreter
  | WriteFile(fileName, contents, getNext) =&gt; {
    writeFile(fileName, contents);
    ()-&gt;getNext-&gt;interpreter;
  }
}

let result = interpreter(appendStringToFile(&quot;./file&quot;, &quot;hello world&quot;));</code></pre>
<p>The interpreter walks through the list-like structure and calls
itself recursively on each of the nodes till it hits
<code>Return</code>.</p>
<p>Kevin: "Why is this better than writing it imperatively?"</p>
<p>*takes a deep breath* Kevin... STFU!</p>
<p>This is better because it <strong>decouples</strong> your
<strong>business logic</strong> from the <strong>effects</strong>! This
is better because you can just create a <strong>mock
interpreter</strong> and <strong>write tests for your business
logic</strong> without actually generating effects! This is better
because you get <strong>dependency injection</strong> for free!</p>
<hr />
<h4 id="are-we-composable-yet">Are we composable yet?</h4>
<p>Now we have a new problem though. It seems like <code>Return</code>
will have to be defined for every kind of effect we may have. This will
also make it difficult to <strong>compose</strong> it with other
effects. So let's abstract that out.</p>
<p>We can create a module function for creating effects and handling the
recursion in the interpreter.</p>
<pre class="reasonml"><code>module type EFFECT = {
  type t&lt;&#39;a&gt;
}

module MakeEffect = (Eff: EFFECT) =&gt; {
  type rec t&lt;&#39;a, &#39;ret&gt; = 
    | Return(&#39;ret)
    | Operation(Eff.t&lt;t&lt;&#39;a, &#39;ret&gt;&gt;)

  let rec interpreter = (eff, handler) =&gt; switch eff {
    | Return(x) =&gt; x
    | Operation(m) =&gt; handler(m)-&gt;interpreter(handler)
  }
}</code></pre>
<p>Then we can rewrite our file effect in peace.</p>
<pre class="reasonml"><code>module FileOperations = {
  type t&lt;&#39;a&gt; =
    | ReadFile(string, string =&gt; &#39;a)
    | WriteFile(string, string, unit =&gt; &#39;a)
}

module FileEffect = MakeEffect(FileOperations)

let appendStringToFile = (fileName, logLine) =&gt; {
  open FileOperations;
  open FileEffect;

  Operation(ReadFile(fileName, contents =&gt;
    Operation(WriteFile(fileName, contents ++ logLine, _ =&gt;
      Operation(ReadFile(fileName, contents =&gt;
        Return(contents)
      ))
    ))
  ))
}

let handler = eff =&gt; switch eff {
  | ReadFile(fileName, resume) =&gt; readFile(fileName)-&gt;resume;
  | WriteFile(fileName, contents, resume) =&gt; {
    writeFile(fileName, contents);
    resume(());
  }
}

let result = appendStringToFile-&gt;FileEffect.interpreter(handler)</code></pre>
<blockquote>
<p><strong>"Effects as a data structure is cool and all but I don't want
to write code that looks like a ladder"</strong> - Former student who
died under suspicious circumstances shortly after making this
statement</p>
</blockquote>
<p>I get it. It looks ugly. All new-born babies do. We just need some
<em>SYNTAX SUGAR</em> to make things better. Don't worry tho. I got you.
But before we go there, we need to implement a <code>flatMap</code>
operation for our effect.</p>
<p>You may know <code>flatMap</code> from it's critically acclaimed role
in <code>Belt.Option</code> and <code>Belt.Result</code> modules. Also,
the horrible <code>Js.Promise.then_</code>, is also a
<code>flatMap</code> on promises. In general,
<code>flatMap: t&lt;'a&gt; =&gt; ('a =&gt; t&lt;'b&gt;) =&gt; t&lt;'b&gt; </code>
allows us to chain <code>t&lt;'a&gt;</code> to <code>t&lt;'b&gt;</code>
using the result of <code>t&lt;'a&gt;</code>.</p>
<pre class="reasonml"><code>// This is a map operation over our file operation
let fileOpsMap = (eff, fn) =&gt; switch eff {
  | ReadFile(f, next) =&gt; ReadFile(f, e =&gt; e-&gt;next-&gt;fn)
  | WriteFile(f, c, next) =&gt; WriteFile(f, c, e =&gt; e-&gt;next-&gt;fn)
}

// This function allows us to chain our effects together
let rec flatMap = (eff, fn) =&gt; switch eff {
  | Return(a) =&gt; fn(a)
  | Eff(m) =&gt; Eff(m-&gt;fileOpsMap(flatMap(_, fn)))
}</code></pre>
<p>While we're at it, we'll also need another function called
<code>liftEff</code>. This function <strong>lifts</strong> any given
operation into an <code>Effect</code> and makes it terminate with its
result. <code>x =&gt; next effect?</code> becomes
<code>Eff(x =&gt; Return(x))</code></p>
<pre class="reasonml"><code>let liftEff = fa =&gt; Eff(fa-&gt;fileOpsMap(e =&gt; Return(e)));</code></pre>
<p>Now putting it all together, our effects helper and file effect will
look something like this</p>
<pre class="reasonml"><code>module type EFFECT = {
  type rec t&lt;&#39;a&gt;;
  let map : t&lt;&#39;a&gt; =&gt; (&#39;a =&gt; &#39;b) =&gt; t&lt;&#39;b&gt;;
};

module MakeEffect = (Eff: EFFECT) =&gt; {
  type rec t&lt;&#39;a&gt; = 
    | Return(&#39;a)
    | Eff(Eff.t&lt;t&lt;&#39;a&gt;&gt;);

  let liftEff = fa =&gt; Eff(fa-&gt;Eff.map(e =&gt; Return(e)));

  let rec flatMap = (eff, fn) =&gt; switch eff {
    | Return(a) =&gt; fn(a)
    | Eff(m) =&gt; Eff(m-&gt;Eff.map(flatMap(_, fn)))
  };

  let rec interpreter = (eff, handler) =&gt; switch eff {
    | Return(x) =&gt; x
    | Eff(m) =&gt; handler(m)-&gt;interpreter(handler)
  };
};

module FileOperations = {
  type rec t&lt;&#39;a&gt; =
    | ReadFile(string, string =&gt; &#39;a)
    | WriteFile(string, string, unit =&gt; &#39;a);

  let map = (eff, fn) =&gt; switch eff {
    | ReadFile(f, next) =&gt; ReadFile(f, e =&gt; e-&gt;next-&gt;fn)
    | WriteFile(f, c, next) =&gt; WriteFile(f, c, e =&gt; e-&gt;next-&gt;fn)
  };
};

module FileEffect = MakeEffect(FileOperations);

// Lifted helper functions
let readFileOp = file =&gt;
  FileEffect.liftEff(FileOperations.ReadFile(file, x =&gt; x));

let writeFileOp = (file, contents) =&gt;
  FileEffect.liftEff(FileOperations.WriteFile(file, contents, x =&gt; x));</code></pre>
<p>Now for the <em>SYNTAX SUGAR</em> I promised!</p>
<pre class="reasonml"><code>let appendStringToFile = (fileName, logLine) =&gt; {
  open FileEffect;

  readFileOp(fileName)
  -&gt;flatMap(contents =&gt; writeFileOp(fileName, contents ++ logLine))
  -&gt;flatMap(_ =&gt; readFileOp(fileName))
};</code></pre>
<p>We have turned our <code>FileOperations</code> into a functor</p>
<hr />
<h4 id="no-not-that-functor-the-other-functor">No, not that functor, the
other functor.</h4>
<p>Functors in ocaml (<a
href="https://rescript-lang.org/docs/manual/latest/module#module-functions-functors">module
functions</a>) are very different from functors in category theory.</p>
<p>What we have made here is a combination of both kinds of functors.
The <code>FileOperations</code> <strong>functor</strong> (category
theory) goes into the <code>MakeEffect</code> <strong>functor</strong>
(module function) and returns <code>FileEffect</code>
<strong>monad</strong> (category theory).</p>
<blockquote>
<p>Fun fact: Functor comes from the contraction of, fun which is Russian
for vodka, ca which of course is the sound a crow makes and tor which is
a modern tin foil hat that actually works.</p>
</blockquote>
<blockquote>
<p>Fun fact: Monad comes from the mind of a mathematician who forgot
about the essay that was due, so at the last minute, started making up
words to fill up the 800 words.</p>
</blockquote>
<p>Don't quote me on that but it's probably true. We'll never know.</p>
<p>We don't have to get into the specifics of functors and monads to
make sense of this class but it is worth the learning curve.</p>
<hr />
<h4 id="ugh-unit-tests">Ugh.. Unit tests</h4>
<p>Writing tests for it is as simple as creating <strong>a mock
handler</strong>.</p>
<pre class="reasonml"><code>let mockFile = ref(&quot;init:&quot;);
let mockHandler = eff =&gt; switch eff {
  | FileOperations.ReadFile(fileName, resume) =&gt; resume(mockFile.contents);
  | FileOperations.WriteFile(fileName, contents, resume) =&gt; {
    mockFile.contents = contents;
    resume(());
  };
};

let result = appendStringToFile(&quot;./file&quot;, &quot;text to append&quot;)
  -&gt;FileEffect.interpreter(mockHandler);

expect.string(result).toEqual(&quot;init:text to append&quot;);
expect.string(mockFile.contents).toEqual(&quot;init:text to append&quot;);</code></pre>
<p>And now for the best part... <em>drum rolls</em></p>
<p><strong>SNAPSHOT/GOLDEN TESTING</strong></p>
<p>Yes! As all our business logic is now just a data structure, you can
create a snapshot of it to test against!</p>
<p>You can perform snapshot testing of your effect by
<strong>accumulating the effects</strong> called on your handler as an
array.</p>
<pre class="reasonml"><code>let nodes = ref([]-&gt;Obj.magic);
let addNode = node =&gt; nodes.contents = nodes.contents-&gt;Belt.Array.concat([node]);

let mockHandler = eff =&gt; {
  addNode(eff);
  switch eff {
    | FileOperations.ReadFile(_f, resume) =&gt; resume(&quot;mock file contents&quot;)
    | FileOperations.WriteFile(_f, _c, resume) =&gt; resume(())
  };
};

appendStringToFile(&quot;./file&quot;, &quot;text to append&quot;)-&gt;FileEffect.interpreter(mockHandler)-&gt;ignore;

expect.value(nodes).toMatchSnapshot();</code></pre>
<p>And just like that, all of our business logic is now 100% safe
against all kinds of refactor.</p>
<ul>
<li>You change the order of effects?... Tests break!</li>
<li>You add another effect in between?... Tests break!</li>
<li>You accidentally delete everything?... Tests explodes!</li>
<li>You got scammed by a Nigerian prince?... This won't help with
that!</li>
<li>You change something that doesn't impact your program?... Tests
pass!</li>
</ul>
<hr />
<h4 id="effect-composition">Effect composition</h4>
<p>File IO is great but your code will involve other effects too. Maybe
you want to implement <strong>logging</strong>? Or maybe some
<strong>caching</strong> mechanism? Or maybe you just want to maintain a
piece of <strong>mutable state</strong> in your code? Just having one
effect called <code>FileEffect</code> is not gonna cut it.</p>
<p>To be able to compose multiple effects into one big effect, we can
use the almighty <a
href="https://rescript-lang.org/docs/manual/latest/polymorphic-variant">STRUCTURAL/POLYMORPHIC
VARIANTS</a>!</p>
<pre class="reasonml"><code>// File IO effect
module FileOperations = {
  type rec t&lt;&#39;a&gt; = [ #ReadFile(string, string =&gt; &#39;a) | #WriteFile(string, string, unit =&gt; &#39;a) ];

  let map = (eff, fn) =&gt; switch eff {
    | #ReadFile(f, next) =&gt; #ReadFile(f, e =&gt; e-&gt;next-&gt;fn)
    | #WriteFile(f, c, next) =&gt; #WriteFile(f, c, e =&gt; e-&gt;next-&gt;fn)
  };
};

// Logger effect
module LoggerOperations = {
  type rec t&lt;&#39;a&gt; = [ #LogMessage(string, string, string =&gt; &#39;a) ];

  let map = (eff, fn) =&gt; switch eff {
    | #LogMessage(m, d, next) =&gt; #LogMessage(m, d, e =&gt; e-&gt;next-&gt;fn)
  };
};

// Composition of FileOperations and LoggerOperations
module MyCustomOperations = {
  type rec t&lt;&#39;a&gt; = [ LoggerOperations.t&lt;&#39;a&gt; | FileOperations.t&lt;&#39;a&gt; ];

  let map = eff =&gt; switch eff {
    | #...FileOperations.t as e =&gt; FileOperations.map(e)
    | #...LoggerOperations.t as e =&gt; LoggerOperations.map(e)
  };
};

module MyCustomEff = MakeEffect(MyCustomOperations);

let logMessageOp = (message, data) =&gt; MyCustomEff.liftEff(#LogMessage(message, data, x =&gt; x));
let readFileOp = file =&gt; MyCustomEff.liftEff(#ReadFile(file, x =&gt; x));
let writeFileOp = (file, contents) =&gt; MyCustomEff.liftEff(#WriteFile(file, contents, x =&gt; x));

// Our program
let appendStringToFile = (fileName, logLine) =&gt; {
  open MyCustomEff;

  readFileOp(fileName)
  -&gt;flatMap(logMessageOp(&quot;:: Logging file contents before update -&quot;))
  -&gt;flatMap(contents =&gt; writeFileOp(fileName, contents ++ logLine))
  -&gt;flatMap(_ =&gt; readFileOp(fileName))
  -&gt;flatMap(logMessageOp(&quot;:: Logging file contents after update -&quot;))
};</code></pre>
<p>You can <strong>compose any number of effects</strong> together into
one for your programs!</p>
<p>And of course, nothing would work without the handler so...</p>
<pre class="reasonml"><code>let handler = eff =&gt; switch eff {
  | #LogMessage(message, data, resume) =&gt; {
    Js.log2(message, data);
    resume(data);
  }
  | #ReadFile(fileName, resume) =&gt; readFile(fileName)-&gt;resume;
  | #WriteFile(fileName, contents, resume) =&gt; {
    writeFile(fileName, contents);
    resume(());
  };
};

let result = appendStringToFile-&gt;MyCustomEff.interpreter(handler);</code></pre>
<hr />
<h4 id="does-all-of-this-have-a-name">Does all of this have a name?</h4>
<p>What we just learned is a construct in functional programming called
<a href="https://wiki.haskell.org/Free_structure">free algebraic
structures</a>. More specifically, <code>FileEffect</code> and
<code>MyCustomEff</code> are Free Monads.</p>
<p>In general, a free monad on a Functor <code>f</code> is a structure
where each node represents <code>f</code>. If you understood what I just
said, please explain it to me after class so I don't look like an idiot
in front of my other students.</p>
<p>In this class, we used it to <strong>fold</strong> (interpret) a data
structure to generate effects. It allowed us to decouple the composition
of our effects with the effect's behavior by creating a pure
representation of our computations.</p>
<p>Free monad implementation for dealing with effects in such a way is
also referred to as <a
href="https://overreacted.io/algebraic-effects-for-the-rest-of-us/">algebraic
effects</a>.</p>
<p>To learn more about this, you could walk through the following links
-</p>
<ul>
<li><a
href="https://rescript-lang.org/docs/manual/latest/module#module-functions-functors">What
the fuck are module functions/functors?</a></li>
<li><a
href="https://medium.com/@dtinth/what-is-a-functor-dcf510b098b6">What
the fuck is a Functor in category theory?</a></li>
<li><a href="https://wiki.haskell.org/All_About_Monads">What the fuck is
a Monad?</a></li>
<li><a href="https://wiki.haskell.org/Free_structure">What the fuck are
Free Algebraic Structures?</a></li>
<li><a
href="https://overreacted.io/algebraic-effects-for-the-rest-of-us/">What
the fuck are algebraic effects?</a></li>
</ul>
<hr />
<h4 id="report-card">Report card</h4>
<p>Our jobs as programmers is to create as many
<strong>guarantees</strong> in our code as possible. To achieve this, we
should always try to design things in a way that pushes everything we
can't guarantee to the edges.</p>
<p>This not only reduces the <strong>surface area for bugs</strong>, but
also reduces the <strong>mental overhead</strong> to the person reading
the code.</p>
<p>This is why we should always try to minimize the surface area of
impurity in our code.</p>
<p>With free monads, we create a guarantee that our business logic is
sound and we push the effects to the edge in the form of our interpreter
since we may not be able to guarantee the correctness of effectful
behavior.</p>
<p>Anyways, impure programs get a C for "Can do better". Almost-pure
programs with Free monads, get an A for "Aahaaa, functional programming
wins again".</p>
<p>Alright kids, get a signature on the report card from your parents.
No fake signatures, John. Those squiggly lines aren't fooling
anyone.</p>
]]>
  </description>
</item>
<item>
  <guid>/blog/2019-03-29-js-magic.html</guid>
  <title># JS Magic Tricks to impress your friends</title>
  <link>https://ediblemonad.dev/blog/2019-03-29-js-magic.html</link>
  <comments>https://ediblemonad.dev/blog/2019-03-29-js-magic.html</comments>
  <pubDate>2019-03-29</pubDate>
  <description>
    <![CDATA[<h2 id="js-magic-tricks-to-impress-your-friends">JS Magic Tricks to
impress your friends</h2>
<p>My name is Houdini J.S. Magnifico. What I'm about to perform here are
a set of illusions and magic tricks that are sure to blow your mind! So
prepare to be amazed!</p>
<blockquote>
<p>The tricks shown here are performed by trained professionals. Do not
attempt these stunts at home. Do it in production. Viewer discretion is
advised.</p>
</blockquote>
<p>Let the show begin!</p>
<hr />
<h4 id="for-my-first-trick-i-will-make-this-function-disappear">For my
first trick, I will make this function… DISAPPEAR!</h4>
<p>This is my totally normal function. Nothing weird about it. A
function you'd find in the wild.</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">typeof</span> innocentTotallyNormalFunction <span class="op">===</span> <span class="st">&quot;function&quot;</span> <span class="co">// &gt; true</span></span></code></pre></div>
<p>Let me just wave Brendan Eich's mouse pad over it for a bit… and…
BOOM!</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="fu">innocentTotallyNormalFunction</span>()</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="co">// &gt; Uncaught TypeError: innocentTotallyNormalFunction is not a function</span></span></code></pre></div>
<p>GONE! The function is not a function anymore. Schrodinger's function
has dissappeared!</p>
<p><strong><em>audience applauds</em></strong></p>
<p>Thank you! Thank you!</p>
<h5 id="heres-how-it-works">Here's how it works</h5>
<div class="sourceCode" id="cb3"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> innocentTotallyNormalFunction <span class="op">=</span> (() <span class="kw">=&gt;</span> {})<span class="op">.</span><span class="at">apply</span><span class="op">.</span><span class="fu">bind</span>()<span class="op">;</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="co">// Works with any method&#39;s bind();</span></span></code></pre></div>
<p>Weird right? It's called JavaScript and a lot of people use this in
production. The reason this doesn't work is because .apply method
expects the context of a function but .bind gives it undefined as the
context. this.means that the apply method doesn't know which function it
is trying to apply. Then the apply method has an identity crisis and
everything goes to shit.</p>
<hr />
<h4 id="magic-list">Magic list</h4>
<p>Here I have a function that clones an array. Perfectly normal,
production ready code.</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> clone <span class="op">=</span> list <span class="kw">=&gt;</span> list<span class="op">.</span><span class="fu">reduce</span>((newList<span class="op">,</span> item) <span class="kw">=&gt;</span> [<span class="op">...</span>newList<span class="op">,</span> item]<span class="op">,</span> [])<span class="op">;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="co">// Another clone implementation you can use is,</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> clone <span class="op">=</span> <span class="bu">Object</span><span class="op">.</span><span class="at">values</span><span class="op">;</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a><span class="co">// Or if you wanna go old school...</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> clone <span class="op">=</span> list <span class="kw">=&gt;</span> {</span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">const</span> newList <span class="op">=</span> []<span class="op">;</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span>(<span class="kw">let</span> index <span class="kw">in</span> list) {</span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>    newList<span class="op">.</span><span class="fu">push</span>(list[index])<span class="op">;</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>  }</span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> newList<span class="op">;</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a>}<span class="op">;</span></span></code></pre></div>
<p>Here's an ordinary list with nothing fishy going on inside</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>array<span class="op">.</span><span class="at">length</span> <span class="co">// &gt; 23</span></span></code></pre></div>
<p>I'm just gonna casually use the clone function to copy the list and
check the length of the newly created list…</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="fu">clone</span>(array)<span class="op">.</span><span class="at">length</span> <span class="co">// &gt; 1</span></span></code></pre></div>
<p><strong>Magic!!</strong></p>
<p>The list is no longer 23 items long. 23 to 1! Next-gen compression
algorithm, question mark? Or is it just magic?</p>
<h5 id="well-heres-how-it-all-went-down">Well, here's how it all went
down</h5>
<p>The concept behind this is one that not many developers are familiar
with. Array holes, also called empty slots are points in an array that
are empty. No, I'm not talking about undefined or null or 0. Just
empty.</p>
<p>Ref: <a href="https://2ality.com/2015/09/holes-arrays-es6.html">Array
holes/empty slots</a>, <a
href="https://2ality.com/2012/06/dense-arrays.html">Sparse
arrays</a></p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="bu">Array</span>(<span class="dv">5</span>) <span class="co">// &gt; [&lt;empty x 5&gt;]</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="co">// OR</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>[<span class="op">,,,,,</span>] <span class="co">// &gt; [&lt;empty x 5&gt;]</span></span></code></pre></div>
<p>This creates an array of 5 items but without any values. But
javascript doesn't use undefined as the default values tho. It instead
creates empty slots (holes) in the arrays but keeps given the length. So
when you copy it using the reduce method, it doesn't iterate over the
empty slots. So the newly generated array is shorter.</p>
<hr />
<h4 id="schrodingers-magic-list">Schrodinger's magic list</h4>
<p>The list we are gonna be working on is document.all which is a list
of all nodes in a document.</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="bu">document</span><span class="op">.</span><span class="at">all</span> <span class="co">// &gt; HTMLAllCollection {...}</span></span></code></pre></div>
<p>Council of W3C, give me the strength to make this list disappear!!!
Boom! Shaa! Waka-Waka Boom!</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">typeof</span> <span class="bu">document</span><span class="op">.</span><span class="at">all</span> <span class="co">// &gt; undefined</span></span></code></pre></div>
<p><strong><em>Be Amazed!!</em></strong></p>
<p>Go get an MRI scan because your tiny little brain just exploded!</p>
<h5 id="heres-the-big-reveal">Here's the big reveal!</h5>
<p><code>document.all</code> is a very old and deprecated api that
allowed you to iterate over all the nodes rendered to the DOM. The
typeof expression returning <code>undefined</code> was by design as a
part of deprecation of that non-standard feature. Weird, I know. But
that's just how javascript rolls.</p>
<hr />
<h4 id="are-we-infinity-yet">Are we Infinity yet?</h4>
<p>Let's take a number, <code>let x: number</code>.</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>x <span class="op">+</span> <span class="dv">1</span> <span class="op">===</span> x<span class="op">;</span> <span class="co">// &gt;&gt; true</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>x <span class="op">+</span> <span class="dv">2</span> <span class="op">===</span> x<span class="op">;</span> <span class="co">// &gt;&gt; false</span></span></code></pre></div>
<p>“What just happened?”</p>
<p>I added 1 to x and the value didn't change! Then I added 2 to it and…
the universe… it changed.</p>
<h5 id="check-out-how-this-works">Check out how this works</h5>
<div class="sourceCode" id="cb11"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> x <span class="op">=</span> <span class="fl">1e16</span><span class="op">;</span> <span class="co">// OR 1 * Math.pow(10, 16) OR 10000000000000000</span></span></code></pre></div>
<p>This is by design. It's documented in IEEE 754-2008. When the number
is as large as this, it rounds it up to the nearest even number.</p>
<p>Ref: <a
href="https://en.wikipedia.org/wiki/IEEE_754#Rounding_rules">Rounding
rules section in IEEE 754</a></p>
<hr />
<h4
id="is-a-not-a-number-a-number-or-not-a-number-well-its-nan-of-your-business">Is
a “not a number” a number or not a number? Well, it's NaN of your
business</h4>
<div class="sourceCode" id="cb12"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">typeof</span> <span class="kw">NaN</span> <span class="op">===</span> <span class="st">&#39;number&#39;</span> <span class="co">// &gt;&gt; true</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="kw">NaN</span> <span class="op">!==</span> <span class="kw">NaN</span> <span class="co">// &gt;&gt; true</span></span></code></pre></div>
<p>Wut? ‘Not a number' is a number and ‘Not a number' is not equal to
‘Not a number'</p>
<p>Javascript is a magical language</p>
<h5 id="know-the-trick">Know the trick</h5>
<p>NaN is a numeric data type but it behaves as an identity when any
mathematical operation is applied to it.</p>
<p><em>“But why is NaN === NaN returning false?”</em></p>
<p>Because the Gods of Javascript wished so. If either side of ===
operator is NaN, the operation returns false. Thats just how it works.
Don't question it.</p>
<hr />
<h4 id="check-if-your-list-has-more-than-1-items">Check if your list has
more than 1 items</h4>
<p>A very complicated problem in programming.</p>
<p>A normie dev would go ahead and write something like</p>
<div class="sourceCode" id="cb13"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> hasAtleast2Elements <span class="op">=</span> x <span class="kw">=&gt;</span> x<span class="op">.</span><span class="at">length</span> <span class="op">&gt;=</span> <span class="dv">2</span><span class="op">;</span></span></code></pre></div>
<p>That solution is 13 characters long. In the modern world of
javascript, 13 characters is way too many characters. It is a
performance bottleneck.</p>
<p>Let's write something more optimized in size</p>
<div class="sourceCode" id="cb14"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> hasAtleast2Elements <span class="op">=</span> x <span class="kw">=&gt;</span> <span class="op">!</span><span class="pp">isNaN</span>(<span class="op">+</span>x)<span class="op">;</span></span></code></pre></div>
<p>There. 10 characters. Much better. We removed <strong>23%</strong> of
our JavaScript! Good job. Less JavaScript is good JavaScript</p>
<h5 id="the-genius-behind-this-action">The genius behind this
action</h5>
<p>We improved our load time by 23% but at what cost?! How does that
function even work? Magic? Not magic, JavaScript!</p>
<p>The + operator applied to a list returns NaN if the number of items
in the list is more than 1.</p>
<p>Why does it do that? Well, type casting. +[] is equal to
+[].toString().</p>
<p>So,</p>
<div class="sourceCode" id="cb15"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a>[]<span class="op">.</span><span class="fu">toString</span>() <span class="op">===</span> <span class="st">&#39;&#39;</span> <span class="co">// &gt;&gt; +&#39;&#39; === 0</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>[<span class="dv">1</span>]<span class="op">.</span><span class="fu">toString</span>() <span class="op">===</span> <span class="st">&#39;1&#39;</span> <span class="co">// &gt;&gt; +&#39;1&#39; === 1</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>[<span class="dv">1</span><span class="op">,</span> <span class="dv">2</span>]<span class="op">.</span><span class="fu">toString</span>() <span class="op">===</span> <span class="st">&#39;1,2&#39;</span> <span class="co">// &gt;&gt; +&#39;1,2&#39; === NaN (Cannot typecast as it is not a number)</span></span></code></pre></div>
<hr />
<hr />
<p>That's all for today! Tune in next time to watch Magnifico use magic
in production and get fired immediately.</p>
<p>Now I'm gonna make myself disappear.</p>
<p>…</p>
<p>…</p>
<p>…</p>
<p>Why is this… Just a second folks… Some technical difficul…</p>
<p><strong><em>magic man magically disappears</em></strong></p>
]]>
  </description>
</item>
<item>
  <guid>/blog/2019-03-15-redux-recipies.html</guid>
  <title># Grandma's recipes for cooking redux</title>
  <link>https://ediblemonad.dev/blog/2019-03-15-redux-recipies.html</link>
  <comments>https://ediblemonad.dev/blog/2019-03-15-redux-recipies.html</comments>
  <pubDate>2019-03-15</pubDate>
  <description>
    <![CDATA[<h2 id="grandmas-recipes-for-cooking-redux">Grandma's recipes for
cooking redux</h2>
<p>Welcome to my Grandma's Kitchen. I'm your host, the grandson. Let's
start cooking, shall we?</p>
<p>Disclaimer: Stuff referenced in this post are not my opinions, they
are straight up facts. If you disagree, you're probably right but don't
tell anyone. Reader discretion is advised.</p>
<p>For far too long have we suffered the torture of writing boilerplate
code and messy actions. Not anymore. Here are some recipes to cook redux
the way my grandma wants you to.</p>
<p>We are going to be cooking with the following ingredients today -</p>
<ul>
<li><a href="https://github.com/redux-saga/redux-saga">Redux
Saga</a></li>
<li><a href="https://github.com/phenax/redux-utils">Redux Utils</a></li>
<li><a href="https://github.com/evilsoft/crocks">Crocks</a></li>
<li><a href="https://github.com/reduxjs/reselect">Reselect</a></li>
<li><a href="https://github.com/ramda/ramda">Ramda</a> (optional. Add
according to taste)</li>
</ul>
<hr />
<h4 id="spicy-hot-action-namestypes">Spicy hot action names/types</h4>
<p>You wouldn't expect there to be any changes in the way you create
action names/types but why not? Go check your action types file. You
will find that there is a recurring pattern of the three states.
<code>ACTION_PENDING</code>, <code>ACTION_SUCCESS</code> and
<code>ACTION_FAILURE</code> (not FAIL because <code>PENDING</code>,
<code>SUCCESS</code> and <code>FAILURE</code> have the same number of
characters and my grandma likes consistency). And while we are at it we
can also learn something from the REST architecture from my grandma's
time and bring the resource/action pattern in here.</p>
<p><code>actionTypes</code> function uses the
<code>@resource/ACTION/STATE</code> convention.</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> { actionTypes } <span class="im">from</span> <span class="st">&#39;@phenax/redux-utils&#39;</span><span class="op">;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> types <span class="op">=</span> <span class="fu">actionTypes</span>({</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">DISHES</span><span class="op">:</span> {</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">LIST</span><span class="op">:</span> [<span class="st">&#39;PENDING&#39;</span><span class="op">,</span> <span class="st">&#39;SUCCESS&#39;</span><span class="op">,</span> <span class="st">&#39;FAILURE&#39;</span>]<span class="op">,</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    <span class="dt">ADD</span><span class="op">:</span> [<span class="st">&#39;PENDING&#39;</span><span class="op">,</span> <span class="st">&#39;SUCCESS&#39;</span><span class="op">,</span> <span class="st">&#39;FAILURE&#39;</span>]<span class="op">,</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>  }<span class="op">,</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>  <span class="dt">SESSION</span><span class="op">:</span> {</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>    <span class="dt">INIT</span><span class="op">:</span> [<span class="st">&#39;PENDING&#39;</span><span class="op">,</span> <span class="st">&#39;SUCCESS&#39;</span><span class="op">,</span> <span class="st">&#39;FAILURE&#39;</span>]<span class="op">,</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>  }<span class="op">,</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>})<span class="op">;</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>types<span class="op">.</span><span class="at">DISHES</span><span class="op">.</span><span class="at">ADD</span><span class="op">.</span><span class="at">SUCCESS</span> <span class="op">===</span> <span class="st">&#39;@dishes/ADD/SUCCESS&#39;</span><span class="op">;</span> <span class="co">// true</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a><span class="co">// Your actions will then look something like</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a><span class="fu">dispatch</span>({</span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>  <span class="dt">type</span><span class="op">:</span> types<span class="op">.</span><span class="at">DISHES</span><span class="op">.</span><span class="at">ADD</span><span class="op">.</span><span class="at">_</span><span class="op">,</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>  <span class="dt">payload</span><span class="op">:</span> {</span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>    <span class="dt">name</span><span class="op">:</span> <span class="st">&#39;Chicken that tastes like paneer&#39;</span><span class="op">,</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>    <span class="dt">ingredients</span><span class="op">:</span> {</span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>      <span class="dt">chicken</span><span class="op">:</span> { <span class="dt">count</span><span class="op">:</span> <span class="dv">1</span><span class="op">,</span> <span class="dt">unit</span><span class="op">:</span> <span class="st">&#39;bird&#39;</span> }<span class="op">,</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>      <span class="dt">salt</span><span class="op">:</span> { <span class="dt">toTaste</span><span class="op">:</span> <span class="kw">true</span> }<span class="op">,</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>      <span class="dt">pepper</span><span class="op">:</span> { <span class="dt">count</span><span class="op">:</span> <span class="dv">2</span><span class="op">,</span> <span class="dt">unit</span><span class="op">:</span> <span class="st">&#39;shakes&#39;</span> }<span class="op">,</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>      <span class="dt">milk</span><span class="op">:</span> { <span class="dt">count</span><span class="op">:</span> <span class="dv">3</span><span class="op">,</span> <span class="dt">unit</span><span class="op">:</span> <span class="st">&#39;seconds of pouring&#39;</span> }<span class="op">,</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a>    }<span class="op">,</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a>  }<span class="op">,</span></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a>})<span class="op">;</span></span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a><span class="co">// The underescore (`._`) is the dispatch that gets picked up by the sagas. Its a default dispatch i.e. stateless dispatch.</span></span></code></pre></div>
<hr />
<h4 id="reducer-salad">Reducer salad</h4>
<p>The three state pattern is also seen repeated a lot inside reducers.
My grandma keeps telling me “My back hurts when I scroll through long
switch-case statements”. So if you haven't guessed already, we are going
to change that too now. We have to care for the elderly.</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> { createPartialReducer<span class="op">,</span> mergeReducers } <span class="im">from</span> <span class="st">&#39;@phenax/redux-utils&#39;</span><span class="op">;</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> initialState <span class="op">=</span> { <span class="dt">loading</span><span class="op">:</span> <span class="kw">false</span><span class="op">,</span> <span class="dt">readyForServing</span><span class="op">:</span> <span class="kw">true</span><span class="op">,</span> <span class="dt">dishes</span><span class="op">:</span> []<span class="op">,</span> <span class="dt">error</span><span class="op">:</span> <span class="st">&quot;&quot;</span> }<span class="op">;</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> getLoadingState <span class="op">=</span> state <span class="kw">=&gt;</span> ({ readyForServing }) <span class="kw">=&gt;</span> ({</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">...</span>state<span class="op">,</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>  readyForServing<span class="op">,</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>  <span class="dt">loading</span><span class="op">:</span> <span class="kw">true</span><span class="op">,</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>})<span class="op">;</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> addDishReducer <span class="op">=</span> <span class="fu">createPartialReducer</span>(types<span class="op">.</span><span class="at">DISHES</span><span class="op">.</span><span class="at">ADD</span><span class="op">,</span> (state <span class="op">=</span> initialState<span class="op">,</span> action) <span class="kw">=&gt;</span> ({</span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>  <span class="dt">PENDING</span><span class="op">:</span> <span class="fu">getLoadingState</span>(state)<span class="op">,</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>  <span class="dt">SUCCESS</span><span class="op">:</span> newDish <span class="kw">=&gt;</span> ({</span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">...</span>state<span class="op">,</span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>    <span class="dt">readyForServing</span><span class="op">:</span> <span class="kw">true</span><span class="op">,</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>    <span class="dt">loading</span><span class="op">:</span> <span class="kw">true</span><span class="op">,</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a>    <span class="dt">dishes</span><span class="op">:</span> [<span class="op">...</span>state<span class="op">.</span><span class="at">dishes</span><span class="op">,</span> newDish]<span class="op">,</span></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a>  })<span class="op">,</span></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a>  <span class="dt">FAILURE</span><span class="op">:</span> e <span class="kw">=&gt;</span> ({</span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">...</span>state<span class="op">,</span></span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a>    <span class="dt">readyForServing</span><span class="op">:</span> <span class="kw">false</span><span class="op">,</span></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a>    <span class="dt">loading</span><span class="op">:</span> <span class="kw">true</span><span class="op">,</span></span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a>    <span class="dt">error</span><span class="op">:</span> e<span class="op">.</span><span class="at">message</span><span class="op">,</span></span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a>  })<span class="op">,</span></span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a>}))<span class="op">;</span></span>
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-27"><a href="#cb2-27" aria-hidden="true" tabindex="-1"></a><span class="co">// Your regular reducer can be merged with partials</span></span>
<span id="cb2-28"><a href="#cb2-28" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> regularOldReducer <span class="op">=</span> (state <span class="op">=</span> initialState<span class="op">,</span> action) <span class="kw">=&gt;</span> {</span>
<span id="cb2-29"><a href="#cb2-29" aria-hidden="true" tabindex="-1"></a>  <span class="cf">switch</span>(action<span class="op">.</span><span class="at">type</span>) {</span>
<span id="cb2-30"><a href="#cb2-30" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> types<span class="op">.</span><span class="at">SOMEOTHER</span><span class="op">.</span><span class="at">ACTION</span><span class="op">.</span><span class="at">PENDING</span><span class="op">:</span></span>
<span id="cb2-31"><a href="#cb2-31" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> {</span>
<span id="cb2-32"><a href="#cb2-32" aria-hidden="true" tabindex="-1"></a>        <span class="op">...</span>state<span class="op">,</span></span>
<span id="cb2-33"><a href="#cb2-33" aria-hidden="true" tabindex="-1"></a>        <span class="dt">loading</span><span class="op">:</span> <span class="kw">true</span><span class="op">,</span></span>
<span id="cb2-34"><a href="#cb2-34" aria-hidden="true" tabindex="-1"></a>      }<span class="op">;</span></span>
<span id="cb2-35"><a href="#cb2-35" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> types<span class="op">.</span><span class="at">SOMEOTHER</span><span class="op">.</span><span class="at">ACTION</span><span class="op">.</span><span class="at">SUCCESS</span><span class="op">:</span></span>
<span id="cb2-36"><a href="#cb2-36" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> {</span>
<span id="cb2-37"><a href="#cb2-37" aria-hidden="true" tabindex="-1"></a>        <span class="op">...</span>state<span class="op">,</span></span>
<span id="cb2-38"><a href="#cb2-38" aria-hidden="true" tabindex="-1"></a>        <span class="dt">loading</span><span class="op">:</span> <span class="kw">false</span><span class="op">,</span></span>
<span id="cb2-39"><a href="#cb2-39" aria-hidden="true" tabindex="-1"></a>        <span class="dt">dishes</span><span class="op">:</span> []<span class="op">,</span></span>
<span id="cb2-40"><a href="#cb2-40" aria-hidden="true" tabindex="-1"></a>      }<span class="op">;</span></span>
<span id="cb2-41"><a href="#cb2-41" aria-hidden="true" tabindex="-1"></a>    <span class="cf">case</span> types<span class="op">.</span><span class="at">SOMEOTHER</span><span class="op">.</span><span class="at">ACTION</span><span class="op">.</span><span class="at">FAILURE</span><span class="op">:</span></span>
<span id="cb2-42"><a href="#cb2-42" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> {</span>
<span id="cb2-43"><a href="#cb2-43" aria-hidden="true" tabindex="-1"></a>        <span class="op">...</span>state<span class="op">,</span></span>
<span id="cb2-44"><a href="#cb2-44" aria-hidden="true" tabindex="-1"></a>        <span class="dt">loading</span><span class="op">:</span> <span class="kw">false</span><span class="op">,</span></span>
<span id="cb2-45"><a href="#cb2-45" aria-hidden="true" tabindex="-1"></a>        <span class="dt">dishes</span><span class="op">:</span> []<span class="op">,</span></span>
<span id="cb2-46"><a href="#cb2-46" aria-hidden="true" tabindex="-1"></a>        <span class="dt">error</span><span class="op">:</span> e<span class="op">.</span><span class="at">message</span><span class="op">,</span></span>
<span id="cb2-47"><a href="#cb2-47" aria-hidden="true" tabindex="-1"></a>      }<span class="op">;</span></span>
<span id="cb2-48"><a href="#cb2-48" aria-hidden="true" tabindex="-1"></a>  }</span>
<span id="cb2-49"><a href="#cb2-49" aria-hidden="true" tabindex="-1"></a>}<span class="op">;</span></span>
<span id="cb2-50"><a href="#cb2-50" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-51"><a href="#cb2-51" aria-hidden="true" tabindex="-1"></a><span class="im">export</span> <span class="im">default</span> <span class="fu">mergeReducers</span>(addDishReducer<span class="op">,</span> regularOldReducer)<span class="op">;</span></span></code></pre></div>
<p>The partial reducers allow you to split the reducer into smaller
functions based on the resource/action/state convention. You can also
use this to show off your rad point-free trick shots.</p>
<hr />
<h4 id="duck-promises">Duck promises</h4>
<p>There are 3 different ways to interpret name of this dish. Clue, it's
not a typo (even though it fits perfectly). Another clue, we're not
cooking a duck here. You are correct. Just duck those promises and go
with <code>Async</code> from crocks. (Not to be confused with
<code>async/await</code> which is just a prank that the C# community is
playing on us disguised as w3c draft authors). Here's how to use fetch
(or any other promise based api) and turn it into a composible,
cancellable, lazy Async task. Grandma does not approve laziness but we
will use it anyway because GOD DAMMIT, IT'S MY FREAKING COOKING SHOW!
GET OUT OF MY ROOM, GRANDMA!</p>
<p>For you, a simple made-up example of fetching with network timeout.
fetchJson is just an Async wrapper for fetch api.</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> Async <span class="im">from</span> <span class="st">&#39;crocks/Async&#39;</span><span class="op">;</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> { prop<span class="op">,</span> filter<span class="op">,</span> map<span class="op">,</span> either<span class="op">,</span> complement } <span class="im">from</span> <span class="st">&#39;ramda&#39;</span><span class="op">;</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> { fetchJson } <span class="im">from</span> <span class="st">&#39;@phenax/redux-utils/async&#39;</span><span class="op">;</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="co">// Some other api call that happens after we get the data from the user</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="co">// fetchChefInfo :: a -&gt; Async a</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> fetchChefInfo <span class="op">=</span> data <span class="kw">=&gt;</span> <span class="fu">Async</span>((rej<span class="op">,</span> res) <span class="kw">=&gt;</span> <span class="pp">setTimeout</span>(() <span class="kw">=&gt;</span> <span class="fu">res</span>(data)<span class="op">,</span> <span class="dv">700</span>))<span class="op">;</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a><span class="co">// fetchServableDishes :: Object * -&gt; Async [User]</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> fetchServableDishes <span class="op">=</span> params <span class="kw">=&gt;</span> <span class="fu">fetchJson</span>(<span class="st">&#39;/dishes&#39;</span><span class="op">,</span> params)</span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>  <span class="op">.</span><span class="fu">race</span>(Async<span class="op">.</span><span class="fu">rejectAfter</span>(<span class="dv">2000</span><span class="op">,</span> <span class="kw">new</span> <span class="bu">Error</span>(<span class="st">&#39;Request Timeout&#39;</span>)))</span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>  <span class="op">.</span><span class="fu">map</span>(<span class="fu">prop</span>(<span class="st">&#39;dishes&#39;</span>))</span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>  <span class="op">.</span><span class="fu">map</span>(<span class="fu">compose</span>(</span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>    filter<span class="op">,</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>    complement<span class="op">,</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>    <span class="fu">either</span>(</span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a>      <span class="fu">prop</span>(<span class="st">&#39;isReady&#39;</span>)<span class="op">,</span></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a>      <span class="fu">prop</span>(<span class="st">&#39;isBurnt&#39;</span>)<span class="op">,</span></span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true" tabindex="-1"></a>    )<span class="op">,</span></span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true" tabindex="-1"></a>  ))<span class="op">;</span></span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span> task <span class="op">=</span> <span class="fu">fetchServableDishes</span>()<span class="op">;</span></span>
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true" tabindex="-1"></a><span class="co">// The request has not been sent yet (it&#39;s lazy like crazy! Thank you. Thank you.). You can keep composing and chaining stuff</span></span>
<span id="cb3-25"><a href="#cb3-25" aria-hidden="true" tabindex="-1"></a>task <span class="op">=</span> task</span>
<span id="cb3-26"><a href="#cb3-26" aria-hidden="true" tabindex="-1"></a>  <span class="op">.</span><span class="fu">map</span>(<span class="fu">map</span>(decorateDish))</span>
<span id="cb3-27"><a href="#cb3-27" aria-hidden="true" tabindex="-1"></a>  <span class="op">.</span><span class="fu">chain</span>(fetchChefInfo)<span class="op">;</span></span>
<span id="cb3-28"><a href="#cb3-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-29"><a href="#cb3-29" aria-hidden="true" tabindex="-1"></a><span class="co">// And when you finally decide that you want to make the api call, you can fork it.</span></span>
<span id="cb3-30"><a href="#cb3-30" aria-hidden="true" tabindex="-1"></a><span class="co">// Nothing is executed till you call .fork</span></span>
<span id="cb3-31"><a href="#cb3-31" aria-hidden="true" tabindex="-1"></a>task<span class="op">.</span><span class="fu">fork</span>(</span>
<span id="cb3-32"><a href="#cb3-32" aria-hidden="true" tabindex="-1"></a>  e <span class="kw">=&gt;</span> <span class="bu">console</span><span class="op">.</span><span class="fu">error</span>(e)<span class="op">,</span></span>
<span id="cb3-33"><a href="#cb3-33" aria-hidden="true" tabindex="-1"></a>  activeUsers <span class="kw">=&gt;</span> {</span>
<span id="cb3-34"><a href="#cb3-34" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Do stuff</span></span>
<span id="cb3-35"><a href="#cb3-35" aria-hidden="true" tabindex="-1"></a>  }<span class="op">,</span></span>
<span id="cb3-36"><a href="#cb3-36" aria-hidden="true" tabindex="-1"></a>)<span class="op">;</span></span></code></pre></div>
<hr />
<h4 id="barbecue-sagas">Barbecue sagas</h4>
<p>Redux saga is the best way to write actions. That is a fact, not an
opinion. No need to look it up. Not going to change anything with that
but we can add a few ingredients to enhance its flavor. We are also
going to use <code>Async</code> instead of <code>Promise</code> because
my grandma believes you shouldn't make promises you can't
keep/manage.</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> { put } <span class="im">from</span> <span class="st">&#39;redux-saga/effects&#39;</span><span class="op">;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> { callAsync<span class="op">,</span> putResponse } <span class="im">from</span> <span class="st">&#39;@phenax/redux-utils/saga&#39;</span><span class="op">;</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="im">export</span> <span class="kw">function</span><span class="op">*</span> <span class="fu">add</span>({ payload }) {</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">yield</span> <span class="fu">put</span>({ <span class="dt">type</span><span class="op">:</span> types<span class="op">.</span><span class="at">DISHES</span><span class="op">.</span><span class="at">ADD</span><span class="op">.</span><span class="at">PENDING</span><span class="op">,</span> <span class="dt">payload</span><span class="op">:</span> {} })<span class="op">;</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">const</span> response <span class="op">=</span> <span class="kw">yield</span> <span class="fu">callAsync</span>(saveNewDish<span class="op">,</span> payload)<span class="op">;</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">yield</span> <span class="fu">putResponse</span>(types<span class="op">.</span><span class="at">DISHES</span><span class="op">.</span><span class="at">ADD</span><span class="op">,</span> response)<span class="op">;</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>}<span class="op">;</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a><span class="im">export</span> <span class="kw">function</span><span class="op">*</span> <span class="fu">list</span>({ payload }) {</span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">yield</span> <span class="fu">put</span>({ <span class="dt">type</span><span class="op">:</span> types<span class="op">.</span><span class="at">DISHES</span><span class="op">.</span><span class="at">LIST</span><span class="op">.</span><span class="at">PENDING</span><span class="op">,</span> <span class="dt">payload</span><span class="op">:</span> {} })<span class="op">;</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">const</span> response <span class="op">=</span> <span class="kw">yield</span> <span class="fu">callAsync</span>(fetchServableDishes)<span class="op">;</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">yield</span> <span class="fu">putResponse</span>(types<span class="op">.</span><span class="at">DISHES</span><span class="op">.</span><span class="at">LIST</span><span class="op">,</span> response)<span class="op">;</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>}<span class="op">;</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a><span class="im">export</span> <span class="im">default</span> <span class="kw">function</span><span class="op">*</span> <span class="bu">root</span>() {</span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a>  <span class="kw">yield</span> <span class="fu">all</span>([<span class="fu">takeLatest</span>(types<span class="op">.</span><span class="at">DISHES</span><span class="op">.</span><span class="at">ADD</span><span class="op">.</span><span class="at">_</span><span class="op">,</span> add)])<span class="op">;</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a>  <span class="kw">yield</span> <span class="fu">all</span>([<span class="fu">takeLatest</span>(types<span class="op">.</span><span class="at">DISHES</span><span class="op">.</span><span class="at">LIST</span><span class="op">.</span><span class="at">_</span><span class="op">,</span> list)])<span class="op">;</span></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a>}<span class="op">;</span></span></code></pre></div>
<p>Here,</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">yield</span> <span class="fu">putResponse</span>(types<span class="op">.</span><span class="at">DISHES</span><span class="op">.</span><span class="at">LIST</span><span class="op">,</span> response)<span class="op">;</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="co">// is just a shorthand for</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="kw">yield</span> <span class="fu">put</span>(response<span class="op">.</span><span class="fu">cata</span>({</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Success</span><span class="op">:</span> data <span class="kw">=&gt;</span> ({ <span class="dt">type</span><span class="op">:</span> types<span class="op">.</span><span class="at">DISHES</span><span class="op">.</span><span class="at">LIST</span><span class="op">.</span><span class="at">SUCCESS</span><span class="op">,</span> <span class="dt">payload</span><span class="op">:</span> data })<span class="op">,</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Failure</span><span class="op">:</span> error <span class="kw">=&gt;</span> ({ <span class="dt">type</span><span class="op">:</span> types<span class="op">.</span><span class="at">DISHES</span><span class="op">.</span><span class="at">LIST</span><span class="op">.</span><span class="at">FAILURE</span><span class="op">,</span> <span class="dt">payload</span><span class="op">:</span> error })<span class="op">,</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>}))<span class="op">;</span></span></code></pre></div>
<hr />
<h4 id="selector-noodles">Selector noodles</h4>
<p>Selectors allow you to derive your data from the state and memoize
the operation. We are going to use reselect for this and we're also
gonna sprinkle some ramda in there according to taste. You can use
lodash too but why would you do something like that? Ramda is to lodash
what a smart watch is to a tin-can telephone.</p>
<p>Grandma: “Back in my day, underscore was pretty popular. It was
like…”.</p>
<p>Yeah grandma, we get it, you're old. Now shut up and let me show
these people some selector action.</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> { createSelector } <span class="im">from</span> <span class="st">&quot;reselect&quot;</span><span class="op">;</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> { pathOr<span class="op">,</span> prop<span class="op">,</span> __<span class="op">,</span> map } <span class="im">from</span> <span class="st">&#39;ramda&#39;</span><span class="op">;</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="co">// selectBurntDishes :: { dishes :: { dishIds :: [String], items :: Object Profile } } -&gt; [String]</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="im">export</span> <span class="kw">const</span> selectBurntDishes <span class="op">=</span> <span class="fu">createSelector</span>(</span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>  <span class="fu">pathOr</span>({}<span class="op">,</span> [<span class="st">&#39;dishes&#39;</span><span class="op">,</span> <span class="st">&#39;items&#39;</span>])<span class="op">,</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>  <span class="fu">pathOr</span>([]<span class="op">,</span> [<span class="st">&#39;dishes&#39;</span><span class="op">,</span> <span class="st">&#39;dishIds&#39;</span>])<span class="op">,</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>  (items<span class="op">,</span> dishIds) <span class="kw">=&gt;</span> dishIds<span class="op">.</span><span class="fu">filter</span>(<span class="fu">compose</span>(</span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>    <span class="fu">prop</span>(<span class="st">&#39;isBurnt&#39;</span>)<span class="op">,</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>    <span class="fu">map</span>(<span class="fu">prop</span>(__<span class="op">,</span> items))<span class="op">,</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>  ))<span class="op">,</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a>)<span class="op">;</span></span></code></pre></div>
<p>Now you can use it anywhere…</p>
<p>In you component's mapStateToProps,</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> mapStateToProps <span class="op">=</span> state <span class="kw">=&gt;</span> ({</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">burntDishes</span><span class="op">:</span> <span class="fu">selectBurntDishes</span>(state)<span class="op">,</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>})<span class="op">;</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="im">export</span> <span class="im">default</span> <span class="fu">connect</span>(mapStateToProps)(ListBurntDishes)<span class="op">;</span></span></code></pre></div>
<p>In your sagas,</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">function</span><span class="op">*</span> <span class="fu">mySaga</span>() {</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">const</span> burntDishes <span class="op">=</span> <span class="kw">yield</span> <span class="fu">select</span>(selectBurntDishes)<span class="op">;</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Do stuff with those ids</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
<p>Doesn't that look pretty? If you're new to the point-free way, you
may feel like you just watched a french movie without subtitles but
trust me, this is worth the confusing first few days.</p>
<hr />
<h4 id="conclusion">Conclusion</h4>
<p>Old ideas and opinions are what new ones are born from. Grandma's
recipes were great and they've come out of experience that doesn't mean
we have to keep making the same thing a billion times. Small (and
sometimes large) migrations are a good thing.</p>
<p>So let's summarise. What did we learn today?</p>
<ul>
<li>Use grandma's favorite convention of
<code>@resource/ACTION/STATE</code> for your action types</li>
<li>The elderly hate long switch case statements</li>
<li>Duck promises because <code>Async</code> rocks!</li>
<li>Sagas are the freakin best!!</li>
<li>Memoize those selectors for a better tomorrow</li>
</ul>
<p>These are all solutions to the small yet annoying inconveniences that
I ran into while working on a personal project of mine. I'm collecting
all of the tiny helpers over at <a
href="https://github.com/phenax/redux-utils">@phenax/redux-utils</a>.
The project is not done yet so the library will be getting more updates.
PRs are welcome!!</p>
<p>Hope these ideas help you write some tasty code.</p>
]]>
  </description>
</item>
<item>
  <guid>/blog/2019-03-14-sum-types.html</guid>
  <title># Functional JS - Sum Types In JavaScript</title>
  <link>https://ediblemonad.dev/blog/2019-03-14-sum-types.html</link>
  <comments>https://ediblemonad.dev/blog/2019-03-14-sum-types.html</comments>
  <pubDate>2019-03-14</pubDate>
  <description>
    <![CDATA[<h2 id="functional-js---sum-types-in-javascript">Functional JS - Sum
Types In JavaScript</h2>
<p>JavaScript has a very bad reputation in most developer communities.
So much so that, “Writing cleaner and safer JavaScript…” in the title
may already seem a bit redundant to most readers. A lot of that has to
do with loose typing, invalid values and the horrible chain of ternary
expressions or heaven forbid, if statements to handle them. With
JavaScript, all functions run on the concept of “pretend what you are
getting is what you asked for”. If the value is not valid for the kind
of operation you are running on it, well, too bad. To save yourself from
this, you can write run-time validations, add type-checks, etc but the
core of the problem is till left largely unsolved.</p>
<hr />
<h4 id="lets-learn-from-haskell">Let’s learn from Haskell</h4>
<p>Functional programming languages like Haskell have a clear solution
for this. Sum Types! Sum Type (or Tagged Union) is an Algebraic Data
Type which describes values that can take on several different types.
Popular examples in haskell are the Maybe monad (for handling the
validity of values) and the Either monad (for error handling).</p>
<p>Don’t worry. Maybe, I don’t know anything about monads Either (see
what I did there?). All we need to know is that a Sum Type is a has
multiple named constructors.</p>
<p>In Haskell, a Sum type looks something like this -</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">MetalGenre</span> <span class="ot">=</span> <span class="dt">ProgMetal</span> <span class="op">|</span> <span class="dt">DeathCore</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="ot">scream ::</span> <span class="dt">MetalGenre</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>scream genre <span class="ot">=</span> <span class="fu">putStrLn</span> <span class="op">$</span> <span class="kw">case</span> genre <span class="kw">of</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">ProgMetal</span> <span class="ot">-&gt;</span> <span class="st">&quot;Oh!&quot;</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">DeathCore</span> <span class="ot">-&gt;</span> <span class="st">&quot;BleaAaAHHH!!&quot;</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="ot">main ::</span> <span class="dt">IO</span>()</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> scream <span class="dt">ProgMetal</span></span></code></pre></div>
<p>Here, MetalGenre is the type and ProgMetal, DeathCore are
constructors of that type.</p>
<p>A really popular and useful example of a Sum type in the functional
world is the Maybe type. In Haskell, Maybe is a monad that wraps a value
and helps you make sure that invalid values are not acted upon, thus
allowing you to write safer functions.</p>
<p>This is what Maybe’s definition looks like in Haskell -</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Maybe</span> <span class="ot">=</span> <span class="dt">Just</span> a <span class="op">|</span> <span class="dt">Nothing</span></span></code></pre></div>
<p>Now here, all valid values will be wrapped in a Just and all invalid
values will be wrapped in a Nothing. This way, we can handle invalid
values in a clean and elegant way and be sure of the fact that the
function is only called for the valid values.</p>
<p>You might be thinking, “But isn’t this only possible because Haskell
is a statically typed beauty and JavaScript is the spawn of satan?”.
Maybe it isn’t. (The joke’s getting old now)</p>
<hr />
<h4 id="enumfp">EnumFP</h4>
<p>Shameless self-plug alert!</p>
<p>I have a library to help with that! (Said every JavaScript developer
ever).</p>
<p><a href="https://github.com/phenax/enum-fp">EnumFP</a> (PRs
welcome)</p>
<p>EnumFP is a simple and light-weight way to create Sum types in
JavaScript. Inspired by the awesomeness of Haskell, the library is
written with safety in mind.</p>
<p>This is what the metal genre example would look like with EnumFP.</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> MetalGenre <span class="op">=</span> <span class="fu">Enum</span>([<span class="st">&#39;ProgMetal&#39;</span><span class="op">,</span> <span class="st">&#39;DeathCore&#39;</span>])</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> scream <span class="op">=</span> <span class="fu">compose</span>(<span class="bu">console</span><span class="op">.</span><span class="fu">log</span><span class="op">,</span> MetalGenre<span class="op">.</span><span class="fu">cata</span>({</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">ProgMetal</span><span class="op">:</span> () <span class="kw">=&gt;</span> <span class="st">&quot;Oh!&quot;</span><span class="op">,</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">DeathCore</span><span class="op">:</span> () <span class="kw">=&gt;</span> <span class="st">&quot;BleaAaAHHH!!&quot;</span><span class="op">,</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>}))<span class="op">;</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a><span class="fu">scream</span>(MetalGenre<span class="op">.</span><span class="fu">ProgMetal</span>())<span class="op">;</span></span></code></pre></div>
<hr />
<h4 id="maybe-maybe">Maybe, maybe?</h4>
<p>The concept of what a Maybe does is more important than the
implementation itself. Containing a value in a way that allows you to
perform a set of operations on the container and not worry about the
validity of the input is what Maybe is about.</p>
<p>You can implement a simple Maybe and a couple of utility functions
using EnumFP. EnumFP also allows you to add argument descriptions. This
example uses the caseOf function which is like match but for partial
application).</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> Maybe <span class="op">=</span> <span class="fu">Enum</span>({ <span class="dt">Just</span><span class="op">:</span> [<span class="st">&#39;value&#39;</span>]<span class="op">,</span> <span class="dt">Nothing</span><span class="op">:</span> [] })<span class="op">;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="co">// fmap :: (a -&gt; b) -&gt; Maybe a -&gt; Maybe b</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> fmap <span class="op">=</span> fn <span class="kw">=&gt;</span> Maybe<span class="op">.</span><span class="fu">cata</span>({</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Just</span><span class="op">:</span> <span class="fu">compose</span>(Maybe<span class="op">.</span><span class="at">Just</span><span class="op">,</span> fn)<span class="op">,</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Nothing</span><span class="op">:</span> Maybe<span class="op">.</span><span class="at">Nothing</span><span class="op">,</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>})<span class="op">;</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a><span class="co">// mjoin :: Maybe Maybe a -&gt; Maybe a</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> mjoin <span class="op">=</span> Maybe<span class="op">.</span><span class="fu">cata</span>({</span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Just</span><span class="op">:</span> x <span class="kw">=&gt;</span> x<span class="op">,</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Nothing</span><span class="op">:</span> Maybe<span class="op">.</span><span class="at">Nothing</span><span class="op">,</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>})<span class="op">;</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a><span class="co">// chain :: (a -&gt; Maybe b) -&gt; Maybe a -&gt; Maybe b</span></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> chain <span class="op">=</span> fn <span class="kw">=&gt;</span> <span class="fu">compose</span>(mjoin<span class="op">,</span> <span class="fu">fmap</span>(fn))<span class="op">;</span></span></code></pre></div>
<p>Here,</p>
<p><strong>fmap</strong> returns a new Maybe and runs the function over
the value inside, in case of Just and ignores a Nothing. (Like
Array.prototype.map)</p>
<p><strong>mjoin</strong> unwraps a given nested Maybe. Because many
monads like Maybe, are agnostic about the value inside, you can put the
monad inside another monad (That’s what shesaid) (Like
Array.prototype.flatten)</p>
<p><strong>chain</strong> maps over the Maybe and then flattens the
resulting nested Maybe. (Like Array.prototype.flatMap).</p>
<p>Let’s use this and write a function that accepts a User instance and
gives you the first name without throwing an error for invalid user or
invalid name.</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="co">// head :: [a] -&gt; Maybe a</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> head <span class="op">=</span> arr <span class="kw">=&gt;</span> (arr<span class="op">.</span><span class="at">length</span> <span class="op">?</span> Maybe<span class="op">.</span><span class="fu">Just</span>(arr[<span class="dv">0</span>]) <span class="op">:</span> Maybe<span class="op">.</span><span class="fu">Nothing</span>())<span class="op">;</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="co">// prop :: String -&gt; Object a -&gt; Maybe a</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> prop <span class="op">=</span> key <span class="kw">=&gt;</span> obj <span class="kw">=&gt;</span> key <span class="kw">in</span> obj <span class="op">?</span> Maybe<span class="op">.</span><span class="fu">Just</span>(obj[key]) <span class="op">:</span> Maybe<span class="op">.</span><span class="fu">Nothing</span>()<span class="op">;</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a><span class="co">// trim :: String -&gt; String</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> trim <span class="op">=</span> str <span class="kw">=&gt;</span> str<span class="op">.</span><span class="fu">trim</span>()<span class="op">;</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a><span class="co">// split :: String -&gt; String -&gt; [String]</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> split <span class="op">=</span> seperator <span class="kw">=&gt;</span> str <span class="kw">=&gt;</span> str<span class="op">.</span><span class="fu">split</span>(seperator)<span class="op">;</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a><span class="co">// safeUser :: User -&gt; Maybe User</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> safeUser <span class="op">=</span> user <span class="kw">=&gt;</span> <span class="fu">isUserValid</span>(user) <span class="op">?</span> Maybe<span class="op">.</span><span class="fu">Just</span>(user) <span class="op">:</span> Maybe<span class="op">.</span><span class="fu">Nothing</span>()<span class="op">;</span></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a><span class="co">// getFirstName :: User -&gt; Maybe String</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> getFirstName <span class="op">=</span> <span class="fu">compose</span>(</span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true" tabindex="-1"></a>    <span class="fu">chain</span>(head)<span class="op">,</span> <span class="co">// Maybe [String] -&gt; Maybe String</span></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true" tabindex="-1"></a>    <span class="fu">fmap</span>(<span class="fu">split</span>(<span class="st">&#39; &#39;</span>))<span class="op">,</span> <span class="co">// Maybe String -&gt; Maybe [String]</span></span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true" tabindex="-1"></a>    <span class="fu">fmap</span>(trim)<span class="op">,</span> <span class="co">// Maybe String -&gt; Maybe String</span></span>
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true" tabindex="-1"></a>    <span class="fu">chain</span>(<span class="fu">prop</span>(<span class="st">&#39;name&#39;</span>))<span class="op">,</span> <span class="co">// Maybe User -&gt; Maybe String</span></span>
<span id="cb5-22"><a href="#cb5-22" aria-hidden="true" tabindex="-1"></a>    safeUser<span class="op">,</span> <span class="co">// User -&gt; Maybe User</span></span>
<span id="cb5-23"><a href="#cb5-23" aria-hidden="true" tabindex="-1"></a>)<span class="op">;</span></span>
<span id="cb5-24"><a href="#cb5-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-25"><a href="#cb5-25" aria-hidden="true" tabindex="-1"></a>Maybe<span class="op">.</span><span class="fu">match</span>(<span class="fu">getFirstName</span>(user)<span class="op">,</span> {</span>
<span id="cb5-26"><a href="#cb5-26" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Just</span><span class="op">:</span> name <span class="kw">=&gt;</span> <span class="bu">console</span><span class="op">.</span><span class="fu">log</span>(<span class="st">&#39;My name is&#39;</span><span class="op">,</span> name)<span class="op">,</span></span>
<span id="cb5-27"><a href="#cb5-27" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Nothing</span><span class="op">:</span> () <span class="kw">=&gt;</span> <span class="bu">console</span><span class="op">.</span><span class="fu">log</span>(<span class="st">&#39;Whats in a name?&#39;</span>)<span class="op">,</span></span>
<span id="cb5-28"><a href="#cb5-28" aria-hidden="true" tabindex="-1"></a>})<span class="op">;</span></span></code></pre></div>
<p>In the example above, we first convert the user to a safe user by
wrapping it in a Maybe. Then we get the user’s name using the prop
function. The prop and head functions here, instead of returning the
value, wraps the value in a Maybe. This is why to map it and then unwrap
it, we use chain instead of fmap.</p>
<hr />
<h4 id="working-with-react">Working with React</h4>
<p>Yes, EnumFP works well with react! (Jumping from one over-populated
community to the next).</p>
<p>With the new react hooks being introduced in 16.8, it would be a sin
not to mention it here. EnumFP ships with a useReducer hook which is a
simple wrapper around react’s useReducer.</p>
<p>Don’t want to upgrade to 16.8? Do you still watch reruns of Seinfeld?
Want to wait for your grand-children to help you with the upgrade… and…
walking?</p>
<p>No worries. There’s an HOC available as well.</p>
<p>You can find out more about integrations with react here.</p>
<p>And this is not limited to just component state tho. You can use Sum
Types to work with any kind of enumerable state values. From handling
Success, Pending and Failure states for any action to containing values
based on it’s type or validity. Sum Types are here to clean up all of
that.</p>
<hr />
<h4 id="conclusion">Conclusion</h4>
<p>This is just the tip of the iceberg. There are a lot more of these
amazing ideas hidden in the world of functional programming, waiting to
move to other languages. Being a part of the JavaScript community for a
while has made me realise that it’s not all bad. What we lack in
language features and standard library, we make up for in the variety of
libraries just an npm install away, and the strong community constantly
working towards “Making JS great again”. So let’s build a wall together
between us and bad code. Covfefe.</p>
]]>
  </description>
</item>

  </channel>
</rss>
