<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2025-03-03T01:27:42+00:00</updated><id>/feed.xml</id><title type="html">The Devel!</title><subtitle>choonkeat on programming &amp; software</subtitle><author><name>choonkeat</name></author><entry><title type="html">Better B</title><link href="/weblog/2025/03/better-b.html" rel="alternate" type="text/html" title="Better B" /><published>2025-03-01T00:00:00+00:00</published><updated>2025-03-01T00:00:00+00:00</updated><id>/weblog/2025/03/better-b</id><content type="html" xml:base="/weblog/2025/03/better-b.html"><![CDATA[<h3 id="high-output">High output</h3>

<p>I used to work with this young leetcoder. He is smart and fast. He can whip out code double quick time. Sometimes when I’m looking at his PR, I’m in awe. In awe at how a requirement could be followed to the letter, yet doing the wrong thing 😭 The angle of how his code can be incorrect catches me off guard.</p>

<p>The current AI coding agent reminds me of him: one moment exceeding expectations one-shot-ing an entire feature, another moment stumbling over the weirdest rabbit hole. We are in the era of high output programmers <sup><a href="#footnote1">[1]</a></sup> <sup><a href="#footnote2">[2]</a></sup> <sup><a href="#footnote3">[3]</a></sup> <sup><a href="#footnote4">[4]</a></sup> <sup><a href="#footnote5">[5]</a></sup>, so everyone gets to work with my young leetcoder now:</p>

<ul>
  <li>Reading <em>all</em> their code <em>all</em> the time is unsustainable and quickly becomes a bottleneck</li>
  <li>Not verifying is even more reckless; what is clearly X to you might be clearly Y to them</li>
</ul>

<p>We need all the help we can get to verify quickly &amp; sustainably.</p>

<h3 id="triage">Triage</h3>

<ol>
  <li>
    <p>What did they say they’re <em>going</em> to do? If that’s wrong, interrupt and course correct. <strong>1 unit of my time &amp; effort spent; 0 of theirs.</strong></p>

    <blockquote>
      <p>Best time to fix a bug is before it’s written.</p>

      <p>AI coding agents are <em>really</em> good at this: explaining their plan and verbalizing what they’re doing. They are basically the model pair programmer interviewees. Puts us human programmers to shame.</p>

      <p>Pro-tip is to have them write down their plan in a <code class="language-plaintext highlighter-rouge">tasks/{pending|doing|done}-{task}.md</code> file. It leaves good documentation, helps reel them in when they go down test-fix rabbit holes losing the plot, and even lets us switch between AI models &amp; humans easily.</p>

      <p>The finishing touch is to have them <code class="language-plaintext highlighter-rouge">[x]</code> check off the sub-tasks inside the file as we verify their progress.</p>
    </blockquote>
  </li>
  <li>
    <p>Can it compile? If not, short circuit; no need to look at anything else until this is fixed. <strong>1 unit of time &amp; effort spent.</strong></p>

    <blockquote>
      <p>Good type systems in the category of “if it compiles, it works” really shine when wielded by high output coders.</p>

      <p>Make bugs into type errors<sup><a href="#footnote6">[6]</a></sup>.</p>

      <p>The more we can express in the type system, the more we can catch super fast, the lesser we need to verify by running code (last bullet point; orders of magnitude more time &amp; effort).</p>
    </blockquote>
  </li>
  <li>
    <p>Does the db schema, type definition, type signature changes make sense? If not, short circuit. <strong>1-5 units of time &amp; effort spent.</strong> <sup><a href="#footnote7">[7]</a></sup></p>

    <blockquote>
      <p>Anything else is more verbose, less precise, and less trustworthy than these gems.</p>

      <p>Look ma, no schema? Implicit function arguments? Such ergonomic conveniences now hurt more than help. Just pass the arguments explicitly, and let the type system do the rest.</p>

      <p>As the saying goes, <em>“Show me your flowchart and conceal your tables, and I shall continue to be mystified. Show me your tables, and I won’t usually need your flowchart; it’ll be obvious.”</em></p>
    </blockquote>
  </li>
  <li>
    <p>What does PR description or inline comments say / show? If that’s wrong, short circuit. <strong>5-10 unit of time &amp; effort spent.</strong></p>

    <blockquote>
      <p>Again, AI coding agents put most human Pull Request descriptions to shame.</p>

      <p>Finding a problem here is often faster than finding a problem from test scenarios.</p>
    </blockquote>
  </li>
  <li>
    <p>Are tests passing and do the scenarios cover what’s needed? If not, short circuit. <strong>20-100 units of time &amp; effort.</strong></p>

    <blockquote>
      <p>Humans: are there even tests?</p>
    </blockquote>
  </li>
  <li>
    <p>Run the code in our head and/or on a machine. <strong>100-1000 units of time &amp; effort.</strong></p>
  </li>
</ol>

<h3 id="getting-from-a-to-b">Getting from A to B</h3>

<p>I know many teams prefer to use a language &amp; framework to get from A to B fast: it is easy to hire for, easy to learn, easy to write &amp; read. You need to staff up quickly, or if your engineers are already familiar with some tech stack.</p>

<p>Moving forward, we are all augmented with new age high output programmers that don’t have these problems: they already know the languages, write them quickly, translate them effortlessly, document them even better. What they need from us is to verify their work quickly &amp; sustainably.</p>

<p>In this new world, are there legitimate reasons to hold on to a codebase</p>

<ul>
  <li>that doesn’t<sup><a href="#footnote8">[8]</a></sup> have sound type checking<sup><a href="#footnote9">[9]</a></sup>?</li>
  <li>that cannot<sup><a href="#footnote10">[10]</a></sup> do parse don’t validate<sup><a href="#footnote11">[11]</a></sup> nor make illegal states unrepresentable<sup><a href="#footnote12">[12]</a></sup>?</li>
  <li>that isn’t memory safe<sup><a href="#footnote13">[13]</a></sup>?</li>
  <li>that is memory hungry<sup><a href="#footnote14">[14]</a></sup>?</li>
  <li>that is slow<sup><a href="#footnote15">[15]</a></sup>?</li>
</ul>

<p>Do we prefer something that is good to hire for? Or something that is good to work with?</p>

<h3 id="getting-to-a-better-b">Getting to a better B</h3>

<p>We are finally truly able to walk the talk of choosing the best tool for the job. I am once again<sup><a href="#footnote16">[16]</a></sup> looking forward to getting to “a good B” fast, instead of only getting from A to B fast.</p>

<hr />

<p><sub>
<a name="footnote1">[1]</a> <a href="https://docs.anthropic.com/en/docs/agents-and-tools/claude-code/overview">Anthropic Claude Code</a>
<br />
<a name="footnote2">[2]</a> <a href="https://www.cursor.com/en">Cursor</a>
<br />
<a name="footnote3">[3]</a> <a href="https://codeium.com/windsurf">Codeium Windsurf</a>
<br />
<a name="footnote4">[4]</a> <a href="https://github.blog/news-insights/product-news/github-copilot-the-agent-awakens/">GitHub Copilot - The Agent Awakens</a>
<br />
<a name="footnote5">[5]</a> <a href="https://aider.chat">Aider Chat</a>
<br />
<a name="footnote6">[6]</a> <a href="https://x.com/mattoflambda/status/1008735243581288449">Make Bugs Into Type Errors</a>
<br />
<a name="footnote7">[7]</a> Historically, when my leetcoder gets the wrong idea, this is usually where I really find out.
<br />
<a name="footnote8">[8]</a> <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript">JavaScript</a>
<br />
<a name="footnote9">[9]</a> <a href="https://www.typescriptlang.org">TypeScript</a>
<br />
<a name="footnote10">[10]</a> <a href="https://chatgpt.com/share/67c2900e-6074-8008-9c6b-cf50a9a5adef">In Go, the best you can do is make it hard (but never impossible) to produce an invalid value.</a>
<br />
<a name="footnote11">[11]</a> <a href="https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/">Parse Don’t Validate</a>
<br />
<a name="footnote12">[12]</a> <a href="https://www.youtube.com/watch?v=IcgmSRJHu_8">Make Illegal States Unrepresentable</a>
<br />
<a name="footnote13">[13]</a> <a href="https://cplusplus.com">C++</a>
<br />
<a name="footnote14">[14]</a> <a href="https://www.java.com/en/">Java</a>
<br />
<a name="footnote15">[15]</a> <a href="http://ruby-lang.org">Ruby</a>
<br />
<a name="footnote16">[16]</a> <a href="https://blog.choonkeat.com/weblog/2018/10/getting-from-a-to-b.html#a-better-b">Getting to a Better B</a>
<br />
</sub></p>]]></content><author><name>choonkeat</name></author><summary type="html"><![CDATA[High output]]></summary></entry><entry><title type="html">Stop handling HTTP requests with HTTP response</title><link href="/weblog/2024/05/stop-handling-http-requests-with-http-response.html" rel="alternate" type="text/html" title="Stop handling HTTP requests with HTTP response" /><published>2024-05-28T00:00:00+00:00</published><updated>2024-05-28T00:00:00+00:00</updated><id>/weblog/2024/05/stop-handling-http-requests-with-http-response</id><content type="html" xml:base="/weblog/2024/05/stop-handling-http-requests-with-http-response.html"><![CDATA[<p>In most platforms, our functions that deal with http requests have the same signature</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">// go</span>
<span class="k">func</span><span class="p">(</span><span class="n">w</span> <span class="n">http</span><span class="o">.</span><span class="n">ResponseWriter</span><span class="p">,</span> <span class="n">r</span> <span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Request</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">w</span><span class="o">.</span><span class="n">Header</span><span class="p">()</span><span class="o">.</span><span class="n">Set</span><span class="p">(</span><span class="s">"Content-Type"</span><span class="p">,</span> <span class="s">"text/plain"</span><span class="p">)</span>
    <span class="n">w</span><span class="o">.</span><span class="n">WriteHeader</span><span class="p">(</span><span class="n">http</span><span class="o">.</span><span class="n">StatusOK</span><span class="p">)</span>
    <span class="n">w</span><span class="o">.</span><span class="n">Write</span><span class="p">([]</span><span class="kt">byte</span><span class="p">(</span><span class="s">"Hello"</span><span class="p">))</span>
<span class="p">}</span>
</code></pre></div></div>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// typescript</span>
<span class="kd">function</span> <span class="nx">handler</span><span class="p">(</span><span class="nx">req</span><span class="p">:</span> <span class="nx">http</span><span class="p">.</span><span class="nx">IncomingMessage</span><span class="p">,</span> <span class="nx">res</span><span class="p">:</span> <span class="nx">http</span><span class="p">.</span><span class="nx">ServerResponse</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">res</span><span class="p">.</span><span class="nx">writeHead</span><span class="p">(</span><span class="mi">200</span><span class="p">,</span> <span class="p">{</span> <span class="dl">'</span><span class="s1">Content-Type</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">text/plain</span><span class="dl">'</span> <span class="p">});</span>
    <span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">(</span><span class="dl">"</span><span class="s2">Hello</span><span class="dl">"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>It is the same for Ruby, Python, etc. It’s the same even if <a href="https://guides.rubyonrails.org/getting_started.html">your platform makes them implicit</a>, or <a href="https://koajs.com">puts them <em>both</em> into a <em>single</em> argument named <code class="language-plaintext highlighter-rouge">ctx</code> instead.</a></p>

<p>Yes, platforms <em>have</em> to provide them because they are the primitives. But we don’t <em>have</em> to write our http handlers in a primitive manner!</p>

<h3 id="whats-the-problem">What’s the problem?</h3>

<p>When we work with the <code class="language-plaintext highlighter-rouge">HttpResponse</code> directly, our code is imperative, irreversible, we mutate the response as we go, and can easily become incoherent: someone implements X, someone fixes Y, and before you know it, the code path contain weird combinations:</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">app</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/hello</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">:</span> <span class="nx">Request</span><span class="p">,</span> <span class="nx">res</span><span class="p">:</span> <span class="nx">Response</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="k">try</span> <span class="p">{</span>
        <span class="nx">res</span><span class="p">.</span><span class="nx">writeHead</span><span class="p">(</span><span class="mi">200</span><span class="p">,</span> <span class="p">{</span> <span class="dl">'</span><span class="s1">Content-Type</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">text/html</span><span class="dl">'</span> <span class="p">});</span>
        <span class="nx">res</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">headerHTML</span><span class="p">);</span>
        <span class="nx">res</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="s2">`&lt;h1&gt;Hello, </span><span class="p">${</span><span class="nx">userName</span><span class="p">(</span><span class="nx">req</span><span class="p">)}</span><span class="s2">!&lt;/h1&gt;`</span><span class="p">);</span>
        <span class="nx">res</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">footerHTML</span><span class="p">);</span>
        <span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">();</span>
    <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
        <span class="nx">res</span><span class="p">.</span><span class="nx">writeHead</span><span class="p">(</span><span class="mi">500</span><span class="p">,</span> <span class="p">{</span> <span class="dl">'</span><span class="s1">Content-Type</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">application/json</span><span class="dl">'</span> <span class="p">});</span>
        <span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">(</span><span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">({</span> <span class="na">error</span><span class="p">:</span> <span class="dl">'</span><span class="s1">Internal Server Error</span><span class="dl">'</span><span class="p">,</span> <span class="na">message</span><span class="p">:</span> <span class="nx">err</span><span class="p">.</span><span class="nx">message</span> <span class="p">}));</span>
    <span class="p">}</span>
<span class="p">});</span>
</code></pre></div></div>

<p>Looks fine at a glance? But if <code class="language-plaintext highlighter-rouge">userName</code> encounters an error, it’s nasty:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>HTTP/1.1 200 OK
Content-Type: text/html

&lt;html&gt;
    &lt;head&gt;...&lt;/head&gt;
    &lt;body&gt;{ "error": "Internal Server Error" }
</code></pre></div></div>

<p>Sure we can fix <em>this</em> bug, but the situation is just whack-a-mole: there is infinite combinations of things that can happen. e.g. setting the same cookie multiple times in a request is oddly common.</p>

<h3 id="whats-the-solution">What’s the solution?</h3>

<p>Though http response itself entertains an infinite combination of things, our web application (no matter how big and complex) will only have finite variations of responses: redirect, set cookie <em>and redirect</em>, render page with layout, render page with <em>different layout</em>, error page, json payload, json error, … the list goes on, but it will end.</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">type</span> <span class="nx">AppResponse</span> <span class="o">=</span>
    <span class="o">|</span> <span class="p">{</span> <span class="na">type</span><span class="p">:</span> <span class="dl">'</span><span class="s1">redirect</span><span class="dl">'</span><span class="p">;</span> <span class="nl">url</span><span class="p">:</span> <span class="kr">string</span> <span class="p">}</span>
    <span class="o">|</span> <span class="p">{</span> <span class="na">type</span><span class="p">:</span> <span class="dl">'</span><span class="s1">renderPage</span><span class="dl">'</span><span class="p">;</span> <span class="nl">content</span><span class="p">:</span> <span class="kr">string</span> <span class="p">}</span>
    <span class="c1">// ...</span>
</code></pre></div></div>

<p>To paraphrase a popular adage: <em>if you can’t list them, you can’t manage them.</em></p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">handleResponse</span><span class="p">(</span><span class="nx">res</span><span class="p">:</span> <span class="nx">Response</span><span class="p">,</span> <span class="nx">response</span><span class="p">:</span> <span class="nx">AppResponse</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">switch</span> <span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="kd">type</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">case</span> <span class="dl">'</span><span class="s1">redirect</span><span class="dl">'</span><span class="p">:</span>
            <span class="nx">res</span><span class="p">.</span><span class="nx">writeHead</span><span class="p">(</span><span class="mi">302</span><span class="p">,</span> <span class="p">{</span> <span class="dl">'</span><span class="s1">Location</span><span class="dl">'</span><span class="p">:</span> <span class="nx">response</span><span class="p">.</span><span class="nx">url</span> <span class="p">});</span>
            <span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">();</span>
            <span class="k">break</span><span class="p">;</span>
        <span class="k">case</span> <span class="dl">'</span><span class="s1">renderPage</span><span class="dl">'</span><span class="p">:</span>
            <span class="nx">res</span><span class="p">.</span><span class="nx">writeHead</span><span class="p">(</span><span class="mi">200</span><span class="p">,</span> <span class="p">{</span> <span class="dl">'</span><span class="s1">Content-Type</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">text/html</span><span class="dl">'</span> <span class="p">});</span>
            <span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">(</span><span class="s2">`&lt;html&gt;&lt;body&gt;</span><span class="p">${</span><span class="nx">mainHeader</span><span class="p">}${</span><span class="nx">response</span><span class="p">.</span><span class="nx">content</span><span class="p">}${</span><span class="nx">mainFooter</span><span class="p">}</span><span class="s2">&lt;/body&gt;&lt;/html&gt;`</span><span class="p">);</span>
            <span class="k">break</span><span class="p">;</span>
        <span class="c1">// ...</span>
</code></pre></div></div>

<p>Yes, we have to handle all variants in our helper function. But it’s not <em>more</em> work; we have to do them anyways. The difference is, they are all managed in the same place now.</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">handleAppResponse</span><span class="p">(</span><span class="nx">handler</span><span class="p">:</span> <span class="p">(</span><span class="nx">req</span><span class="p">:</span> <span class="nx">Request</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">AppResponse</span><span class="p">):</span> <span class="p">(</span><span class="nx">req</span><span class="p">:</span> <span class="nx">Request</span><span class="p">,</span> <span class="nx">res</span><span class="p">:</span> <span class="nx">Response</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="k">void</span> <span class="p">{</span>
    <span class="k">return</span> <span class="p">(</span><span class="na">req</span><span class="p">:</span> <span class="nx">Request</span><span class="p">,</span> <span class="na">res</span><span class="p">:</span> <span class="nx">Response</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="nx">handler</span><span class="p">(</span><span class="nx">req</span><span class="p">);</span>
        <span class="nx">handleResponse</span><span class="p">(</span><span class="nx">res</span><span class="p">,</span> <span class="nx">response</span><span class="p">);</span>
    <span class="p">};</span>
<span class="p">}</span>

<span class="nx">app</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/hello</span><span class="dl">'</span><span class="p">,</span> <span class="nx">handleAppResponse</span><span class="p">(</span><span class="nx">handleHello</span><span class="p">));</span>
<span class="nx">app</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/goodbye</span><span class="dl">'</span><span class="p">,</span> <span class="nx">handleAppResponse</span><span class="p">(</span><span class="nx">handleGoodbye</span><span class="p">));</span>
<span class="c1">// ...</span>
</code></pre></div></div>

<p>What we get after all this, is that our “http handlers” have <em>all</em> become simpler functions! We don’t have to fiddle with mutating <code class="language-plaintext highlighter-rouge">http.Response</code>; we can’t because we don’t have access to it! Just return the appropriate response variant!</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">handleHello</span><span class="p">(</span><span class="nx">req</span><span class="p">:</span> <span class="nx">Request</span><span class="p">):</span> <span class="nx">AppResponse</span> <span class="p">{</span>
    <span class="k">try</span> <span class="p">{</span>
        <span class="kd">const</span> <span class="nx">content</span> <span class="o">=</span> <span class="s2">`&lt;h1&gt;Hello, </span><span class="p">${</span><span class="nx">userName</span><span class="p">(</span><span class="nx">req</span><span class="p">)}</span><span class="s2">!&lt;/h1&gt;`</span><span class="p">;</span>
        <span class="k">return</span> <span class="p">{</span> <span class="na">type</span><span class="p">:</span> <span class="dl">'</span><span class="s1">renderPage</span><span class="dl">'</span><span class="p">,</span> <span class="nx">content</span> <span class="p">};</span>
    <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span> <span class="p">{</span> <span class="na">type</span><span class="p">:</span> <span class="dl">'</span><span class="s1">jsonError</span><span class="dl">'</span><span class="p">,</span> <span class="nx">err</span><span class="p">,</span> <span class="na">statusCode</span><span class="p">:</span> <span class="mi">500</span> <span class="p">};</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>and in Go <a href="https://github.com/choonkeat/sumtype-go">with sum types</a> <sup><a href="#footnote1">[1]</a></sup></p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="n">handleHello</span><span class="p">(</span><span class="n">r</span> <span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Request</span><span class="p">)</span> <span class="n">AppResponse</span> <span class="p">{</span>
    <span class="n">uname</span><span class="p">,</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">userName</span><span class="p">(</span><span class="n">r</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
        <span class="k">return</span> <span class="n">JsonError</span><span class="p">(</span><span class="n">err</span><span class="p">,</span> <span class="n">http</span><span class="o">.</span><span class="n">StatusInternalServerError</span><span class="p">)</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="n">RenderPage</span><span class="p">(</span>
        <span class="n">dom</span><span class="o">.</span><span class="n">H1</span><span class="p">(</span> <span class="c">// github.com/choonkeat/dom-go</span>
            <span class="n">dom</span><span class="o">.</span><span class="n">Attrs</span><span class="p">(</span><span class="s">"id"</span><span class="p">,</span> <span class="s">"greeting"</span><span class="p">),</span>
            <span class="n">dom</span><span class="o">.</span><span class="n">InnerText</span><span class="p">(</span><span class="s">"Hello, "</span><span class="p">),</span>
            <span class="n">dom</span><span class="o">.</span><span class="n">InnerText</span><span class="p">(</span><span class="n">uname</span><span class="p">),</span>
        <span class="p">),</span>
    <span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<p>We’ve constrained our http handlers to return <code class="language-plaintext highlighter-rouge">AppResponse</code>. We can’t mutate <code class="language-plaintext highlighter-rouge">http.Response</code> directly. How our web app respond is all managed in a single place. There’s no whack-a-mole problem anymore.</p>

<p><em>Food for thought: if we take 1 more step to replace <code class="language-plaintext highlighter-rouge">http.Request</code> with our own <code class="language-plaintext highlighter-rouge">AppRequest</code>, then our handlers are just functions <code class="language-plaintext highlighter-rouge">handleHello(AppRequest): AppResponse</code> – we don’t even need to fiddle with http to unit test our http handlers?</em></p>

<p><sub><a name="footnote1">[1]</a>
You can also embrace returning-a-value as solution in Go without defining your own sum type <a href="https://github.com/alvinchoong/go-httphandler">using this library</a>
</sub><br /></p>]]></content><author><name>choonkeat</name></author><summary type="html"><![CDATA[In most platforms, our functions that deal with http requests have the same signature]]></summary></entry><entry><title type="html">Null Is Maligned</title><link href="/weblog/2024/03/null-is-maligned.html" rel="alternate" type="text/html" title="Null Is Maligned" /><published>2024-03-05T00:00:00+00:00</published><updated>2024-03-05T00:00:00+00:00</updated><id>/weblog/2024/03/null-is-maligned</id><content type="html" xml:base="/weblog/2024/03/null-is-maligned.html"><![CDATA[<p>For the longest time, I was told <code class="language-plaintext highlighter-rouge">Null</code> was bad: “Null the billion-dollar mistake”</p>

<p>But… doesn’t database tables have nullable columns? And when there <em>is</em> no value, I put <code class="language-plaintext highlighter-rouge">NULL</code> in it? If using <code class="language-plaintext highlighter-rouge">NULL</code> is a billion-dollar mistake there, then what <em>do</em> we use instead?</p>

<p>Cue programmers of various unpopular languages to sweep in, <em>“come! there’s no Null here, maybe”</em></p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>type Maybe a = Nothing | Just a

message1 = Just "Hello, world!"
message2 = Nothing
</code></pre></div></div>

<p>So… <code class="language-plaintext highlighter-rouge">Null</code> is a mistake but <code class="language-plaintext highlighter-rouge">Nothing</code> is alright? Yes. No.</p>

<p>You see <code class="language-plaintext highlighter-rouge">Null</code> itself is not the problem: When something has no value, it <em>is</em> <code class="language-plaintext highlighter-rouge">Null</code> <sup><a href="#footnote1">[1]</a></sup>. That is <em>correct</em>. It ISN’T better if we ignored that correctness and use a <code class="language-plaintext highlighter-rouge">0</code> instead, or <code class="language-plaintext highlighter-rouge">""</code> empty string, or <code class="language-plaintext highlighter-rouge">0001-01-01 00:00:00 +0000 UTC</code>!</p>

<blockquote>
  <p>ASIDE: Go programmers, life is not a binary choice between “uninitialized C variable causes core dump” vs “implicit zero values then”! <sup><a href="#footnote2">[2]</a></sup> Zero values are not our friend: When we unmarshal a json string without error and some numbers are <code class="language-plaintext highlighter-rouge">0</code>, how do we know if the values were missing (not good) or the decoder saw <code class="language-plaintext highlighter-rouge">0</code> in the json string and decoded it (good) ? We don’t know <sup><a href="#footnote3">[3]</a></sup>. Null errors can still be located and fixed, but we can’t locate zero value data corruption like this. And if you argue <em>“Oh but there’s no difference between an absent value and 0”</em> 👀 you should know that’s your Stockholm syndrome talking. <sup><a href="#footnote4">[4]</a></sup></p>
</blockquote>

<p><code class="language-plaintext highlighter-rouge">Null</code> becomes a problem ONLY IF your language lets you use it like it isn’t</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>maybeUser = findUser users 42 // a nullable reference to User value
maybeUser.name                // your compiler is happy; runtime not so much
</code></pre></div></div>

<p>This convenience of referrencing the <code class="language-plaintext highlighter-rouge">name</code> attribute on a possibly null <code class="language-plaintext highlighter-rouge">user</code> — THAT is the billion-dollar mistake: the null <em>reference</em>. Not <code class="language-plaintext highlighter-rouge">Null</code> itself.</p>

<p>Back to the example of <code class="language-plaintext highlighter-rouge">Nothing</code> being the same as <code class="language-plaintext highlighter-rouge">Null</code> (they are!). The difference is that, in some languages, we can’t use a <code class="language-plaintext highlighter-rouge">maybeUser</code> value like a <code class="language-plaintext highlighter-rouge">User</code></p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>maybeUser = findUser users 42
maybeUser.name
^^^^^^^^^---- compiler error!
</code></pre></div></div>

<p>The only thing we can do with a <code class="language-plaintext highlighter-rouge">Maybe</code> value is to deal with each specific code path</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>case maybeUser of
    Just u -&gt;
        "Winner is " ++ u.name # guaranteed safe access

    Nothing -&gt;
        "Nobody won"
</code></pre></div></div>

<p>Inconvenient, but the guarantees are bliss.</p>

<p>So, boys and girls, don’t avoid <code class="language-plaintext highlighter-rouge">Null</code> itself. Don’t make your table column <code class="language-plaintext highlighter-rouge">NOT NULL</code> because of the reputation. Don’t use an inaccurate zero value in place of the correct one. If a column is indeed nullable, be brave and make it nullable.</p>

<p>Add a Null check linter? Change your programming language? Anything palatable to you, but let the Nulls be Nulls.</p>

<p><sub><a name="footnote1">[1]</a> Or Nothing, nil, et al.</sub><br /></p>

<p><sub><a name="footnote2">[2]</a> The simplest correct solution to “uninitialized C variable causes core dump” is to require initialization. A little bit of typing goes a long way.</sub><br /></p>

<p><sub><a name="footnote3">[3]</a> Unless you look into the json string again. 🤦‍♂️</sub><br /></p>

<p><sub><a name="footnote4">[4]</a> After all these sacrifices of correctness for implicit zero values to protect against core dump, Go programmers <em>still</em> have to grapple with the nil zero value and all the same nasties as Null… and worse: <a href="https://go.dev/doc/faq#nil_error">why is my nil error value not equal to nil?</a>. 🤣</sub><br /></p>]]></content><author><name>choonkeat</name></author><summary type="html"><![CDATA[For the longest time, I was told Null was bad: “Null the billion-dollar mistake”]]></summary></entry><entry><title type="html">Re: REPL</title><link href="/weblog/2022/03/regarding-repl.html" rel="alternate" type="text/html" title="Re: REPL" /><published>2022-03-04T00:00:00+00:00</published><updated>2022-03-04T00:00:00+00:00</updated><id>/weblog/2022/03/regarding-repl</id><content type="html" xml:base="/weblog/2022/03/regarding-repl.html"><![CDATA[<p><em>This is a followup to <a href="/weblog/2022/03/regarding-the-user-wizard-scenario.html">Re: The User Wizard Scenario</a> and <a href="/weblog/2022/03/regarding2-statically-typing-big-erratic-json.html">Re: Statically Typing Big Erratic JSON</a></em></p>

<blockquote>
  <p><a href="https://twitter.com/ericnormand/status/1499053983050125315">I like the idea of using a Dict until you’re ready to enforce types. It’s similar to what I suggest at the end….</a>
In the second post, it seems like you haven’t addressed what I consider the root of the problem, which is discovery….
But it is one of the pains that Clojure addresses by bundling dynamic typing with REPL-driven development.</p>
</blockquote>

<p>I realise we were almost talking past each other! I <a href="/weblog/2022/03/regarding2-statically-typing-big-erratic-json.html">had noted in passing</a> the advantage of dynamic types during exploration, citing <code class="language-plaintext highlighter-rouge">JSON.parse</code> and Eric Normand mentioned liking the idea of using a <code class="language-plaintext highlighter-rouge">Dict</code> until we’re ready to enforce. But those two points carry more significance for each party than the other acknowledged! Let’s dig into it instead!</p>

<p>But first,</p>

<p><strong>Q: Does Elm come with a powerful library for working with Dict values (like Clojure does)?</strong></p>

<p>Unfortunately though the <a href="https://package.elm-lang.org/packages/elm/core/latest/Dict">functions</a> are <a href="https://package.elm-lang.org/packages/elm-community/dict-extra/latest/">enough</a>, the … *drum roll*… <em>type</em> is not flexible enough 🙈. Keys are limited <code class="language-plaintext highlighter-rouge">comparable</code> types (hardcoded in Elm), and since values must be the same type, nesting <code class="language-plaintext highlighter-rouge">Dict</code> requires wrapping with something like <code class="language-plaintext highlighter-rouge">Tree a = Node a | Tree a</code>.</p>

<h4 id="repl"><strong>REPL</strong></h4>

<p>It’s definitely more productive in a dynamic language especially with one equipped with a more powerful repl than usual, eg Clojure. I imagine asking the repl to assign the response into a variable. Then work on this variable until I get what I want from it, and when it worked, copy/paste/save the repl code into my app, done!</p>

<p>For my workflow, I use the raw JSON to TDD my decoder as <a href="https://twitter.com/ericnormand/status/1499055989240176642">Eric Normand had described</a>. However, the feedback loop on test-on-file-save, at least for Elm, is not shabby <sup><a href="#footnote1">[1]</a></sup>.</p>

<p>I suspect the main difference could be this:</p>
<ul>
  <li>the repl dev is happy to get working code speedily by the end of it (getting from A to B fast)</li>
  <li>whereas decoder dev feels happy to have an external input defined as type by the end of it (sure-footed).</li>
</ul>

<p>However I feel the speed difference of this activity is in <em>minutes</em><sup><a href="#footnote2">[2]</a></sup>, but the speed difference later on can easily be <em>hours</em>…</p>

<p><strong>Q: How do we deal with changes after that? e.g. some fields turns out to be optional, etc.</strong></p>

<p>For decoder dev, errors happen when decoder reaches unexpected character of the input. So errors can state how their expectation failed: expect “email” field to be string (but it wasn’t). This allows us to zoom in to the “email” field decoder and start TDDing with the new input variant. Fixed.</p>

<p>For repl dev, if we jump immediately to thinking about fixing the parsing function, the difference there isn’t huge either. While manually stepping through the <em>function body</em> (or comparing old json with new json) to locate the problem is a little tedious but that’s still the happy scenario.</p>

<p>The real scenarios that decoder devs are fending off are all those runtime errors that pops up in places that doesn’t make sense. Tracing why such values are in a bad state takes a lot of time &amp; effort in a dynamically typed system: there are so many code paths? across subsystems? It can take hours before we discover the particular parsing function to fix.</p>

<h4 id="boundary--enforcement"><strong>Boundary &amp; Enforcement</strong></h4>

<blockquote>
  <p>I like idea of using a Dict until we’re ready to enforce</p>
</blockquote>

<p>This is more significant to me than an idea to apply for a particular scenario: It’s the fact that entire system is enforced: every tiny part is always locked in and enforced with other tiny parts regardless whether I remember to do it or not. This brings benefits I’d not experienced before non-pure type fp languages:</p>

<ul>
  <li>I am sure all affected areas of code are included in every PR (from myself or anyone else in the team), see <a href="https://twitter.com/choonkeat/status/1494480136036810755">thread</a></li>
  <li>Big bold refactors are safe and feedback is as fast as the Elm compiler. This is unlike when I didn’t have such a type system and compiler, invariants were upheld by a lot of tests. Big refactors means probably only integration tests survive and test code is a real burden to bring along during such refactors (so maybe don’t write them? don’t port them?)</li>
  <li>This all means I don’t have to get my designs “correct” off the bat. Especially in a startup, where we are always discovering something new about our domain, what are our odds? So I can code dirty first because cleaning up later is easier here?</li>
</ul>

<p>I’d mentioned “sure-footed” in an earlier paragraph, but <a href="https://discourse.elm-lang.org/t/what-are-your-favorite-things-about-elm/6947/71">here’s my longer description of what that meant</a>:</p>

<blockquote>
  <p>With Elm, I could take a sure-footed approach to problems that I might have previously felt is too hard for me. My Elm solution to each small part cumulates to the final solution without requiring me to keep revisiting at every step (because it’s “proven”). And the best part is, after I’ve crossed the finishing line &amp; gotten everything working, tidying up my entire solution is a safe and mechanical process. Confidence++</p>
</blockquote>

<p>This applies to both getting things to work <em>in the first place</em> but especially to <em>managing changes later</em>; no unnecessary revisits. That’s what I’m giving up the discovery speed for.</p>

<p>Then again “giving up” sounds harsh since I <em>can</em> improve and reach <em>reasonably good productivity</em> for discovery too. On the other hand, I <em>feel</em> without such pure &amp; statically typed language supporting me so completely, the sure-footedness described above cannot be achieved by myself.</p>

<hr />

<p><sub><a name="footnote1">[1]</a> I was developing a Slack bot in a place with no wifi, and I just wrote decoders based on JSON samples I’d downloaded earlier from their docs site, then I write code that worked with those types, fixing bugs along the way until it compiles. When I’m finally back online, I tried my bot… and it worked the first run! I’m not such a meticulous person so credits totally goes to the Elm compiler and its type system.</sub><br /></p>

<p><sub><a name="footnote2">[2]</a> This should possibly be the understatement akin to SVN users downplaying the speed of Git, while Git rightfully claims <a href="https://youtu.be/4XpnKHJAok8">it’s so freaking fast that you actually use it differently</a>. Must be giddying! I should want to experience such repl workflow someday.</sub><br /></p>]]></content><author><name>choonkeat</name></author><summary type="html"><![CDATA[This is a followup to Re: The User Wizard Scenario and Re: Statically Typing Big Erratic JSON]]></summary></entry><entry><title type="html">Re: The User Wizard Scenario</title><link href="/weblog/2022/03/regarding-the-user-wizard-scenario.html" rel="alternate" type="text/html" title="Re: The User Wizard Scenario" /><published>2022-03-01T00:00:00+00:00</published><updated>2022-03-01T00:00:00+00:00</updated><id>/weblog/2022/03/regarding-the-user-wizard-scenario</id><content type="html" xml:base="/weblog/2022/03/regarding-the-user-wizard-scenario.html"><![CDATA[<p>So Eric Normand had started a conversation to compare notes on dynamic types and static types. You can find it at <a href="https://lispcast.com/user-wizard-scenario/">https://lispcast.com/user-wizard-scenario/</a>.</p>

<p>I liked the very concrete and real scenario he picked. I agree with the volatility observed but I also want to note early on that it isn’t productive to respond to any particular solutions for each step: situation do arise, we developers handle it with the information and time we have at hand.</p>

<p>The final solution in his scenario – at the cost of a bit of type safety – was to use a <code class="language-plaintext highlighter-rouge">Map</code>. Since that’s what a dynamically typed language (e.g. Clojure) would’ve chosen from the start, it begs the question: why not start there in the first place [instead of opting for static types and hoping that volatility doesn’t hit]? Which leads to the statement:</p>

<blockquote>
  <p>sufficiently volatile data prefers a flexible model with optional runtime checks.</p>
</blockquote>

<h3 id="so-how">So how?</h3>

<p>I’ll disclaim upfront that I’ve in fact chosen to use a <code class="language-plaintext highlighter-rouge">Map</code> (aka <code class="language-plaintext highlighter-rouge">Dict</code>) most of the time, when dealing with forms, in my Elm apps. This choice is commonly judged as having given up on type safety.</p>

<p>That’s true but <strong>only if</strong> we stop there!</p>

<p>Once we have a “bag of attributes” backing our form input values, add a function to parse it into the desired type or error messages if any.</p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">parse</span> <span class="p">:</span> <span class="kt">Dict</span> <span class="o">-&gt;</span> <span class="kt">Result</span> <span class="kt">Errors</span> <span class="kt">UserInput</span>
</code></pre></div></div>

<p>If valid, we return the value, e.g. <code class="language-plaintext highlighter-rouge">Ok { email = "bob@example.com" }</code>. Otherwise, return errors, e.g. <code class="language-plaintext highlighter-rouge">Err [ ( Email, "is invalid" ) ]</code>. With the return value, you can enable the submit button when <code class="language-plaintext highlighter-rouge">userInput</code> is present, disable when absent, extract and display input field errors alongside the input fields. Not only are these validation rules consolidated into a single place, we can even use this same pure function on the frontend and the backend too.</p>

<p>Our form can change as much as needed by requirements, we’ll just update <code class="language-plaintext highlighter-rouge">parse</code> accordingly.</p>

<h3 id="managing-boundaries">Managing boundaries</h3>

<p>The main idea here is to treat a form as a whole, and to consider it as external input, like a file. Drawing a line between that external world and the rest of our system. This isn’t specific to managing HTML forms.</p>

<p>Just because one edge of the system is volatile, doesn’t mean the rest of the system have to be as volatile. Just because we are looser with types on the periphery doesn’t mean we have to bear the cost in the rest of our system. We can continue to benefit from the cosy assurance of statically type checked code within these walls we draw.</p>

<p>This explicit management of boundaries, like managed effects, is what I appreciate from a statically typed fp language.</p>

<h3 id="some-explorations">Some explorations</h3>

<p><strong>Q: I want to save each step of partial attributes into the db</strong></p>

<p>I would save the key value <code class="language-plaintext highlighter-rouge">Dict</code> data in each step <em>as-is</em>, without a custom <code class="language-plaintext highlighter-rouge">parse</code> defined for each step: it’s pointless, the entire thing is incomplete anyways. Don’t forget however, we can still use the same <code class="language-plaintext highlighter-rouge">parse</code> to obtain the complete list of errors, but only surface the errors relevant to the current Step’s UI. At the final step, I would require <code class="language-plaintext highlighter-rouge">parse</code> to succeed fully.</p>

<p><strong>Q: What if some form inputs need the values from other form inputs?</strong></p>

<p>For example, an autocompletion list need to know which items have already been added (exclude from suggestions), and the text that is typed so far (filter the suggestions).</p>

<p>We can write a function that returns a <code class="language-plaintext highlighter-rouge">Suggestions</code> value based on those two earlier fields inside our <code class="language-plaintext highlighter-rouge">Dict</code></p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">suggestions</span> <span class="p">:</span> <span class="kt">Dict</span> <span class="o">-&gt;</span> <span class="kt">Suggestions</span>
</code></pre></div></div>

<p>Our autocomplete widget should then require a suggestions value in order to render</p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">widget</span> <span class="p">:</span> <span class="kt">Suggestions</span> <span class="o">-&gt;</span> <span class="kt">Html</span>
</code></pre></div></div>

<p><strong>Q: You mentioned we could use our pure <code class="language-plaintext highlighter-rouge">parse</code> function in the frontend and the backend. What if some of my validation rules are not pure and needed a check against our database?</strong></p>

<p>Extend the <code class="language-plaintext highlighter-rouge">parse</code> function to account for the new <code class="language-plaintext highlighter-rouge">ExternalData</code> input, e.g. <code class="language-plaintext highlighter-rouge">parse : ExternalData -&gt; Dict -&gt; Result Errors UserInput</code> and run the <code class="language-plaintext highlighter-rouge">parse</code> function inside the procedure that queries for those external data. e.g. Client-side code can call upon an HTTP API and then supply the response data to the <code class="language-plaintext highlighter-rouge">parse</code> function along with the form data.</p>

<p>If it’s not feasible in our scenario to supply such data to the Client-side, then we have to admit it can’t be checked by the Client-side however we do it. So, supply an empty value for <code class="language-plaintext highlighter-rouge">ExternalData</code> to skip that validation on the Client-side; we can still have Client-side validation for the other fields + the full validation can still happen with the same function on Server-side.</p>

<p><em>UPDATE: a followup post <a href="/weblog/2022/03/regarding2-statically-typing-big-erratic-json.html">Re: Statically Typing Big Erratic JSON</a></em></p>]]></content><author><name>choonkeat</name></author><summary type="html"><![CDATA[So Eric Normand had started a conversation to compare notes on dynamic types and static types. You can find it at https://lispcast.com/user-wizard-scenario/.]]></summary></entry><entry><title type="html">Re: Statically Typing Big Erratic JSON</title><link href="/weblog/2022/03/regarding2-statically-typing-big-erratic-json.html" rel="alternate" type="text/html" title="Re: Statically Typing Big Erratic JSON" /><published>2022-03-01T00:00:00+00:00</published><updated>2022-03-01T00:00:00+00:00</updated><id>/weblog/2022/03/regarding2-statically-typing-big-erratic-json</id><content type="html" xml:base="/weblog/2022/03/regarding2-statically-typing-big-erratic-json.html"><![CDATA[<p>Related to my previous post <a href="/weblog/2022/03/regarding-the-user-wizard-scenario.html">Re: The User Wizard Scenario</a>, I’d like to address another scenario cited as reasons to favor dynamic types:</p>

<blockquote>
  <p>Some APIs have a huge JSON format. But we might only need a few fields. Some fields could be <code class="language-plaintext highlighter-rouge">false</code> sometimes but a list of strings other times. Some fields should even be parsed depending on some other fields in the JSON. To statically type this is very tedious and the type might not be understandable anymore.</p>
</blockquote>

<p>When it comes to parsing JSON, there are reasons to favor dynamic types (who doesn’t like <code class="language-plaintext highlighter-rouge">JSON.parse</code> when exploring data?), but I think the reasons above are actually reasons <em>to favor static types</em>.</p>

<blockquote>
  <p><strong>1. “Some APIs have a huge JSON format. But we might only need a few fields.”</strong></p>
</blockquote>

<p>In a dynamically typed language, we’d simply ignore the rest of the json and use what we need</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">handle</span><span class="p">(</span><span class="nx">jsonString</span><span class="p">)</span> <span class="p">{</span>
    <span class="kd">let</span> <span class="nx">user</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">jsonString</span><span class="p">)</span>
    <span class="nx">store</span><span class="p">(</span><span class="nx">user</span><span class="p">);</span>
<span class="p">}</span>

<span class="kd">function</span> <span class="nx">store</span><span class="p">({</span> <span class="nx">email</span> <span class="p">})</span> <span class="p">{</span>
    <span class="c1">// do stuff with `email`</span>
<span class="p">}</span>
</code></pre></div></div>

<p>In a statically typed language, we’d simply ignore the rest of the json and decode what we need</p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">userDecoder</span> <span class="o">=</span>
    <span class="kt">Json</span><span class="o">.</span><span class="kt">Decode</span><span class="o">.</span><span class="n">map</span> <span class="p">(</span><span class="o">\</span><span class="n">s</span> <span class="o">-&gt;</span> <span class="p">{</span> <span class="n">email</span> <span class="o">=</span> <span class="n">s</span> <span class="p">})</span>
        <span class="p">(</span><span class="n">field</span> <span class="s">"</span><span class="s2">email"</span> <span class="n">string</span><span class="p">)</span> <span class="c1">-- only decode `"email"` field</span>

<span class="n">handle</span> <span class="n">jsonString</span> <span class="o">=</span>
    <span class="k">case</span> <span class="n">decodeString</span> <span class="n">userDecoder</span> <span class="n">jsonString</span> <span class="k">of</span>
        <span class="kt">Ok</span> <span class="n">user</span> <span class="o">-&gt;</span>
            <span class="n">store</span> <span class="n">user</span>

        <span class="kt">Err</span> <span class="n">jsonError</span> <span class="o">-&gt;</span>      <span class="c1">-- runtime error for</span>
            <span class="n">handle</span> <span class="n">jsonError</span>  <span class="c1">-- dynamically typed langs</span>

<span class="n">store</span> <span class="p">{</span> <span class="n">email</span> <span class="p">}</span> <span class="o">=</span>
    <span class="c1">-- do stuff with `email`</span>
</code></pre></div></div>

<p>The added benefit is, if <code class="language-plaintext highlighter-rouge">email</code> field is anything but a <code class="language-plaintext highlighter-rouge">String</code>, we would’ve gotten a parsing error early and have code to deal with it upfront. Whereas, in the JS example, we might not know that our <code class="language-plaintext highlighter-rouge">email</code> is <code class="language-plaintext highlighter-rouge">null</code> or <code class="language-plaintext highlighter-rouge">42</code> until much later in the system (a background job 3 days later?).</p>

<p>Troubleshooting the source of bad values that causes a crash is tedious and (given decoder pattern exists) an unnecessary trouble imo.</p>

<p>Even if we implemented decoders in JS, we still can’t reap its benefits in the rest of our dynamically typed system. We need to manually add assertions everywhere that matters (that we remember to). <code class="language-plaintext highlighter-rouge">welcomeEmail( { email })</code> ? hmm, add an assertion just to be safe</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">welcomeEmail</span><span class="p">(</span> <span class="p">{</span> <span class="nx">email</span> <span class="p">})</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">email</span> <span class="o">!==</span> <span class="dl">'</span><span class="s1">string</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
</code></pre></div></div>

<p>(Btw, what can we effectively <em>do</em> with an invalid value here? <a href="/weblog/2021/05/awkward-error-handling-is-a-smell.html">Dealing with errors deep in the system is awkward</a>)</p>

<blockquote>
  <p>Isn’t writing type signatures everywhere equivalent to scattering assertions everywhere?</p>
</blockquote>

<p>No. Types are checked at compile time over the entire codebase, while assertions checks at runtime… and <em>only when</em> that line is run. 5th page of a form wizard? Code gotta run until there, in the right condition, to find out about it.</p>

<blockquote>
  <p>We can <em>add</em> type signatures in some dynamically typed languages</p>
</blockquote>

<p>Ironically, type inferred languages like Haskell had long allowed type signatures to even be <em>removed</em> and still keep the benefit!</p>

<p>Basically one provides <em>“where do you want to type check”</em> vs the other provides <em>“everything is type checked”</em>. I think it’s safe to say while we might prefer some control over what we want to type check in our code, we’d also prefer other people’s code to be fully type checked where possible 😆 … as they say, <em><a href="https://research.swtch.com/vgo-eng">“Software engineering is what happens to programming when you add time and other programmers.”</a></em></p>

<blockquote>
  <p><strong>2. “Some fields could be <code class="language-plaintext highlighter-rouge">false</code> sometimes but a list of strings other times. Some fields should even be parsed depending on some other fields in the JSON.”</strong></p>
</blockquote>

<p>Since the said JSON is beyond our control, we just have to deal with it. There is no escape.</p>

<p>In a dynamically typed language, we do whatever is necessary</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">handle</span><span class="p">(</span><span class="nx">jsonString</span><span class="p">)</span> <span class="p">{</span>
    <span class="kd">let</span> <span class="nx">user</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">jsonString</span><span class="p">)</span>

    <span class="c1">// `false` just means no preferences</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">user</span><span class="p">.</span><span class="nx">preferences</span> <span class="o">===</span> <span class="kc">false</span><span class="p">)</span> <span class="nx">user</span><span class="p">.</span><span class="nx">preferences</span> <span class="o">=</span> <span class="p">[]</span>

    <span class="c1">// `state` determines what `date` actually means</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">user</span><span class="p">.</span><span class="nx">state</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">deleted</span><span class="dl">'</span><span class="p">)</span> <span class="nx">user</span><span class="p">.</span><span class="nx">deletedAt</span> <span class="o">=</span> <span class="nx">user</span><span class="p">.</span><span class="nx">date</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">user</span><span class="p">.</span><span class="nx">state</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">active</span><span class="dl">'</span><span class="p">)</span>  <span class="nx">user</span><span class="p">.</span><span class="nx">lastLoginAt</span> <span class="o">=</span> <span class="nx">user</span><span class="p">.</span><span class="nx">date</span>

    <span class="nx">store</span><span class="p">(</span><span class="nx">user</span><span class="p">);</span>
<span class="p">}</span>

<span class="kd">function</span> <span class="nx">store</span><span class="p">({</span> <span class="nx">email</span><span class="p">,</span> <span class="nx">preferences</span><span class="p">,</span> <span class="nx">deletedAt</span><span class="p">,</span> <span class="nx">lastLoginAt</span> <span class="p">})</span> <span class="p">{</span>
    <span class="c1">// do stuff with fields</span>
<span class="p">}</span>
</code></pre></div></div>

<p>In a dynamically typed language, we do whatever is necessary but inside the decoders.</p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">preferenceDecoder</span> <span class="o">=</span>
    <span class="kt">Json</span><span class="o">.</span><span class="kt">Decode</span><span class="o">.</span><span class="n">oneOf</span>
        <span class="p">[</span> <span class="n">map</span> <span class="p">(</span><span class="n">always</span> <span class="p">[])</span> <span class="n">decodeFalse</span> <span class="c1">-- `false` found? decode as an empty list []</span>
        <span class="o">,</span> <span class="n">list</span> <span class="n">string</span>                 <span class="c1">-- otherwise, decode as list of string</span>
        <span class="p">]</span>

<span class="n">dateDecoder</span> <span class="o">=</span>
    <span class="kt">Json</span><span class="o">.</span><span class="kt">Decode</span><span class="o">.</span><span class="n">map2</span> <span class="n">datesFromState</span>
        <span class="c1">-- decode both json fields `state` and `date`</span>
        <span class="c1">-- then hand it off to `datesFromState` to decide</span>
        <span class="p">(</span><span class="kt">Json</span><span class="o">.</span><span class="kt">Decode</span><span class="o">.</span><span class="n">field</span> <span class="s">"</span><span class="s2">state"</span> <span class="n">string</span><span class="p">)</span>
        <span class="p">(</span><span class="kt">Json</span><span class="o">.</span><span class="kt">Decode</span><span class="o">.</span><span class="n">field</span> <span class="s">"</span><span class="s2">date"</span> <span class="n">isoDate</span><span class="p">)</span>

<span class="n">datesFromState</span> <span class="n">stateString</span> <span class="n">date</span> <span class="o">=</span>
    <span class="k">case</span> <span class="n">stateString</span> <span class="k">of</span>
        <span class="s">"</span><span class="s2">deleted"</span> <span class="o">-&gt;</span>
            <span class="p">{</span> <span class="n">deletedAt</span> <span class="o">=</span> <span class="kt">Just</span> <span class="n">date</span><span class="o">,</span> <span class="n">lastLoginAt</span> <span class="o">=</span> <span class="kt">Nothing</span>   <span class="p">}</span>
        <span class="s">"</span><span class="s2">active"</span> <span class="o">-&gt;</span>
            <span class="p">{</span> <span class="n">deletedAt</span> <span class="o">=</span> <span class="kt">Nothing</span><span class="o">,</span>   <span class="n">lastLoginAt</span> <span class="o">=</span> <span class="kt">Just</span> <span class="n">date</span> <span class="p">}</span>
        <span class="n">_</span> <span class="o">-&gt;</span>
            <span class="p">{</span> <span class="n">deletedAt</span> <span class="o">=</span> <span class="kt">Nothing</span><span class="o">,</span>   <span class="n">lastLoginAt</span> <span class="o">=</span> <span class="kt">Nothing</span>   <span class="p">}</span>

<span class="c1">-- We compose our `userDecoder` with these decoders</span>

<span class="n">userDecoder</span> <span class="o">=</span>
    <span class="kt">Json</span><span class="o">.</span><span class="kt">Decode</span><span class="o">.</span><span class="n">map3</span> <span class="n">buildUser</span>
        <span class="c1">-- decode the fields then assemble with `buildUser`</span>
        <span class="p">(</span><span class="n">field</span> <span class="s">"</span><span class="s2">email"</span> <span class="n">string</span><span class="p">)</span>
        <span class="p">(</span><span class="n">field</span> <span class="s">"</span><span class="s2">preferences"</span> <span class="n">preferenceDecoder</span><span class="p">)</span>
        <span class="p">(</span><span class="n">dateDecoder</span><span class="p">)</span>

<span class="n">buildUser</span> <span class="n">email</span> <span class="n">preferences</span> <span class="p">{</span> <span class="n">deletedAt</span><span class="o">,</span> <span class="n">lastLoginAt</span> <span class="p">}</span> <span class="o">=</span>
    <span class="p">{</span> <span class="n">email</span> <span class="o">=</span> <span class="n">email</span>
    <span class="o">,</span> <span class="n">preferences</span> <span class="o">=</span> <span class="n">preferences</span>
    <span class="o">,</span> <span class="n">deletedAt</span> <span class="o">=</span> <span class="n">deletedAt</span>
    <span class="o">,</span> <span class="n">lastLoginAt</span> <span class="o">=</span> <span class="n">lastLoginAt</span>
    <span class="p">}</span>

<span class="c1">-- Then we update the original snippet to mention the new fields</span>

<span class="n">handle</span> <span class="n">jsonString</span> <span class="o">=</span>
    <span class="k">case</span> <span class="n">decodeString</span> <span class="n">userDecoder</span> <span class="n">jsonString</span> <span class="k">of</span>
        <span class="kt">Ok</span> <span class="n">user</span> <span class="o">-&gt;</span>
            <span class="n">store</span> <span class="n">user</span>

        <span class="kt">Err</span> <span class="n">jsonError</span> <span class="o">-&gt;</span>
            <span class="n">handle</span> <span class="n">jsonError</span>

<span class="n">store</span> <span class="p">{</span> <span class="n">email</span><span class="o">,</span> <span class="n">preferences</span><span class="o">,</span> <span class="n">deletedAt</span><span class="o">,</span> <span class="n">lastLoginAt</span> <span class="p">}</span> <span class="o">=</span>
    <span class="c1">-- do stuff</span>
</code></pre></div></div>

<blockquote>
  <p><strong>3. To statically type this is very tedious and the type might not be understandable anymore.</strong></p>
</blockquote>

<p>While there is obviously more lines of code, but note that the <em>type</em> of <code class="language-plaintext highlighter-rouge">User</code> is as clean. The messy reality of the JSON rules are captured and compartmentalized inside individual decoder functions, very testable out of the box too. The rest of the system can use this clean <code class="language-plaintext highlighter-rouge">User</code> type in abandon, with the compiler ensuring there are no stray threads.</p>

<p><em>UPDATE: a followup post <a href="/weblog/2022/03/regarding-repl.html">Re: REPL</a></em></p>]]></content><author><name>choonkeat</name></author><summary type="html"><![CDATA[Related to my previous post Re: The User Wizard Scenario, I’d like to address another scenario cited as reasons to favor dynamic types:]]></summary></entry><entry><title type="html">Awkward error handling is a code smell</title><link href="/weblog/2021/05/awkward-error-handling-is-a-smell.html" rel="alternate" type="text/html" title="Awkward error handling is a code smell" /><published>2021-05-16T00:00:00+00:00</published><updated>2021-05-16T00:00:00+00:00</updated><id>/weblog/2021/05/awkward-error-handling-is-a-smell</id><content type="html" xml:base="/weblog/2021/05/awkward-error-handling-is-a-smell.html"><![CDATA[<p>Say you have a need to pretty print an email address string inside one of your view component and you have the urge to say <em>hey, this pretty printer component shouldn’t print if the email address isn’t valid, like a blank username</em>. The options to error out seem awkward and not great…</p>

<p>Stop. That’s not a good place to <em>start</em> being concern if a value is valid.</p>

<p>If you have to push out something fast, I’d recommend just go ahead and pretty print the given value in a best-effort manner; no error handling. Then find time to refactor.</p>

<p>But refactor to what? Handle the validation concern MUCH earlier in the system: upon receiving the email string (from db? from api response? from user input?), parse it into a proper data structure, e.g. <code class="language-plaintext highlighter-rouge">EmailAddress</code>. If the parse failed, you’ll find that error handling is very natural (db query error, api response invalid, user input error). If parsing succeeded, now pass this <code class="language-plaintext highlighter-rouge">EmailAddress</code> type value around your entire system instead of that original email string.</p>

<p>Once your entire system is refactored to deal with <code class="language-plaintext highlighter-rouge">EmailAddress</code> instead of email address strings, you’ll find your original problem (what if the email I want to pretty print is invalid?) simply does not exist anymore. An even stronger guarantee can be had if your language can enforce that <code class="language-plaintext highlighter-rouge">EmailAddress</code> value can only ever be created via that function that parses a string, and that the <code class="language-plaintext highlighter-rouge">EmailAddress</code> value cannot be mutated.</p>

<p>Whenever you feel a strain in your options to handle an error condition, ask yourself if you’re trying to deal with it at the wrong level; can you deal with it earlier? Chances are, you need to <a href="https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/">Parse, Don’t Validate</a>.</p>]]></content><author><name>choonkeat</name></author><summary type="html"><![CDATA[Say you have a need to pretty print an email address string inside one of your view component and you have the urge to say hey, this pretty printer component shouldn’t print if the email address isn’t valid, like a blank username. The options to error out seem awkward and not great…]]></summary></entry><entry><title type="html">Make bugs into type errors</title><link href="/weblog/2020/08/make-bugs-into-type-errors.html" rel="alternate" type="text/html" title="Make bugs into type errors" /><published>2020-08-26T00:00:00+00:00</published><updated>2020-08-26T00:00:00+00:00</updated><id>/weblog/2020/08/make-bugs-into-type-errors</id><content type="html" xml:base="/weblog/2020/08/make-bugs-into-type-errors.html"><![CDATA[<p>It’s very common for frontend apps to fetch remote data to update sections of the UI. For example</p>

<ol>
  <li>user click and triggers a <code class="language-plaintext highlighter-rouge">LoadThing</code> message which fires off a network call, <code class="language-plaintext highlighter-rouge">getThing</code></li>
  <li>if it was successful, show data</li>
  <li>otherwise, show error</li>
</ol>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">update</span> <span class="p">:</span> <span class="kt">Msg</span> <span class="o">-&gt;</span> <span class="kt">Model</span> <span class="o">-&gt;</span> <span class="p">(</span> <span class="kt">Model</span><span class="o">,</span> <span class="kt">Cmd</span> <span class="kt">Msg</span> <span class="p">)</span>
<span class="n">update</span> <span class="n">msg</span> <span class="n">model</span> <span class="o">=</span>
    <span class="k">case</span> <span class="n">msg</span> <span class="k">of</span>
        <span class="kt">LoadThing</span> <span class="n">num</span> <span class="o">-&gt;</span>
            <span class="p">(</span> <span class="n">model</span>
            <span class="o">,</span> <span class="kt">Task</span><span class="o">.</span><span class="n">attempt</span> <span class="kt">OnThing</span> <span class="p">(</span><span class="n">getThing</span> <span class="n">num</span><span class="p">)</span> <span class="p">)</span>

        <span class="kt">OnThing</span> <span class="p">(</span><span class="kt">Err</span> <span class="n">err</span><span class="p">)</span> <span class="o">-&gt;</span>
            <span class="p">(</span> <span class="p">{</span> <span class="n">model</span>
                <span class="o">|</span> <span class="n">alert</span> <span class="o">=</span> <span class="kt">Just</span> <span class="p">(</span><span class="n">httpErrorString</span> <span class="n">err</span><span class="p">)</span>
              <span class="p">}</span>
            <span class="o">,</span> <span class="kt">Cmd</span><span class="o">.</span><span class="n">none</span> <span class="p">)</span>

        <span class="kt">OnThing</span> <span class="p">(</span><span class="kt">Ok</span> <span class="n">thing</span><span class="p">)</span> <span class="o">-&gt;</span>
            <span class="p">(</span> <span class="p">{</span> <span class="n">model</span>
                <span class="o">|</span> <span class="n">thing</span> <span class="o">=</span> <span class="kt">RemoteData</span><span class="o">.</span><span class="kt">Success</span> <span class="n">thing</span>
              <span class="p">}</span>
            <span class="o">,</span> <span class="kt">Cmd</span><span class="o">.</span><span class="n">none</span> <span class="p">)</span>
</code></pre></div></div>

<p>Did you notice a bug?</p>

<p>A very common bug here is: we’ve forgotten to set the loading status before firing off <code class="language-plaintext highlighter-rouge">getThing</code>. And even after we fix <em>that</em>, we might realise days later that we’ve forgotten to unset the loading state upon getting an error. Whack-a-mole. As the number of APIs grow, and changes happen over time, preventing such bugs will only become harder and harder.</p>

<p>Wait, there’s a request to update the api, now we should update <code class="language-plaintext highlighter-rouge">model.category</code> from the api response too, merge PR &amp; deploy. Oops, we forgot to set <code class="language-plaintext highlighter-rouge">category = Loading</code> 😩 Again 😖</p>

<p>Is our constant vigilance the only protection?</p>

<p><img width="294" alt="Screenshot 2020-08-26 at 10 34 10 PM" src="https://user-images.githubusercontent.com/473/91317369-8cdfd980-e7ec-11ea-8668-96d959898f17.png" /></p>

<p>As a code reviewer, I’d prefer the answer to be: no.</p>

<blockquote>
  <p><a href="https://twitter.com/mattoflambda/status/1008735243581288449">make bugs into type errors - @mattoflambda</a></p>
</blockquote>

<p>Well, since we’re trying to coordinate the state changes of request and response activities for each API, let’s unify them into a sum type</p>

<h3 id="part-12">Part 1/2</h3>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="kt">RequestResponse</span> <span class="n">param</span> <span class="n">response</span>
    <span class="o">=</span> <span class="kt">Request</span> <span class="n">param</span>
    <span class="o">|</span> <span class="kt">Response</span> <span class="p">(</span><span class="kt">Result</span> <span class="kt">Http</span><span class="o">.</span><span class="kt">Error</span> <span class="n">response</span><span class="p">)</span>

<span class="k">type</span> <span class="kt">ApiMsg</span>
    <span class="o">=</span> <span class="kt">ThingApi</span> <span class="p">(</span><span class="kt">RequestResponse</span> <span class="kt">Int</span> <span class="kt">Thing</span><span class="p">)</span>
    <span class="c1">-- other APIs ...</span>
    <span class="c1">-- each API defines a `RequestResponse` with their own `param` and `response` types</span>
</code></pre></div></div>

<p>then we can nest all API related Msg,</p>

<div class="language-diff highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">type Msg
</span><span class="gd">-    = LoadThing Int
-    | OnThing (Result Http.Error Thing)
</span><span class="gi">+    = OnApiMsg ApiMsg
</span>     -- other button click etc Msg still remain
</code></pre></div></div>

<p>and delegate all API related state updates to a new <code class="language-plaintext highlighter-rouge">updateWithApiMsg</code></p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">update</span> <span class="p">:</span> <span class="kt">Msg</span> <span class="o">-&gt;</span> <span class="kt">Model</span> <span class="o">-&gt;</span> <span class="p">(</span> <span class="kt">Model</span><span class="o">,</span> <span class="kt">Cmd</span> <span class="kt">Msg</span> <span class="p">)</span>
<span class="n">update</span> <span class="n">msg</span> <span class="n">model</span> <span class="o">=</span>
    <span class="k">case</span> <span class="n">msg</span> <span class="k">of</span>
        <span class="kt">OnApiMsg</span> <span class="n">apiMsg</span> <span class="o">-&gt;</span>
            <span class="n">updateWithApiMsg</span> <span class="n">apiMsg</span> <span class="n">model</span>
        <span class="c1">-- other button click etc Msg still handled here</span>

<span class="n">updateWithApiMsg</span> <span class="p">:</span> <span class="kt">ApiMsg</span> <span class="o">-&gt;</span> <span class="kt">Model</span> <span class="o">-&gt;</span> <span class="p">(</span> <span class="kt">Model</span><span class="o">,</span> <span class="kt">Cmd</span> <span class="kt">Msg</span> <span class="p">)</span>
<span class="n">updateWithApiMsg</span> <span class="n">siteApi</span> <span class="n">model</span> <span class="o">=</span>
    <span class="k">case</span> <span class="n">siteApi</span> <span class="k">of</span>
        <span class="kt">ThingApi</span> <span class="n">requestResponse</span> <span class="o">-&gt;</span>
            <span class="k">case</span> <span class="n">requestResponse</span> <span class="k">of</span>
                <span class="kt">Request</span> <span class="n">num</span> <span class="o">-&gt;</span>
                    <span class="p">(</span> <span class="n">model</span>
                    <span class="o">,</span> <span class="n">requestCmd</span> <span class="kt">ThingApi</span> <span class="p">(</span><span class="n">getThing</span> <span class="n">num</span><span class="p">)</span> <span class="p">)</span>

                <span class="kt">Response</span> <span class="p">(</span><span class="kt">Err</span> <span class="n">err</span><span class="p">)</span> <span class="o">-&gt;</span>
                    <span class="p">(</span> <span class="p">{</span> <span class="n">model</span>
                        <span class="o">|</span> <span class="n">alert</span> <span class="o">=</span> <span class="kt">Just</span> <span class="p">(</span><span class="n">httpErrorString</span> <span class="n">err</span><span class="p">)</span>
                      <span class="p">}</span>
                    <span class="o">,</span> <span class="kt">Cmd</span><span class="o">.</span><span class="n">none</span> <span class="p">)</span>

                <span class="kt">Response</span> <span class="p">(</span><span class="kt">Ok</span> <span class="n">thing</span><span class="p">)</span> <span class="o">-&gt;</span>
                    <span class="p">(</span> <span class="p">{</span> <span class="n">model</span>
                        <span class="o">|</span> <span class="n">thing</span> <span class="o">=</span> <span class="kt">RemoteData</span><span class="o">.</span><span class="kt">Success</span> <span class="n">thing</span>
                      <span class="p">}</span>
                    <span class="o">,</span> <span class="kt">Cmd</span><span class="o">.</span><span class="n">none</span> <span class="p">)</span>

        <span class="c1">-- other APIs ...</span>
</code></pre></div></div>

<p>We’ve done a bunch of busy work but everything still compiles; we still have our bug?? Perfect. <em>Now</em>, we’re ready to make this bug a type error.</p>

<h3 id="part-22">Part 2/2</h3>

<p>Recall that what we’re trying to achieve is make sure we don’t forget to update the same set of model attributes for every stage of the API call (request, success, error). And each API will have their own set of model attributes.</p>

<blockquote>
  <p>All branches in a <code class="language-plaintext highlighter-rouge">case</code> must produce the same type of values. This way, no matter which branch we take, the result is always a consistent shape.</p>
</blockquote>

<p>Let’s rearrange our Elm code to take advantage of this</p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">updateWithApiMsg</span> <span class="p">:</span> <span class="kt">ApiMsg</span> <span class="o">-&gt;</span> <span class="kt">Model</span> <span class="o">-&gt;</span> <span class="p">(</span> <span class="kt">Model</span><span class="o">,</span> <span class="kt">Cmd</span> <span class="kt">Msg</span> <span class="p">)</span>
<span class="n">updateWithApiMsg</span> <span class="n">siteApi</span> <span class="n">model</span> <span class="o">=</span>
    <span class="k">case</span> <span class="n">siteApi</span> <span class="k">of</span>
        <span class="kt">ThingApi</span> <span class="n">requestResponse</span> <span class="o">-&gt;</span>
            <span class="k">let</span>
                <span class="c1">-- NOTE: `updated` is only a subset of our `Model` record type</span>
                <span class="c1">-- with only the fields that needs to be updated for `ThingApi`</span>
                <span class="p">(</span> <span class="n">updated</span><span class="o">,</span> <span class="n">cmd</span> <span class="p">)</span> <span class="o">=</span>
                    <span class="k">case</span> <span class="n">requestResponse</span> <span class="k">of</span>
                        <span class="kt">Request</span> <span class="n">num</span> <span class="o">-&gt;</span>
                            <span class="p">(</span> <span class="p">{}</span>
                            <span class="o">,</span> <span class="n">requestCmd</span> <span class="kt">ThingApi</span> <span class="p">(</span><span class="n">getThing</span> <span class="n">num</span><span class="p">)</span>
                            <span class="p">)</span>

                        <span class="kt">Response</span> <span class="p">(</span><span class="kt">Err</span> <span class="n">err</span><span class="p">)</span> <span class="o">-&gt;</span>
                            <span class="p">(</span> <span class="p">{</span> <span class="n">alert</span> <span class="o">=</span> <span class="kt">Just</span> <span class="p">(</span><span class="n">httpErrorString</span> <span class="n">err</span><span class="p">)</span> <span class="p">}</span>
                            <span class="o">,</span> <span class="kt">Cmd</span><span class="o">.</span><span class="n">none</span>
                            <span class="p">)</span>

                        <span class="kt">Response</span> <span class="p">(</span><span class="kt">Ok</span> <span class="n">thing</span><span class="p">)</span> <span class="o">-&gt;</span>
                            <span class="p">(</span> <span class="p">{</span> <span class="n">thing</span> <span class="o">=</span> <span class="kt">RemoteData</span><span class="o">.</span><span class="kt">Success</span> <span class="n">thing</span> <span class="p">}</span>
                            <span class="o">,</span> <span class="kt">Cmd</span><span class="o">.</span><span class="n">none</span>
                            <span class="p">)</span>
            <span class="k">in</span>
            <span class="p">(</span> <span class="p">{</span> <span class="n">model</span> <span class="o">|</span> <span class="n">alert</span> <span class="o">=</span> <span class="n">updated</span><span class="o">.</span><span class="n">alert</span><span class="o">,</span> <span class="n">thing</span> <span class="o">=</span> <span class="n">updated</span><span class="o">.</span><span class="n">thing</span> <span class="p">}</span><span class="o">,</span> <span class="n">cmd</span> <span class="p">)</span>

        <span class="c1">-- other APIs ...</span>
        <span class="c1">-- each `updated` record will be different subsets of `Model` record type</span>
</code></pre></div></div>

<p>Now, we have a compiler error!</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>The 2nd branch is a tuple of type:

    ( { alert : Maybe String, thing : RemoteData.RemoteData Http.Error a }
    , Cmd msg
    )

But all the previous branches result in:

    ( {}, Cmd Msg )

Hint: All branches in a `case` must produce the same type of values. This way,
no matter which branch we take, the result is always a consistent shape. Read
&lt;https://elm-lang.org/0.19.1/custom-types&gt; to learn how to “mix” types.
</code></pre></div></div>

<p>Elm does not allow returning different types for different branches of a <code class="language-plaintext highlighter-rouge">case</code> or <code class="language-plaintext highlighter-rouge">if</code> expression, but currently</p>
<ul>
  <li>our “request” branch, returns an empty record <code class="language-plaintext highlighter-rouge">{}</code></li>
  <li>our “error” branch, returns a <code class="language-plaintext highlighter-rouge">{ alert : Maybe Alert }</code> record</li>
  <li>our “ok” branch, returns a <code class="language-plaintext highlighter-rouge">{ thing : RemoteData.RemoteData Http.Error a }</code> record</li>
  <li>and if any branch forgets, and returns <code class="language-plaintext highlighter-rouge">( model, sendRequestCmd )</code> it won’t work too!</li>
</ul>

<p>The only way to compile, is to return the <em>same subset</em> of fields for <em>all branches</em> of our <code class="language-plaintext highlighter-rouge">case requestResponse of</code> – which is exactly what we wanted!</p>

<h3 id="result">Result</h3>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">updateWithApiMsg</span> <span class="p">:</span> <span class="kt">ApiMsg</span> <span class="o">-&gt;</span> <span class="kt">Model</span> <span class="o">-&gt;</span> <span class="p">(</span> <span class="kt">Model</span><span class="o">,</span> <span class="kt">Cmd</span> <span class="kt">Msg</span> <span class="p">)</span>
<span class="n">updateWithApiMsg</span> <span class="n">siteApi</span> <span class="n">model</span> <span class="o">=</span>
    <span class="k">case</span> <span class="n">siteApi</span> <span class="k">of</span>
        <span class="kt">ThingApi</span> <span class="n">requestResponse</span> <span class="o">-&gt;</span>
            <span class="k">let</span>
                <span class="c1">-- NOTE: `updated` is only a subset of our `Model` record type</span>
                <span class="c1">-- with only the fields that needs to be updated for `ThingApi`</span>
                <span class="p">(</span> <span class="n">updated</span><span class="o">,</span> <span class="n">cmd</span> <span class="p">)</span> <span class="o">=</span>
                    <span class="k">case</span> <span class="n">requestResponse</span> <span class="k">of</span>
                        <span class="kt">Request</span> <span class="n">num</span> <span class="o">-&gt;</span>
                            <span class="p">(</span> <span class="p">{</span> <span class="n">alert</span> <span class="o">=</span> <span class="n">model</span><span class="o">.</span><span class="n">alert</span> <span class="c1">-- aka no change</span>
                              <span class="o">,</span> <span class="n">thing</span> <span class="o">=</span> <span class="kt">RemoteData</span><span class="o">.</span><span class="kt">Loading</span>
                              <span class="p">}</span>
                            <span class="o">,</span> <span class="n">requestCmd</span> <span class="kt">ThingApi</span> <span class="p">(</span><span class="n">getThing</span> <span class="n">num</span><span class="p">)</span>
                            <span class="p">)</span>

                        <span class="kt">Response</span> <span class="p">(</span><span class="kt">Err</span> <span class="n">err</span><span class="p">)</span> <span class="o">-&gt;</span>
                            <span class="p">(</span> <span class="p">{</span> <span class="n">alert</span> <span class="o">=</span> <span class="kt">Just</span> <span class="p">(</span><span class="n">httpErrorString</span> <span class="n">err</span><span class="p">)</span>
                              <span class="o">,</span> <span class="n">thing</span> <span class="o">=</span> <span class="kt">RemoteData</span><span class="o">.</span><span class="kt">Failure</span> <span class="n">err</span>
                              <span class="p">}</span>
                            <span class="o">,</span> <span class="kt">Cmd</span><span class="o">.</span><span class="n">none</span>
                            <span class="p">)</span>

                        <span class="kt">Response</span> <span class="p">(</span><span class="kt">Ok</span> <span class="n">thing</span><span class="p">)</span> <span class="o">-&gt;</span>
                            <span class="p">(</span> <span class="p">{</span> <span class="n">alert</span> <span class="o">=</span> <span class="kt">Just</span> <span class="s">"</span><span class="s2">Thing loaded successfully"</span>
                              <span class="o">,</span> <span class="n">thing</span> <span class="o">=</span> <span class="kt">RemoteData</span><span class="o">.</span><span class="kt">Success</span> <span class="n">thing</span>
                              <span class="p">}</span>
                            <span class="o">,</span> <span class="kt">Cmd</span><span class="o">.</span><span class="n">none</span>
                            <span class="p">)</span>
            <span class="k">in</span>
            <span class="p">(</span> <span class="p">{</span> <span class="n">model</span> <span class="o">|</span> <span class="n">alert</span> <span class="o">=</span> <span class="n">updated</span><span class="o">.</span><span class="n">alert</span><span class="o">,</span> <span class="n">thing</span> <span class="o">=</span> <span class="n">updated</span><span class="o">.</span><span class="n">thing</span> <span class="p">}</span><span class="o">,</span> <span class="n">cmd</span> <span class="p">)</span>

        <span class="c1">-- other APIs ...</span>
        <span class="c1">-- each `updated` record will be different subsets of `Model` record type</span>
</code></pre></div></div>

<p>Now, each branch is required to return the same fields; each API can have their own field set. Elm compiler can be our constant vigilance instead. 🎉</p>]]></content><author><name>choonkeat</name></author><summary type="html"><![CDATA[It’s very common for frontend apps to fetch remote data to update sections of the UI. For example]]></summary></entry><entry><title type="html">What does it mean by `Html Msg`?</title><link href="/weblog/2020/08/what-does-it-mean-by-html-msg.html" rel="alternate" type="text/html" title="What does it mean by `Html Msg`?" /><published>2020-08-24T00:00:00+00:00</published><updated>2020-08-24T00:00:00+00:00</updated><id>/weblog/2020/08/what-does-it-mean-by-html-msg</id><content type="html" xml:base="/weblog/2020/08/what-does-it-mean-by-html-msg.html"><![CDATA[<p>There are possibly 2 questions in this question. I’ll answer them 1 by 1</p>

<h3 id="part-1-h-t-m-l-message">Part 1: h-t-m-l message</h3>

<p>After knowing the basic Elm syntax, we could be reading the following “return values” like this</p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">userFromJWT</span> <span class="p">:</span> <span class="kt">String</span> <span class="o">-&gt;</span> <span class="kt">Maybe</span> <span class="kt">User</span>
<span class="c1">-- returns a User value or nothing</span>
</code></pre></div></div>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">split</span> <span class="p">:</span> <span class="kt">String</span> <span class="o">-&gt;</span> <span class="kt">List</span> <span class="kt">String</span>
<span class="c1">-- returns a list of String</span>
</code></pre></div></div>

<p>With the help from our prior programming experience, we treat the return values as <code class="language-plaintext highlighter-rouge">*User</code> and <code class="language-plaintext highlighter-rouge">[]String</code> and jumps directly to think in terms of <em>“How do I use a <code class="language-plaintext highlighter-rouge">var u *User</code> value? <code class="language-plaintext highlighter-rouge">u.name</code>?”</em> and <em>“How do I use a <code class="language-plaintext highlighter-rouge">var s String</code>? <code class="language-plaintext highlighter-rouge">String.length(s)</code>?”</em></p>

<p>We don’t actually “see” the words <code class="language-plaintext highlighter-rouge">Maybe</code> or <code class="language-plaintext highlighter-rouge">List</code>; our attention was focused on <code class="language-plaintext highlighter-rouge">User</code> and <code class="language-plaintext highlighter-rouge">String</code>.</p>

<p>If we proceed with these instincts alone, we’ll fumble when we see unfamiliar types. We’d ask the wrong questions</p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">view</span> <span class="p">:</span> <span class="kt">Model</span> <span class="o">-&gt;</span> <span class="kt">Html</span> <span class="kt">Msg</span>
<span class="c1">-- returns an h-t-m-l message... but how do I return such a message?</span>
</code></pre></div></div>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">userEmail</span> <span class="p">:</span> <span class="kt">Json</span><span class="o">.</span><span class="kt">Decode</span><span class="o">.</span><span class="kt">Decoder</span> <span class="kt">String</span>
<span class="c1">-- returns a json decode decoder string... but how do I return such a string?</span>
</code></pre></div></div>

<p>There are no answers to the questions because there’s a misunderstanding of the grammar. To avoid being misled by my prior programming experience, I do this one weird trick instead:</p>

<ol>
  <li>
    <p>Just focus on the first word</p>

    <div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="kt">Html</span> <span class="kt">Msg</span>
 <span class="o">^^^^</span>
 <span class="c1">-- and read "Html" type</span>


 <span class="kt">Json</span><span class="o">.</span><span class="kt">Decode</span><span class="o">.</span><span class="kt">Decoder</span> <span class="kt">String</span>
 <span class="o">^^^^^^^^^^^^^^^^^^^</span>
 <span class="c1">-- and read "Json.Decode.Decoder" type</span>


 <span class="kt">HelloWorld</span> <span class="p">(</span><span class="kt">Html</span> <span class="n">msg</span><span class="p">)</span> <span class="p">(</span><span class="kt">Json</span><span class="o">.</span><span class="kt">Decode</span><span class="o">.</span><span class="kt">Decoder</span> <span class="kt">String</span><span class="p">)</span>
 <span class="o">^^^^^^^^^^</span>
 <span class="c1">-- and read "HelloWorld" type</span>
</code></pre></div>    </div>
  </li>
  <li>
    <p>Then look at the documentation for that word; look for functions <em>that returns that word</em></p>
  </li>
</ol>

<p>Here are some functions that I found with text search <code class="language-plaintext highlighter-rouge">-&gt; Html </code> on <a href="https://package.elm-lang.org/packages/elm/html/latest/Html">in the <code class="language-plaintext highlighter-rouge">Html</code> docs page</a></p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">text</span> <span class="p">:</span> <span class="kt">String</span> <span class="o">-&gt;</span> <span class="kt">Html</span> <span class="n">msg</span>
<span class="n">div</span> <span class="p">:</span> <span class="kt">List</span> <span class="p">(</span><span class="kt">Attribute</span> <span class="n">msg</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kt">List</span> <span class="p">(</span><span class="kt">Html</span> <span class="n">msg</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kt">Html</span> <span class="n">msg</span>
<span class="n">span</span> <span class="p">:</span> <span class="kt">List</span> <span class="p">(</span><span class="kt">Attribute</span> <span class="n">msg</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kt">List</span> <span class="p">(</span><span class="kt">Html</span> <span class="n">msg</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kt">Html</span> <span class="n">msg</span>

<span class="c1">-- note: unfamiliar types like `Attribute` usually refers to a type defined in the same module, i.e. `Html.Attribute`. You may have to search around for it</span>
</code></pre></div></div>
<p>And calling any of the these functions will be able to give us a value of <code class="language-plaintext highlighter-rouge">Html</code> type, just provide the necessary input argument values.</p>

<p>Here are some functions that I found returning <code class="language-plaintext highlighter-rouge">Decoder</code> <a href="https://package.elm-lang.org/packages/elm/json/latest/Json-Decode">in the docs page of <code class="language-plaintext highlighter-rouge">Json.Decode</code></a> (there wasn’t a page on <code class="language-plaintext highlighter-rouge">Json.Decode.Decoder</code> alone)</p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">string</span> <span class="p">:</span> <span class="kt">Decoder</span> <span class="kt">String</span>
<span class="n">int</span> <span class="p">:</span> <span class="kt">Decoder</span> <span class="kt">Int</span>
<span class="n">list</span> <span class="p">:</span> <span class="kt">Decoder</span> <span class="n">a</span> <span class="o">-&gt;</span> <span class="kt">Decoder</span> <span class="p">(</span><span class="kt">List</span> <span class="n">a</span><span class="p">)</span>
<span class="n">field</span> <span class="p">:</span> <span class="kt">String</span> <span class="o">-&gt;</span> <span class="kt">Decoder</span> <span class="n">a</span> <span class="o">-&gt;</span> <span class="kt">Decoder</span> <span class="n">a</span>
<span class="n">oneOf</span> <span class="p">:</span> <span class="kt">List</span> <span class="p">(</span><span class="kt">Decoder</span> <span class="n">a</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kt">Decoder</span> <span class="n">a</span>
</code></pre></div></div>
<p>Same idea: calling any of the these functions will be able to give us a value of <code class="language-plaintext highlighter-rouge">Json.Decode.Decoder</code> type, just provide the necessary input argument values.</p>

<h3 id="part-2-ok-but-what-is-this-html-type">Part 2 Ok, but what <em>is</em> this <code class="language-plaintext highlighter-rouge">Html</code> type</h3>

<p>In an Elm <a href="https://package.elm-lang.org/packages/elm/browser/latest/">Browser program</a> we are required to provide a <code class="language-plaintext highlighter-rouge">view</code> function that returns <code class="language-plaintext highlighter-rouge">Html</code> type. We can deduce Elm takes this return value and renders the corresponding DOM nodes in the browser.</p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">view</span> <span class="p">:</span> <span class="n">model</span> <span class="o">-&gt;</span> <span class="kt">Html</span> <span class="n">msg</span>
<span class="n">view</span> <span class="n">model</span> <span class="o">=</span>
    <span class="kt">Html</span><span class="o">.</span><span class="n">h1</span> <span class="p">[</span> <span class="kt">Html</span><span class="o">.</span><span class="kt">Attributes</span><span class="o">.</span><span class="n">class</span> <span class="s">"</span><span class="s2">greeting"</span> <span class="p">]</span> <span class="p">[</span> <span class="kt">Html</span><span class="o">.</span><span class="n">text</span> <span class="s">"</span><span class="s2">Hello"</span> <span class="p">]</span>
</code></pre></div></div>

<p>will render</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;h1</span> <span class="na">class=</span><span class="s">"greeting"</span><span class="nt">&gt;</span>Hello<span class="nt">&lt;/h1&gt;</span>
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">Html</code> module does not export the internal details of this type for us to look at (aka it’s an opaque type). The module only exports a bunch of functions for us to call, to obtain various <code class="language-plaintext highlighter-rouge">Html</code> values. And really that’s all we can know about it.</p>

<h3 id="part-2b-and-whats-the-relevance-of-msg-part">Part 2b And what’s the relevance of <code class="language-plaintext highlighter-rouge">msg</code> part?</h3>

<p>That’s the type parameter of <code class="language-plaintext highlighter-rouge">Html</code> type. We can’t always have an effective mental model of what role they play. Sometimes we can deduce easily, e.g. <code class="language-plaintext highlighter-rouge">Maybe Int</code> or <code class="language-plaintext highlighter-rouge">List String</code>. But other times, it’s not as obvious</p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">string</span> <span class="p">:</span> <span class="kt">Parser</span> <span class="p">(</span><span class="kt">String</span> <span class="o">-&gt;</span> <span class="n">a</span><span class="p">)</span> <span class="n">a</span>
</code></pre></div></div>

<p>What we can practically do with them is to make sure the type parameters / associated data types align, e.g.</p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">map</span> <span class="p">:</span> <span class="p">(</span><span class="n">a</span> <span class="o">-&gt;</span> <span class="n">b</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">a</span> <span class="o">-&gt;</span> <span class="n">b</span>
<span class="n">map</span> <span class="n">func</span> <span class="n">arg</span> <span class="o">=</span>
    <span class="o">...</span>
</code></pre></div></div>

<p>To “line up” the type parameters.. i’ll make sure the the <code class="language-plaintext highlighter-rouge">a</code> types are the same. And similarly:</p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">h1</span> <span class="p">:</span> <span class="kt">List</span> <span class="p">(</span><span class="kt">Attribute</span> <span class="n">msg</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kt">List</span> <span class="p">(</span><span class="kt">Html</span> <span class="n">msg</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kt">Html</span> <span class="n">msg</span>
</code></pre></div></div>

<p>When we call <a href="https://package.elm-lang.org/packages/elm/html/latest/Html#h1"><code class="language-plaintext highlighter-rouge">Html.h1</code></a> we can give any list of attributes and list of inner html elements – as long as their <code class="language-plaintext highlighter-rouge">msg</code> are the same type.</p>

<p>Now, if we go back up and look at a Browser program signature, e.g. <a href="https://package.elm-lang.org/packages/elm/browser/latest/Browser#sandbox">Browser.sandbox</a></p>

<div class="language-elm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">sandbox</span> <span class="p">:</span>
    <span class="p">{</span> <span class="n">init</span> <span class="p">:</span> <span class="n">model</span>
    <span class="o">,</span> <span class="n">view</span> <span class="p">:</span> <span class="n">model</span> <span class="o">-&gt;</span> <span class="kt">Html</span> <span class="n">msg</span>
    <span class="o">,</span> <span class="n">update</span> <span class="p">:</span> <span class="n">msg</span> <span class="o">-&gt;</span> <span class="n">model</span> <span class="o">-&gt;</span> <span class="n">model</span>
    <span class="p">}</span>
</code></pre></div></div>

<ol>
  <li>Remember, the type parameters must line up. So <code class="language-plaintext highlighter-rouge">msg</code> must refer to the same type everywhere regardless of whether it is <code class="language-plaintext highlighter-rouge">Int</code> or <a href="https://guide.elm-lang.org/architecture/buttons.html">a <code class="language-plaintext highlighter-rouge">Msg</code> custom type</a></li>
  <li>Recall that
    <blockquote>
      <p><code class="language-plaintext highlighter-rouge">update</code> — a way to update your state based on messages
https://guide.elm-lang.org/architecture/</p>
    </blockquote>
  </li>
</ol>

<p>This means the <code class="language-plaintext highlighter-rouge">msg</code> in <code class="language-plaintext highlighter-rouge">Html msg</code> refers to the type of value that will be handled in your <code class="language-plaintext highlighter-rouge">update</code> function. So we can conclude that</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">Html</code> is the DOM node type</li>
  <li><code class="language-plaintext highlighter-rouge">msg</code> is the type for <em>“what event type does this DOM node trigger”</em></li>
</ul>]]></content><author><name>choonkeat</name></author><summary type="html"><![CDATA[There are possibly 2 questions in this question. I’ll answer them 1 by 1]]></summary></entry><entry><title type="html">Code Usability</title><link href="/weblog/2019/10/code-usability.html" rel="alternate" type="text/html" title="Code Usability" /><published>2019-10-07T00:00:00+00:00</published><updated>2019-10-07T00:00:00+00:00</updated><id>/weblog/2019/10/code-usability</id><content type="html" xml:base="/weblog/2019/10/code-usability.html"><![CDATA[<p>There’s a great talk by <a href="https://twitter.com/rtfeldman">Richard Feldman</a> making the rounds: <a href="https://www.youtube.com/watch?v=QyJZzq0v7Z4">Why Isn’t Functional Programming the Norm?</a></p>

<p>There’s a slide that says</p>

<blockquote>
  <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>circle.grow(3)
grow(circle, 3)
</code></pre></div>  </div>

  <p>“Objects and methods” are syntax sugar for structs and procedures.</p>
</blockquote>

<p>I use to agree: they are <em>just</em> syntax sugar, where “syntax sugar” imply something inconsequential or communicates a lack of importance.</p>

<p>But in <a href="/weblog/2019/09/the-elm-json-decoder-object.html">recalling my stumbles</a> learning Elm – and given the fact that the talk is about our we wish FP was the norm; winning market share – I think we should appreciate the difference from another angle: usability. Appreciate maybe why OOP (syntax) has even slightly more users because of that usability win.</p>

<p>Hey it all adds up right?</p>

<blockquote>
  <p>Affordance describes all actions that are made physically possible by the properties of an object or an environment. A bottle screw cap affords twisting. A hinged door affords pushing or pulling. A staircase affords ascending or descending.</p>

  <p><a href="https://uxdesign.cc/affordance-in-user-interface-design-3b4b0b361143">https://uxdesign.cc/affordance-in-user-interface-design-3b4b0b361143</a></p>
</blockquote>

<p>So, in the code snippet above, what does the variable <code class="language-plaintext highlighter-rouge">circle</code> afford us to do? and how does a programmer find out?</p>

<blockquote>
  <p>NOTE: Keep in mind that the variable could be of a less straightforward type than a <code class="language-plaintext highlighter-rouge">Circle</code> or <code class="language-plaintext highlighter-rouge">Shape</code> (e.g. <code class="language-plaintext highlighter-rouge">UnnormalizedMeterReading</code>), or the programmer might be new to the codebase, or be the original author but had <a href="/weblog/2018/08/rails-hiatus.html">forgotten all the details after a hiatus</a>.</p>
</blockquote>

<p>What does an OOP programmer do? I’ll just type c-i-r-c-l-e-. and after that period <code class="language-plaintext highlighter-rouge">.</code> my code editor will show a handy dropdown list of possible actions, along with documentation snippet, specifically catered for the variable:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>circle.
       color(c Color)       : set foreground color to c
       grow(n Integer)      : increases diameter by n
       moveTo(x, y Integer) : place the circle on specified x,y coordinate
</code></pre></div></div>

<p>Contextual help. Perfect. Basically an equivalent in GUI would be the wizard dialog and its “next” “next” “finish” buttons.</p>

<p>NOTE: That’s in fact <em>exactly</em> what the <a href="https://www.apple.com/sg/swift/playgrounds/">Swift Playgrounds iPad</a> app does. You can code without even bringing up the keyboard.</p>

<p>On the other hand, what does an FP programmer do? Assuming I can figure out what type the variable is, I’ll open the documentation in my browser, press <code class="language-plaintext highlighter-rouge">CMD-F</code> and try my luck with “Find on page” with some guess words… say… <code class="language-plaintext highlighter-rouge">resize</code>? no?</p>

<blockquote>
  <p>When you design user interfaces, it’s a good idea to keep two principles in mind:</p>
  <ol>
    <li>Users don’t have the manual, and if they did, they wouldn’t read it.</li>
    <li>In fact, users can’t read anything, and if they could, they wouldn’t want to.</li>
  </ol>

  <p>– <a href="https://www.joelonsoftware.com/2001/10/24/user-interface-design-for-programmers/">https://www.joelonsoftware.com/2001/10/24/user-interface-design-for-programmers/</a></p>
</blockquote>

<p>The first step is admitting you have a problem.</p>

<p>What’s the next step? A function signature search perhaps? A bit out of the way, but more importantly, it needs precision to yield results <a href="https://klaftertief.github.io/elm-search/?q=Json.Decode.Decoder%20a%20-%3E%20String%20-%3E%20a">fail example</a> vs <a href="https://klaftertief.github.io/elm-search/?q=Json.Decode.Decoder%20a%20-&gt;%20String%20-&gt;%20Result%20Error%20a">success example</a>.</p>

<p><em>“Can any function from any module that can receive this Shape value, along with any other arguments, please stand forward? Curried functions in the current closure?”</em></p>

<p>Maybe something for the code editor community to think about.</p>

<hr />

<p><em>FWIW, the SQL syntax has the same problem too: you type <code class="language-plaintext highlighter-rouge">SELECT </code> and wait there.. no code editor can help you very much since nobody knows what you are trying to select <code class="language-plaintext highlighter-rouge">FROM</code> yet. If that syntax had just switcheroo, <code class="language-plaintext highlighter-rouge">FROM ... SELECT ...</code> the more usable SQL syntax could’ve driven SQL adoption even higher ;-)</em></p>

<p>UPDATE: See also, <a href="https://2017.ecoop.org/details/ecoop-2017-papers/27/Data-exploration-through-dot-driven-development">Data exploration through dot-driven development</a></p>

<p>UPDATE: ReScript editor feature allows <a href="https://web-cdn.bsky.app/profile/rescript-lang.org/post/3lequ2hmyws22">”.” to trigger completions for more than just record fields. Example: you’ll get completions for pipeable functions from the module of that type.</a>!</p>]]></content><author><name>choonkeat</name></author><summary type="html"><![CDATA[There’s a great talk by Richard Feldman making the rounds: Why Isn’t Functional Programming the Norm?]]></summary></entry></feed>