<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
<title>Chris Done's Blog</title>
<link>https://chrisdone.com</link>
<description><![CDATA[Blog all about programming, especially in Haskell since 2008!]]></description>
<atom:link href="https://chrisdone.com/rss.xml" rel="self" type="application/rss+xml" />
<lastBuildDate>Wed, 22 Dec 2021 00:00:00 UT</lastBuildDate>
<item><title><![CDATA[Meta]]></title><link>https://chrisdone.com/posts/meta</link><guid>https://chrisdone.com/posts/meta</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Meta</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Meta</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Commentary and updates about my blog, its software, features,
etc.</p>
<p>I added a “microblog” feature to my blog. It lets me use the form
feed character in a post to split it up into a series of sub posts,
which have independent pages. It’s a nice way to organise updates to a
topic and avoid them necessarily hitting my main RSS feed.</p>
<p>Examples are</p>
<ul>
<li><a href="https://chrisdone.com/posts/llms/">LLMs</a></li>
<li><a href="https://chrisdone.com/posts/pi-blog/">My raspberry
pi</a></li>
</ul>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2026-06-13 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sat, 13 Jun 2026 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Blogs]]></title><link>https://chrisdone.com/posts/blogs</link><guid>https://chrisdone.com/posts/blogs</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Blogs</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Blogs</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>A list of blogs I like. I’ll add to this from time to time.</p>
<h2 id="proper-blogs">Proper blogs</h2>
<p>Small, quirky, intimate. Proper blogs.</p>
<ul>
<li>http://static.v25media.com/edw519_mod.html</li>
<li>https://lr0.org/blog/</li>
<li>https://ratfactor.com/</li>
<li>https://caolan.uk/</li>
</ul>
<h2 id="big-blogs">Big blogs</h2>
<p>Big, well known, somewhat performative. Post-blogging blogs.</p>
<ul>
<li>https://danluu.com/</li>
<li>https://prog21.dadgum.com/</li>
</ul>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2026-06-09 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Tue, 09 Jun 2026 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[System Colic]]></title><link>https://chrisdone.com/posts/system-colic</link><guid>https://chrisdone.com/posts/system-colic</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>System Colic</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>System Colic</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Colic is a thing that some newborn babies go through. Your newborn
baby cries for hours on end, every day, for weeks. And they’re by all
measures healthy. Experts don’t know what causes it and they don’t have
any remedies for it. As a parent, you and your partner pretty much lose
your marbles and start questioning all your life choices that lead up to
this moment. You will try all the remedies; massages, positions,
“anti-colic drops”, whatever you can. The <a
href="https://www.nhs.uk/conditions/colic/">NHS page on colic</a>
suggests you ask for support from friends, family and their
helpline.</p>
<p>That’s an extreme case of the broader experience of having a baby,
which is often just trying to figure out what’s wrong with them, with
very little to go on, because they can’t talk to you, and actually they
scream at you, making it harder to discuss nuanced hypotheses with your
partner.</p>
<p>Complex software systems aren’t babies. But they can be a bit like
that. They’re going wrong, because they’re slow, or they’ve got bugs, or
something, and there isn’t one obvious cause. The system is alerting but
you’ve got nowhere to start from. You try out remedies that maybe have
an affect and maybe don’t. Emery Berger did a great talk called <a
href="https://thestrangeloop.com/2019/performance-matters.html">Performance
Matters</a> at Strange Loop, showing how, especially in modern systems,
everything from the hardware (think L* caches, branch prediction), the
OS (swap, virtual memory, syscalls, memory layout), runtime (allocators,
GC, etc), and your application code, and then in cloud times,
distributed systems and all their failure modes, are all independent
layers with their own affordances and tolerances that trigger at
opposing intervals. You think you’ve got something performing reliably
and then some threshold of the layer below is passed and suddenly
performance goes up or down, and you aren’t wise as to why.</p>
<p>I’m calling this <em>system colic</em> as a negative term for an
undesirable state of affairs. We know we don’t have to accept the
illegibility of a system, and can put work into exposing visibility into
them, or choose better components that do better in this regard.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2026-05-28 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Thu, 28 May 2026 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Home fibre]]></title><link>https://chrisdone.com/posts/home-fibre</link><guid>https://chrisdone.com/posts/home-fibre</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Home fibre</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Home fibre</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p><em>When a Cat6 cable does the job, but I want fibre optic
anyway</em></p>
<!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-refresh-toc -->
<p><strong>Table of Contents</strong></p>
<ul>
<li><a href="#why">Why</a></li>
<li><a href="#things-i-learned">Things I learned</a></li>
<li><a href="#components">Components</a>
<ul>
<li><a href="#the-fibre-optic-patch-cable">The fibre optic patch
cable</a></li>
<li><a href="#side-b">Side B</a></li>
<li><a href="#side-a">Side A</a></li>
<li><a href="#computer-side">Computer side</a></li>
</ul></li>
<li><a href="#the-final-result">The final result</a>
<ul>
<li><a href="#whole-setup">Whole setup</a></li>
<li><a href="#the-fs-media-converter-in-action">The FS media converter
in action</a></li>
<li><a href="#tp-link-media-converter-in-action">TP-link media converter
in action</a></li>
</ul></li>
<li><a href="#pictures-of-the-parts">Pictures of the parts</a>
<ul>
<li><a href="#sc-apc-test-patch-cable">SC-APC test patch cable</a></li>
<li><a href="#fs-media-converter">FS media converter</a></li>
<li><a href="#fs-power-lead">FS power lead</a></li>
<li><a href="#tp-link-media-converter">TP-Link media converter</a></li>
<li><a href="#tp-link-power-lead">TP-Link power lead</a></li>
<li><a href="#lc-upc-to-ac-apc-patch-cable">LC UPC to AC APC patch
cable</a></li>
<li><a href="#sc-ac-connectors">SC-AC connectors</a></li>
<li><a href="#sc-upc-to-sc-apc">SC-UPC to SC-APC</a></li>
<li><a href="#gigabit-ethernet-to-usb-c">Gigabit ethernet to
USB-C</a></li>
</ul></li>
</ul>
<!-- markdown-toc end -->
<h2 id="why">Why</h2>
<p>I’ve got an ethernet port by my TV, and my desk is on the other side
of the room. WiFi is fine, but I want to be cabled to take full
advantage of my gigabit internet.</p>
<p>My home is a newbuild, so I don’t feel like fishing through stud
walls. I discovered that these days fibre optic is well within hobby
price range, and you can get a magical InvisiLight EZ-Bend fibre cable
that can bend around sharp corners and lose no signal. They look
invisible to a casual glance when ran on the edges of walls. I took it
as an opportunity to have fun with simple hardware!</p>
<p>As of June 2nd 2026, I’m still waiting for the EZ-Bend cable to
arrive, but I’ve done a test with the rest of the setup.</p>
<h2 id="things-i-learned">Things I learned</h2>
<p>You need to understand this if you’re buying.</p>
<ol type="1">
<li>Fibre optic has modes (which comes from optical modes):
<ul>
<li><strong>Single-mode</strong> means the glass tube through which
light is emitted is very tiny. Something like 8-10μm. It requires a
laser, it’s more expensive, and the alignment has to be very precise.
Its distances before attenuation are measured in kilometers.</li>
<li><strong>Multi-mode</strong> has a really big core diameter. You can
use LED or other emitters, the light attenuates quicker (under half a
km), but it’s cheaper. The wavelengths used are also different.</li>
</ul></li>
<li>A patch cable may contain one or two or more fibres.
<ul>
<li>Single fibre, you’ll need two of these cables then if you’re
emitting only in one direction.</li>
<li>Duplex cable, contains two fibres, one for TX, one for RX.</li>
<li>And media converters accept either TX/RX (transmit/receive) ports,
where you might have one TX fibre and one RX fibre.</li>
</ul></li>
<li>Scenarios: Duplex vs half-duplex vs simplex:
<ul>
<li>Full duplex: two fibres, one TX, one RX.</li>
<li>Half duplex: you have one fibre, but take turns TX’ing and
RX’ing.</li>
<li>Simplex: one fibre, but sending concurrently via BiDi (separate
TX/RX wavelengths via <a
href="https://en.wikipedia.org/wiki/Wavelength-division_multiplexing">WDM</a>).</li>
</ul></li>
<li>Fibre cables have a variety of connectors:
<ul>
<li>SC (standard connector), it’s bigger.
<ul>
<li>SC UPC - domed glass.</li>
<li>SC APC - angled glass.</li>
</ul></li>
<li>LC APC/UPC - it’s smaller, and has a different clasp like an RJ45
connector.</li>
<li>None of these are compatible, but you can buy all the combinations
of patch cables that have X on one end and Y on the other end, which is
what I did.</li>
<li>See the pictures!</li>
</ul></li>
</ol>
<p>My setup is: a single mode, single fibre, simplex, bidirectional
(WDM). The main fibre is SC APC, but my media converters are on LC UPC
and SC UPC. One media converter transmits data at 1310 nm wavelength and
receives data at 1550 nm wavelength, and the other media converter has
the transmit/receive flipped.</p>
<h2 id="components">Components</h2>
<p>The setup comprises the following components.</p>
<h3 id="the-fibre-optic-patch-cable">The fibre optic patch cable</h3>
<p>I ordered the real InvisiLight EZ-Bend and a 1m yellow test
cable.</p>
<ul>
<li><strong>The real thing:</strong> InvisiLight® EZ-Bend™ Indoor
Jumpers, 20m, SC APC, white, Single Mode
<ul>
<li>This 3mm cable is capable of 2.5mm bend radius, is easy to run along
a wall and around corners.</li>
<li>Still waiting for delivery, estimated 4 weeks.</li>
</ul></li>
<li><strong>The test cable</strong>: 1m (3ft) Fiber Patch Cable, 1
Fiber, SC APC Simplex to SC APC Simplex, Single Mode (OS2), Riser
(OFNR), 2.0mm, Tight-Buffered, Yellow
<ul>
<li>For testing, equivalent to the EZ-Bend one.</li>
<li>Arrived, delivered promptly by fs.com.</li>
</ul></li>
</ul>
<h3 id="side-b">Side B</h3>
<p>This was my first choice for simplicity; grab an off the shelf TP
Link that has fibre in and eth in and you’re good.</p>
<ul>
<li>TP-Link Gigabit WDM Media Converter, Auto-negotiation, TL-FC311B-20
<ul>
<li>transmits data at 1310 nm wavelength and receives data at 1550 nm
wavelength</li>
<li>Arrived, from Amazon.</li>
</ul></li>
<li>1x: 1m (3ft) Fiber Patch Cable, 1 Fiber, SC UPC Simplex to SC APC
Simplex, Single Mode (OS2), Riser (OFNR), 2.0mm, Tight-Buffered, Yellow
<ul>
<li>Arrived, delivered promptly by fs.com.</li>
</ul></li>
<li>1x: SC/APC to SC/APC Simplex Single Mode Fiber Keystone Jack
<ul>
<li>Arrived, delivered promptly by fs.com.</li>
</ul></li>
</ul>
<p>I attempted to order the corresponding TL-FC311A-20 (note the ‘A’)
unit, but:</p>
<ul>
<li>Ordered from Amazon. Delayed. Amazon. I cancelled.</li>
<li>Ordered from Scan. Delayed. I cancelled.</li>
<li>Ordered from Converge Technology Solutions. They cancelled due to no
stock despite claiming a few in stock.</li>
</ul>
<p>These suppliers are a bit fast and loose with their stock
inventory.</p>
<h3 id="side-a">Side A</h3>
<p>After my experience trying to source the ‘A’ part for the TP Link
media converter, I decided that since I had such a good experience with
fs.com, that I’d just ordered everything from there.</p>
<p>I got an SFP media converter and module.</p>
<ul>
<li><p>1000BASE-BX-D SFP BiDi 1550nm-TX/1310nm-RX 20km Simplex LC/UPC
SMF Transceiver Module for FS Switches</p></li>
<li><p>Mini Unmanaged 1x 10/100/1000Base-T RJ45 to 1x 1000Base-X SFP
Gigabit Ethernet Media Converter, British Plug Standard</p></li>
<li><p>1m (3ft) Fiber Patch Cable, 1 Fiber, LC UPC Simplex to SC APC
Simplex, Single Mode (OS2), Riser (OFNR), 2.0mm, Tight-Buffered,
Yellow</p></li>
<li><p>1x: SC/APC to SC/APC Simplex Single Mode Fiber Keystone Jack</p>
<ul>
<li>Arrived, delivered promptly by fs.com.</li>
</ul></li>
</ul>
<h3 id="computer-side">Computer side</h3>
<p>MacBooks don’t have ethernet (so brave), so I needed an adapter for
it.</p>
<ul>
<li>Belkin USB-C to 2.5Gb Ethernet Adapter - White
<ul>
<li>Bought from Apple.</li>
</ul></li>
</ul>
<h2 id="the-final-result">The final result</h2>
<p>If you just want to see the final test result, here it is. For
pictures of all the parts, see further down.</p>
<h3 id="whole-setup">Whole setup</h3>
<p><img src="/images/home-fibre/full-thing.png" /></p>
<h3 id="the-fs-media-converter-in-action">The FS media converter in
action</h3>
<p><img src="/images/home-fibre/fs-media-converter-in-action.png" /></p>
<h3 id="tp-link-media-converter-in-action">TP-link media converter in
action</h3>
<p><img
src="/images/home-fibre/tp-link-media-converter-in-action.png" /></p>
<h2 id="pictures-of-the-parts">Pictures of the parts</h2>
<h3 id="sc-apc-test-patch-cable">SC-APC test patch cable</h3>
<p><img src="/images/home-fibre/ac-apc-test-patch-cable.png" /></p>
<h3 id="fs-media-converter">FS media converter</h3>
<p><img src="/images/home-fibre/fs-media-converter.png" /></p>
<h3 id="fs-power-lead">FS power lead</h3>
<p><img src="/images/home-fibre/fs-power.png" /></p>
<h3 id="tp-link-media-converter">TP-Link media converter</h3>
<p><img src="/images/home-fibre/tp-link-media-converter.png" /></p>
<h3 id="tp-link-power-lead">TP-Link power lead</h3>
<p><img src="/images/home-fibre/tp-link-power.png" /></p>
<h3 id="lc-upc-to-ac-apc-patch-cable">LC UPC to AC APC patch cable</h3>
<p><img src="/images/home-fibre/lc-upc-to-ac-apc.png" /></p>
<h3 id="sc-ac-connectors">SC-AC connectors</h3>
<p><img src="/images/home-fibre/sc-apc-connectors.png" /></p>
<h3 id="sc-upc-to-sc-apc">SC-UPC to SC-APC</h3>
<p>Both SC, but the polish differs.</p>
<p><img src="/images/home-fibre/sc-upc-to-sc-apc.png" /></p>
<h3 id="gigabit-ethernet-to-usb-c">Gigabit ethernet to USB-C</h3>
<p><img src="/images/home-fibre/gigabit-eth-to-usbc.png" /></p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2026-05-17 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sun, 17 May 2026 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Some updates about Hell in 2026]]></title><link>https://chrisdone.com/posts/hell-year-in-review-2026</link><guid>https://chrisdone.com/posts/hell-year-in-review-2026</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Some updates about Hell in 2026</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Some updates about Hell in 2026</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>I’ve added a few neat bits and bobs to <a
href="https://chrisdone.github.io/hell/">Hell</a> since I last blogged
about it.</p>
<p>On the API side, things have slowed down when compared with the prior
year,<a href="#fn1" class="footnote-ref" id="fnref1"
role="doc-noteref"><sup>1</sup></a> but other improvements were still
made.</p>
<h2 id="sum-types">Sum types</h2>
<p>I’ve added support for using case statements on built-in primitive
types, like <code>Maybe</code>, as in:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">case</span> i <span class="kw">of</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Maybe</span><span class="op">.</span><span class="dt">Just</span> x <span class="ot">-&gt;</span> <span class="dt">IO</span><span class="op">.</span><span class="fu">print</span> x</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Maybe</span><span class="op">.</span><span class="dt">Nothing</span> <span class="ot">-&gt;</span> Text.putStrLn <span class="st">&quot;nope&quot;</span></span></code></pre></div>
<p>Previously, one only had <code>Maybe.maybe</code>, which is fine, but
is often not the direct way to write something. So having
<code>case</code> syntax for that is handy. You just have to qualify the
constructor names, and then it knows that it’s a built-in.</p>
<h2 id="type-class-entailment">Type class entailment</h2>
<p>I’ve added limited support for resolving instances which feature
entailment on the instance, such as <code>Eq a =&gt; Eq [a]</code>, and
this works in a nested way. So one can compare values of any depth
provided they have an <code>Eq</code> instance, as seen in the following
examples:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>Text.putStrLn <span class="op">$</span> <span class="dt">Show</span><span class="op">.</span><span class="fu">show</span> <span class="op">$</span> <span class="dt">Eq</span><span class="op">.</span>eq (<span class="dv">1</span>,<span class="dv">1</span>) (<span class="dv">1</span>,<span class="dv">1</span>)</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>Text.putStrLn <span class="op">$</span> <span class="dt">Show</span><span class="op">.</span><span class="fu">show</span> <span class="op">$</span> <span class="dt">Eq</span><span class="op">.</span>eq [<span class="dt">Maybe</span><span class="op">.</span><span class="dt">Just</span> <span class="dv">1</span>] [<span class="dt">Maybe</span><span class="op">.</span><span class="dt">Just</span> <span class="dv">2</span>]</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>Text.putStrLn <span class="op">$</span> <span class="dt">Show</span><span class="op">.</span><span class="fu">show</span> <span class="op">$</span> <span class="dt">Eq</span><span class="op">.</span>eq [<span class="dt">Either</span><span class="op">.</span><span class="dt">Left</span> <span class="dv">1</span>] [<span class="dt">Either</span><span class="op">.</span><span class="dt">Right</span> <span class="st">&quot;abc&quot;</span>]</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="dt">IO</span><span class="op">.</span><span class="fu">print</span> [<span class="dt">Maybe</span><span class="op">.</span><span class="dt">Just</span> <span class="dv">1</span>, <span class="dt">Maybe</span><span class="op">.</span><span class="dt">Nothing</span>]</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="dt">IO</span><span class="op">.</span><span class="fu">print</span> <span class="op">$</span> <span class="dt">Maybe</span><span class="op">.</span><span class="dt">Just</span> [<span class="dv">1</span>] <span class="op">&lt;&gt;</span> <span class="dt">Maybe</span><span class="op">.</span><span class="dt">Nothing</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="dt">IO</span><span class="op">.</span><span class="fu">print</span> <span class="op">$</span> [<span class="dt">Either</span><span class="op">.</span><span class="dt">Left</span> (<span class="dt">Maybe</span><span class="op">.</span><span class="dt">Just</span> <span class="dv">1</span>), <span class="dt">Either</span><span class="op">.</span><span class="dt">Right</span> (<span class="dt">Maybe</span><span class="op">.</span><span class="dt">Just</span> <span class="st">&quot;abc&quot;</span>), <span class="dt">Either</span><span class="op">.</span><span class="dt">Left</span> <span class="dt">Maybe</span><span class="op">.</span><span class="dt">Nothing</span>]</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="dt">IO</span><span class="op">.</span><span class="fu">print</span> [<span class="dt">Maybe</span><span class="op">.</span><span class="dt">Just</span> (<span class="dv">1</span>, <span class="dv">2</span>), <span class="dt">Maybe</span><span class="op">.</span><span class="dt">Nothing</span>]</span></code></pre></div>
<p>The complete list of instances is now on <a
href="https://chrisdone.github.io/hell/api/">the API documentation
page</a>.</p>
<p>The implementation is quite nice, where instances are listed like
this:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ot">instances ::</span> <span class="dt">Instances</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>instances <span class="ot">=</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Instances</span> <span class="op">$</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    Map.fromList</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>      [ entail1 <span class="op">@</span><span class="dt">Show</span> <span class="op">@</span>[],</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>        entail1 <span class="op">@</span><span class="dt">Show</span> <span class="op">@</span><span class="dt">Set</span>,</span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>        entail1 <span class="op">@</span><span class="dt">Show</span> <span class="op">@</span><span class="dt">Tree</span>,</span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>        entail1 <span class="op">@</span><span class="dt">Show</span> <span class="op">@</span><span class="dt">Maybe</span>,</span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>        entail1 <span class="op">@</span><span class="dt">Show</span> <span class="op">@</span><span class="dt">Vector</span>,</span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>        entail2 <span class="op">@</span><span class="dt">Show</span> <span class="op">@</span><span class="dt">Either</span>,</span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>        entail2 <span class="op">@</span><span class="dt">Show</span> <span class="op">@</span>(,),</span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>        <span class="op">...</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>        instance1 <span class="op">@</span><span class="dt">Functor</span> <span class="op">@</span><span class="dt">Either</span>,</span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>        instance1 <span class="op">@</span><span class="dt">Functor</span> <span class="op">@</span>(,), <span class="co">-- Functor (a,)</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>        instance0 <span class="op">@</span><span class="dt">Applicative</span> <span class="op">@</span><span class="dt">IO</span>,</span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>        instance0 <span class="op">@</span><span class="dt">Applicative</span> <span class="op">@</span><span class="dt">Maybe</span>,</span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a>        instance0 <span class="op">@</span><span class="dt">Applicative</span> <span class="op">@</span>[],</span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a>        instance0 <span class="op">@</span><span class="dt">Applicative</span> <span class="op">@</span><span class="dt">Tree</span>,</span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true" tabindex="-1"></a>        instance0 <span class="op">@</span><span class="dt">Applicative</span> <span class="op">@</span><span class="dt">Options.Parser</span>,</span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true" tabindex="-1"></a>        instance1 <span class="op">@</span><span class="dt">Applicative</span> <span class="op">@</span><span class="dt">Either</span>,</span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true" tabindex="-1"></a>        instance0 <span class="op">@</span><span class="dt">Alternative</span> <span class="op">@</span><span class="dt">Options.Parser</span>,</span>
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true" tabindex="-1"></a>        instance0 <span class="op">@</span><span class="dt">Alternative</span> <span class="op">@</span><span class="dt">Maybe</span>,</span>
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true" tabindex="-1"></a>        entail1 <span class="op">@</span><span class="dt">Monoid</span> <span class="op">@</span><span class="dt">Maybe</span>,</span>
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true" tabindex="-1"></a>        instance0 <span class="op">@</span><span class="dt">Monoid</span> <span class="op">@</span><span class="dt">Text</span>,</span>
<span id="cb3-25"><a href="#cb3-25" aria-hidden="true" tabindex="-1"></a>        instance1 <span class="op">@</span><span class="dt">Monoid</span> <span class="op">@</span><span class="dt">Vector</span>,</span>
<span id="cb3-26"><a href="#cb3-26" aria-hidden="true" tabindex="-1"></a>        instance2 <span class="op">@</span><span class="dt">Monoid</span> <span class="op">@</span><span class="dt">Options.Mod</span>,</span>
<span id="cb3-27"><a href="#cb3-27" aria-hidden="true" tabindex="-1"></a>        instance1 <span class="op">@</span><span class="dt">Monoid</span> <span class="op">@</span>[],</span>
<span id="cb3-28"><a href="#cb3-28" aria-hidden="true" tabindex="-1"></a>        entail1 <span class="op">@</span><span class="dt">Semigroup</span> <span class="op">@</span><span class="dt">Maybe</span>,</span>
<span id="cb3-29"><a href="#cb3-29" aria-hidden="true" tabindex="-1"></a>        instance2 <span class="op">@</span><span class="dt">Semigroup</span> <span class="op">@</span><span class="dt">Either</span>,</span>
<span id="cb3-30"><a href="#cb3-30" aria-hidden="true" tabindex="-1"></a>        instance2 <span class="op">@</span><span class="dt">Semigroup</span> <span class="op">@</span><span class="dt">Options.Mod</span>,</span>
<span id="cb3-31"><a href="#cb3-31" aria-hidden="true" tabindex="-1"></a>        instance0 <span class="op">@</span><span class="dt">Semigroup</span> <span class="op">@</span><span class="dt">Text</span>,</span>
<span id="cb3-32"><a href="#cb3-32" aria-hidden="true" tabindex="-1"></a>        <span class="op">...</span></span></code></pre></div>
<p>With</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ot">instance0 ::</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">forall</span> cls a<span class="op">.</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>  (cls a, <span class="dt">Typeable</span> cls, <span class="dt">Typeable</span> a) <span class="ot">=&gt;</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>  ((<span class="dt">SomeTypeRep</span>, <span class="dt">SomeTypeRep</span>), <span class="dt">Dynamic</span>)</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>instance0 <span class="ot">=</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>  ( (<span class="dt">SomeTypeRep</span> <span class="op">$</span> typeRep <span class="op">@</span>cls, <span class="dt">SomeTypeRep</span> <span class="op">$</span> typeRep <span class="op">@</span>a),</span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>    toDyn <span class="op">$</span> <span class="dt">Dict</span> <span class="op">@</span>(cls a)</span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>  )</span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a><span class="ot">instance1 ::</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">forall</span> {k0} {k1} (<span class="ot">c ::</span> k1 <span class="ot">-&gt;</span> <span class="dt">Constraint</span>) (<span class="ot">t ::</span> k0 <span class="ot">-&gt;</span> k1)<span class="op">.</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>  ((<span class="kw">forall</span> a<span class="op">.</span> c (t a)), <span class="dt">Typeable</span> c, <span class="dt">Typeable</span> t, <span class="dt">Typeable</span> k0, <span class="dt">Typeable</span> k1) <span class="ot">=&gt;</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>  ((<span class="dt">SomeTypeRep</span>, <span class="dt">SomeTypeRep</span>), <span class="dt">Dynamic</span>)</span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>instance1 <span class="ot">=</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a>  ( (<span class="dt">SomeTypeRep</span> <span class="op">$</span> typeRep <span class="op">@</span>c, <span class="dt">SomeTypeRep</span> <span class="op">$</span> typeRep <span class="op">@</span>t),</span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a>    toDyn <span class="op">$</span> <span class="dt">D1</span> <span class="op">@</span>c <span class="op">@</span>t <span class="dt">Dict</span></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a>  )</span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a><span class="ot">entail1 ::</span></span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true" tabindex="-1"></a>  <span class="kw">forall</span> {k1} (<span class="ot">c ::</span> k1 <span class="ot">-&gt;</span> <span class="dt">Constraint</span>) (<span class="ot">t ::</span> k1 <span class="ot">-&gt;</span> k1)<span class="op">.</span></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true" tabindex="-1"></a>  ((<span class="kw">forall</span> a<span class="op">.</span> c a <span class="ot">=&gt;</span> c (t a)), <span class="dt">Typeable</span> c, <span class="dt">Typeable</span> t,  <span class="dt">Typeable</span> k1) <span class="ot">=&gt;</span></span>
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true" tabindex="-1"></a>  ((<span class="dt">SomeTypeRep</span>, <span class="dt">SomeTypeRep</span>), <span class="dt">Dynamic</span>)</span>
<span id="cb4-23"><a href="#cb4-23" aria-hidden="true" tabindex="-1"></a>entail1 <span class="ot">=</span></span>
<span id="cb4-24"><a href="#cb4-24" aria-hidden="true" tabindex="-1"></a>  ( (<span class="dt">SomeTypeRep</span> <span class="op">$</span> typeRep <span class="op">@</span>c, <span class="dt">SomeTypeRep</span> <span class="op">$</span> typeRep <span class="op">@</span>t),</span>
<span id="cb4-25"><a href="#cb4-25" aria-hidden="true" tabindex="-1"></a>    toDyn <span class="op">$</span> <span class="dt">ED1</span> <span class="op">@</span>c <span class="op">@</span>t (<span class="dt">Sub</span> <span class="dt">Dict</span>)</span>
<span id="cb4-26"><a href="#cb4-26" aria-hidden="true" tabindex="-1"></a>  )</span>
<span id="cb4-27"><a href="#cb4-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-28"><a href="#cb4-28" aria-hidden="true" tabindex="-1"></a><span class="co">-- Entailment, c a =&gt; c (t a), E.g. Eq a :- Eq [a]</span></span>
<span id="cb4-29"><a href="#cb4-29" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">ED1</span> c t <span class="ot">=</span> <span class="dt">ED1</span> (<span class="kw">forall</span> e<span class="op">.</span> c e <span class="op">:-</span> c (t e))</span></code></pre></div>
<p>And then resolution looks like this:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ot">resolve1 ::</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">forall</span> {k0} {k1} (<span class="ot">t ::</span> k0 <span class="ot">-&gt;</span> k1) (<span class="ot">c ::</span> k1 <span class="ot">-&gt;</span> <span class="dt">Constraint</span>) (<span class="ot">a ::</span> k0)<span class="op">.</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>  (<span class="dt">Typeable</span> k0, <span class="dt">Typeable</span> k1) <span class="ot">=&gt;</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">TypeRep</span> (c (t a)) <span class="ot">-&gt;</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">TypeRep</span> c <span class="ot">-&gt;</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">TypeRep</span> t <span class="ot">-&gt;</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Instances</span> <span class="ot">-&gt;</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Maybe</span> (<span class="dt">Dict</span> (c (t a)))</span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>resolve1 cta c t (<span class="dt">Instances</span> m) <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Dynamic</span> rep dict <span class="ot">&lt;-</span> Map.lookup (<span class="dt">SomeTypeRep</span> c, <span class="dt">SomeTypeRep</span> t) m</span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>  (<span class="kw">do</span> <span class="dt">Type.HRefl</span> <span class="ot">&lt;-</span> Type.eqTypeRep rep <span class="op">$</span> <span class="dt">Type.App</span> (<span class="dt">Type.App</span> (typeRep <span class="op">@</span><span class="dt">D1</span>) c) t</span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>      <span class="kw">let</span> <span class="dt">D1</span> d <span class="ot">=</span> dict</span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a>      <span class="fu">pure</span> d) <span class="op">&lt;|&gt;</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a>    <span class="co">-- When we see e.g. C (T A), where T A and A have the same kind,</span></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a>    <span class="co">-- we can lookup C A, for the entailment C A :- C (T A).</span></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a>    (<span class="kw">do</span> <span class="kw">case</span> cta <span class="kw">of</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a>          <span class="dt">Type.App</span> _c a<span class="op">@</span>(<span class="dt">Type.App</span> f a&#39;) <span class="ot">-&gt;</span> <span class="kw">do</span></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true" tabindex="-1"></a>            <span class="dt">Type.HRefl</span> <span class="ot">&lt;-</span> Type.eqTypeRep (typeRepKind a&#39;) (typeRepKind a)</span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true" tabindex="-1"></a>            <span class="dt">Type.HRefl</span> <span class="ot">&lt;-</span> Type.eqTypeRep rep <span class="op">$</span> <span class="dt">Type.App</span> (<span class="dt">Type.App</span> (typeRep <span class="op">@</span><span class="dt">ED1</span>) c) f</span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true" tabindex="-1"></a>            <span class="kw">let</span> <span class="dt">ED1</span> entailment <span class="ot">=</span> dict</span>
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true" tabindex="-1"></a>            dictA <span class="ot">&lt;-</span> lookupDict a&#39; c</span>
<span id="cb5-22"><a href="#cb5-22" aria-hidden="true" tabindex="-1"></a>            <span class="fu">pure</span> <span class="op">$</span> mapDict entailment dictA</span>
<span id="cb5-23"><a href="#cb5-23" aria-hidden="true" tabindex="-1"></a>          _ <span class="ot">-&gt;</span> <span class="dt">Nothing</span>)</span></code></pre></div>
<p>For future reference, you can see the latest implementation <a
href="https://github.com/chrisdone/hell/blob/main/src/Hell.hs">in
Hell.hs in the repo.</a></p>
<p>What remains is adding support for
e.g. <code>Ord a =&gt; Eq (Set a)</code>, but I don’t expect it’ll be
too hard.</p>
<h2 id="apis-added">APIs added</h2>
<p>I added optparse-applicative, so the following code works exactly as
it would in Haskell:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- Includes example of Semigroup.</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Opts</span> <span class="ot">=</span> <span class="dt">Opts</span> {</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="ot">  quiet ::</span> <span class="dt">Bool</span>,</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="ot">  filePath ::</span> <span class="dt">Maybe</span> <span class="dt">Text</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a> }</span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>options <span class="ot">=</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>  (\quiet path <span class="ot">-&gt;</span> <span class="dt">Main.Opts</span> { quiet <span class="ot">=</span> quiet, filePath <span class="ot">=</span> path })</span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>       <span class="op">&lt;$&gt;</span> Options.switch (Flag.long <span class="st">&quot;quiet&quot;</span> <span class="op">&lt;&gt;</span> Flag.help <span class="st">&quot;Be quiet?&quot;</span>)</span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>       <span class="op">&lt;*&gt;</span> (Alternative.optional <span class="op">$</span> Options.strOption (Option.long <span class="st">&quot;path&quot;</span> <span class="op">&lt;&gt;</span> Option.help <span class="st">&quot;The filepath to export&quot;</span>))</span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>  opts <span class="ot">&lt;-</span> Options.execParser (Options.info (Main.options <span class="op">&lt;**&gt;</span> Options.helper) Options.fullDesc)</span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a>  Text.putStrLn <span class="op">$</span> <span class="dt">Maybe</span><span class="op">.</span><span class="fu">maybe</span> <span class="st">&quot;No file path&quot;</span> Function.id (Record.get <span class="op">@</span><span class="st">&quot;filePath&quot;</span> opts)</span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a>  Text.putStrLn <span class="op">$</span> <span class="dt">Show</span><span class="op">.</span><span class="fu">show</span> <span class="op">@</span><span class="dt">Bool</span> <span class="op">$</span> Record.get <span class="op">@</span><span class="st">&quot;quiet&quot;</span> opts</span></code></pre></div>
<p>It’s got date/time APIs:</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>  now <span class="ot">&lt;-</span> UTCTime.getCurrentTime</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>  Text.putStrLn <span class="st">&quot;Current time:&quot;</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">IO</span><span class="op">.</span><span class="fu">print</span> now</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>  Text.putStrLn <span class="st">&quot;ISO8601:&quot;</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>  Text.putStrLn <span class="op">$</span> UTCTime.iso8601Show now</span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>  Text.putStrLn <span class="st">&quot;Parsed:&quot;</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Maybe</span><span class="op">.</span><span class="fu">maybe</span> (Error.error <span class="st">&quot;Impossible!&quot;</span>) <span class="dt">IO</span><span class="op">.</span><span class="fu">print</span> <span class="op">$</span> UTCTime.iso8601ParseM <span class="st">&quot;2025-05-30T11:18:26.195147084Z&quot;</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a>  Text.putStrLn <span class="st">&quot;Increased:&quot;</span></span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a>  <span class="dt">IO</span><span class="op">.</span><span class="fu">print</span> <span class="op">$</span> UTCTime.addUTCTime (<span class="dt">Double</span><span class="op">.</span>mult <span class="fl">60.0</span> <span class="fl">60.0</span>) now</span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true" tabindex="-1"></a>  Text.putStrLn <span class="st">&quot;Parts:&quot;</span></span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true" tabindex="-1"></a>  <span class="dt">IO</span><span class="op">.</span><span class="fu">print</span> <span class="op">$</span> TimeOfDay.timeToTimeOfDay <span class="op">$</span> UTCTime.utctDayTime now</span>
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true" tabindex="-1"></a>  <span class="dt">IO</span><span class="op">.</span><span class="fu">print</span> <span class="op">$</span> UTCTime.utctDay now</span>
<span id="cb7-18"><a href="#cb7-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-19"><a href="#cb7-19" aria-hidden="true" tabindex="-1"></a><span class="ot">  day1 ::</span> <span class="dt">Day</span> <span class="ot">&lt;-</span></span>
<span id="cb7-20"><a href="#cb7-20" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Maybe</span><span class="op">.</span><span class="fu">maybe</span> (Error.error <span class="st">&quot;Invalid&quot;</span>) <span class="dt">IO</span><span class="op">.</span><span class="fu">pure</span> <span class="op">$</span> Day.fromGregorianValid (<span class="dt">Int</span><span class="op">.</span><span class="fu">toInteger</span> <span class="dv">2025</span>) <span class="dv">08</span> <span class="dv">09</span></span>
<span id="cb7-21"><a href="#cb7-21" aria-hidden="true" tabindex="-1"></a>  day2 <span class="ot">&lt;-</span> <span class="dt">Maybe</span><span class="op">.</span><span class="fu">maybe</span> (Error.error <span class="st">&quot;Invalid&quot;</span>) <span class="dt">IO</span><span class="op">.</span><span class="fu">pure</span> <span class="op">$</span> Day.iso8601ParseM <span class="st">&quot;2025-08-09&quot;</span></span>
<span id="cb7-22"><a href="#cb7-22" aria-hidden="true" tabindex="-1"></a>  <span class="dt">IO</span><span class="op">.</span><span class="fu">print</span> <span class="op">$</span> <span class="dt">Eq</span><span class="op">.</span>eq day1 day2 <span class="co">-- True</span></span>
<span id="cb7-23"><a href="#cb7-23" aria-hidden="true" tabindex="-1"></a>  Text.putStrLn <span class="op">$</span> Day.iso8601Show day1 <span class="co">-- 2025-08-09</span></span></code></pre></div>
<p>I think Haskell has a really nice date/time API – compared to most
other languages, anyway.</p>
<p>I’ve been planning for my next thing to add to be Wai/Warp, so that
it’s easy to write HTTP servers which comes up surprisingly often. The
Wai/Warp API is very stable, so I can feel happy including it as a
primitive.</p>
<h2 id="syntactic-constructs-added">Syntactic constructs added</h2>
<p>I added the ability to declare type sigs on top-levels like this:</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Foo</span> <span class="ot">=</span> <span class="dt">Foo</span> { bar,<span class="ot"> mu ::</span> <span class="dt">Int</span> }</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="ot">main ::</span> <span class="dt">IO</span> () <span class="ot">=</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>  Main.foo</span></code></pre></div>
<p>Also added applicative operators, and NamedFieldPuns. I think that’s
about it.</p>
<h2 id="remaining-work">Remaining work</h2>
<p>I need to implement a faster unification—I have a work in progress
unification-fd branch, which I may or may not proceed with, as the API
doesn’t bring me much joy. Some speed up is needed, though, as my naive
algorithm is slow.</p>
<p>It still needs to be ported to the GHC parser, so we can get all the
extra syntactic goodies like foo.bar, multi-line strings, etc. But
that’s boring, labrious work, so I’ll get to it when I really, really
want to.</p>
<p>No LLMs have been used on any part of this project so far. It’s more
of an art project at this point. My artisanal open source project.</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>For which a lot of activity was
driven by adding more library functions–because our team at work has
been adopting Nushell alongside Hell. Nushell is in many ways is easier
than Hell, for things like data munging and web requests and such out of
the box, and it has a proper REPL. Hell doesn’t have a REPL and isn’t
trying to be that kind of experience. It was debated whether we should
just use Nushell for everything, but a couple people argued that Hell is
particularly good at process orchestration due to its simple and easy
concurrency primitives. So we’re using both for now.<a href="#fnref1"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2026-04-23 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Thu, 23 Apr 2026 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Proposal to extend JSON with sum types (variants)]]></title><link>https://chrisdone.com/posts/json-with-sum-types</link><guid>https://chrisdone.com/posts/json-with-sum-types</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Proposal to extend JSON with sum types (variants)</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Proposal to extend JSON with sum types (variants)</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>A small syntactical addition that I propose to add to JSON is
variants. It looks like this:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode lua"><code class="sourceCode lua"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="op">#</span><span class="st">&quot;succeeded&quot;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="op">#</span><span class="st">&quot;failed&quot;</span><span class="op">(</span><span class="st">&quot;Problem flerbing the fobnicator.&quot;</span><span class="op">)</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="op">#</span><span class="st">&quot;loading&quot;</span><span class="op">({</span> <span class="st">&quot;remaining&quot;</span><span class="op">:</span> <span class="dv">3</span><span class="op">,</span> <span class="st">&quot;completed&quot;</span><span class="op">:</span> <span class="dv">7</span> <span class="op">})</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="op">[</span> <span class="op">#</span><span class="st">&quot;foo&quot;</span><span class="op">,</span> <span class="op">#</span><span class="st">&quot;bar&quot;</span><span class="op">(</span><span class="dv">1</span><span class="op">),</span> <span class="op">#</span><span class="st">&quot;boz&quot;</span><span class="op">(</span><span class="st">&quot;Ok!&quot;</span><span class="op">)</span> <span class="op">]</span></span></code></pre></div>
<p>I trust that the syntax is intuitive and follows norms that a hashtag
is a way of labelling something.</p>
<p>The grammar is simply:</p>
<pre class="bnf"><code>root ::= string | number | ... | object | variant
variant ::= &quot;#&quot; string variant-arg?
variant-arg ::= &quot;(&quot; root &quot;)&quot;</code></pre>
<p>It would be more convenient without the quotes, but JSON is primarily
a transfer format and secondarily a human readable format. The latter is
what JSON5 is for. Additionally, it’s faster to crunch through JSON’s
explicitly delimited string literals than more elaborate rules.</p>
<p>I think this syntax gives a good balance of intention and
practicality. Sum types exist nicely in XML and static languages (Rust,
Haskell), and this is always covered by convention in JSON. It seems
about the right time to make this concept first-class.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2026-02-02 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Mon, 02 Feb 2026 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Laws]]></title><link>https://chrisdone.com/posts/laws</link><guid>https://chrisdone.com/posts/laws</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Laws</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Laws</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Laws that apply to our industry (and others) are interesting to me,
and I’m writing up here the ones that often come to mind. I usually
forget the name, so writing them up might be helpful for remembering in
future.</p>
<h1 id="brookss-law">Brooks’s law</h1>
<p>Adding manpower to a late software project makes it later.</p>
<p>Ramp-up time, increased communication overhead are the causes.</p>
<h1 id="parkinsons-law">Parkinson’s Law</h1>
<p>C. Northcote Parkinson’s law: Work expands so as to fill the time
available for its completion. Similarly, in computing, data expands to
fill the space available for storage, or tasks expected of a computer
expand to fill the resources.</p>
<p>Related is William Stanley Jevons’s paradox (<em>Jevons
paradox</em>): Making resource use more efficient leads to more using
more resources, negating the perceived benefits. Computers get faster
and get more memory, so our apps are written in high-level languages
that use more resources to do the same thing, and then the experience is
slow again.</p>
<p>Related: Andy and Bill’s law (of Intel and Microsoft): “what Andy
giveth, Bill taketh away.”</p>
<h1 id="law-of-triviality">Law of Triviality</h1>
<p>C. Northcote Parkinson’s law of trivality, from which bikeshedding
derives, is that within an organization or committee, people will more
passionately argue about trivial matters than difficult, complex
matters, naturally because that requires less thinking.</p>
<h1 id="conways-law">Conway’s Law</h1>
<p>Melvin Conway’s law is:</p>
<blockquote>
<p>Any organization that designs a system (defined broadly) will produce
a design whose structure is a copy of the organization’s communication
structure.</p>
</blockquote>
<h1 id="law-of-leaky-abstractions">Law of Leaky Abstractions</h1>
<p>Joel Spolsky’s law states that every nontrivial abstraction leaks the
details that it’s trying to protect you from. Worse still, if you’ve
only learned the abstraction and not the level below it, you’re
ill-equipped to deal with the leak anyway.</p>
<h1 id="hutbers-law">Hutber’s law</h1>
<p>Patrick Hutber: Improvement means deterioration. If a company tells
you it is improving a service it provides, it almost always means it
will do less for you, charge you more, or both.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2025-09-23 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Tue, 23 Sep 2025 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Argumentum ad colossum]]></title><link>https://chrisdone.com/posts/argumentum-ad-colossum</link><guid>https://chrisdone.com/posts/argumentum-ad-colossum</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Argumentum ad colossum</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Argumentum ad colossum</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>I’m coining a new phrase to use for discussion purposes:
<em>argumentum ad colossum</em>.</p>
<p>It’s very difficult to replicate what worked for one company at
another company, because culture is hard to transfer. This has been
argued in business literature, e.g. Google’s OKRs and silly interviews,
Amazon’s “two-pizza teams”, Netflix’s culture of radical candor, Apple’s
BDFL-style leadership, Toyota’s lean manufacturing systems, Basecamp’s
Shape Up. It’s hard to acknowledge that these can run counter to another
company’s DNA.</p>
<p>In tech circles, there’s commentary about “cargo cult engineering”
(scrum, SRE, fix-bugs-first), or copying methodologies. Similarly,
adoption of specific architectures, technologies and design choices has
been criticised. Kafka event driven architecture, microservices or
monorepos, cloud deploy vs roll-your-own, Kubernetes, chaos monkey,
using TLA+, adopting generative AI, and so on. You can’t transplant a
technological design isolated from other factors, inconveniently. The
full thinking needs to be done.</p>
<p>It reminds me somewhat of <a
href="https://www.lesswrong.com/posts/rHBdcHGLJ7KvLJQPk/the-logical-fallacy-of-generalization-from-fictional">The
Logical Fallacy of Generalization from Fictional Evidence</a>, where
people are essentially arguing from stories, not experience or
science.</p>
<p>Nevertheless I hear people slipping into this line of thinking, of
the form “well, if we were at X giant corporation we would just…”,
including myself, and feel like I need a catchy tongue-in-cheek name, so
here it is: <em>argumentum ad colossum.</em></p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2025-09-14 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sun, 14 Sep 2025 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Applicative-wired monad pattern]]></title><link>https://chrisdone.com/posts/applicative-wired-monad</link><guid>https://chrisdone.com/posts/applicative-wired-monad</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Applicative-wired monad pattern</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Applicative-wired monad pattern</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>In Haskell API design, you sometimes want to model a computation that
looks like a monad, i.e. some things depend on other things, and make
use of do-notation, but you want to be able to statically inspect the
resulting structure, too.</p>
<p>The <code>ApplicativeDo</code> notation attempts to bridge this gap
by a language extension and some conventions. It lets you write
applicatives with do-notation, <strong>but</strong> dependencies between
actions are <strong>explicitly forbidden.</strong> That limits its
utility for this purpose.</p>
<p>Here’s a separate pattern I’ve put to use in a build system library,
but has been used in popular database libraries and FRP libraries,
before I ever did.</p>
<p>You have two types like,</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Action</span> a</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Value</span> a</span></code></pre></div>
<p>The <code>Action</code> is some instance of <code>Monad</code>, and
could be a free monad. The <code>Value</code> is some instance of
<code>Applicative</code>, and can be a free applicative.</p>
<p>The trick is that all functions exposed by the API only return the
type <code>Action (Value a)</code>, and sometimes accept
<code>Value a</code> as arguments. This means you wire up a graph, with
<code>Action</code> containing nodes and <code>Value</code> serving the
edges. You combine multiple output values into a single argument value
via its <code>Applicative</code> instance. Then it’s easy to graph it
out or batch it as needed. Works for SQL DBs (e.g. Rel8), build systems
or FRP (e.g. Reflex).</p>
<p>This does mean you can’t simply run <code>mapM</code> against a
<code>Value [a]</code>, and this often requires a special operator for
the action in the domain in question.</p>
<p>I’m not sure that there’s already name for it, but it’s definitely a
pattern. You see it in quite a few places. Hence pointing it out.</p>
<p>Full code example below. I’ve added an extra <code>f</code> parameter
on the <code>Action</code> type to emphasize that by exposing an API
like this, you can inspect the monad’s structure, but that you can also
keep your monad well-formed (i.e. interpret the <code>Applicative</code>
as <code>Identity</code>). But it’s not necessary to add a parameter to
everything, and in practice all examples I’ve seen do not have a
parameter, and are specialized on a particular type. Sometimes the type
isn’t actually an <code>Applicative</code>, but is similar in spirit
(e.g. DB libraries often have <code>Expr a</code> returned by
<code>Query a</code> monad).</p>
<p>Thanks to Liam Goodacre for his suggestion to eliminate the earlier
inlined Coyoneda in my example. Thanks to Jack Kelly for his suggestion
to use a <code>Coyoneda</code> rather than free-Applicative, as this
example doesn’t need it. Separately, Emeka Nkurumeh has noted that, if
you squint, this is an implementation of relative monads, which I’ll
likely write another post about because it’s very interesting!</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# language KindSignatures, BlockArguments, GADTs, LambdaCase, GeneralizedNewtypeDeriving #-}</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Functor.Coyoneda</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Kind</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Functor.Const</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Monad.Free</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.ByteString</span> <span class="kw">as</span> <span class="dt">S</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.ByteString.Char8</span> <span class="kw">as</span> <span class="dt">S8</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Functor.Identity</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.ByteString</span> (<span class="dt">ByteString</span>)</span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.Map</span> <span class="kw">as</span> <span class="dt">Map</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Map</span> (<span class="dt">Map</span>)</span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.Set</span> <span class="kw">as</span> <span class="dt">Set</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Set</span> (<span class="dt">Set</span>)</span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Monad.Trans.State.Strict</span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a><span class="co">--------------------------------------------------------------------------------</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a><span class="co">-- The applicative-wired monad pattern</span></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Spec</span> f m a <span class="kw">where</span></span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Spec</span><span class="ot"> ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> f (m a) <span class="ot">-&gt;</span> <span class="dt">Spec</span> f m (f a)</span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">Action</span> f m a <span class="ot">=</span> <span class="dt">Action</span> {<span class="ot"> runAction ::</span> <span class="dt">Free</span> (<span class="dt">Coyoneda</span> (<span class="dt">Spec</span> f m)) a }</span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a>  <span class="kw">deriving</span> (<span class="dt">Functor</span>, <span class="dt">Applicative</span>, <span class="dt">Monad</span>)</span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a><span class="ot">act ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> f (m a) <span class="ot">-&gt;</span> <span class="dt">Action</span> f m (f a)</span>
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a>act l f <span class="ot">=</span> <span class="dt">Action</span> <span class="op">$</span> liftF <span class="op">$</span> liftCoyoneda <span class="op">$</span> <span class="dt">Spec</span> l f</span>
<span id="cb2-27"><a href="#cb2-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-28"><a href="#cb2-28" aria-hidden="true" tabindex="-1"></a><span class="co">--------------------------------------------------------------------------------</span></span>
<span id="cb2-29"><a href="#cb2-29" aria-hidden="true" tabindex="-1"></a><span class="co">-- An example</span></span>
<span id="cb2-30"><a href="#cb2-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-31"><a href="#cb2-31" aria-hidden="true" tabindex="-1"></a><span class="ot">example ::</span> <span class="dt">Applicative</span> f <span class="ot">=&gt;</span> <span class="dt">Action</span> f <span class="dt">IO</span> (f (<span class="dt">ByteString</span>, <span class="dt">ByteString</span>))</span>
<span id="cb2-32"><a href="#cb2-32" aria-hidden="true" tabindex="-1"></a>example <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb2-33"><a href="#cb2-33" aria-hidden="true" tabindex="-1"></a>  file1 <span class="ot">&lt;-</span> act <span class="st">&quot;read_file_1&quot;</span> (<span class="fu">pure</span> <span class="op">$</span> S.readFile <span class="st">&quot;file1.txt&quot;</span>)</span>
<span id="cb2-34"><a href="#cb2-34" aria-hidden="true" tabindex="-1"></a>  file2 <span class="ot">&lt;-</span> act <span class="st">&quot;read_file_2&quot;</span> (S.readFile <span class="op">.</span>  <span class="fu">unwords</span> <span class="op">.</span> <span class="fu">words</span> <span class="op">.</span> S8.unpack <span class="op">&lt;$&gt;</span> file1)</span>
<span id="cb2-35"><a href="#cb2-35" aria-hidden="true" tabindex="-1"></a>  <span class="fu">pure</span> <span class="op">$</span> (,) <span class="op">&lt;$&gt;</span> file1 <span class="op">&lt;*&gt;</span> file2</span>
<span id="cb2-36"><a href="#cb2-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-37"><a href="#cb2-37" aria-hidden="true" tabindex="-1"></a><span class="co">--------------------------------------------------------------------------------</span></span>
<span id="cb2-38"><a href="#cb2-38" aria-hidden="true" tabindex="-1"></a><span class="co">-- IO interpretation</span></span>
<span id="cb2-39"><a href="#cb2-39" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-40"><a href="#cb2-40" aria-hidden="true" tabindex="-1"></a><span class="ot">runIO ::</span> <span class="dt">Action</span> <span class="dt">Identity</span> <span class="dt">IO</span> a <span class="ot">-&gt;</span> <span class="dt">IO</span> a</span>
<span id="cb2-41"><a href="#cb2-41" aria-hidden="true" tabindex="-1"></a>runIO <span class="ot">=</span> foldFree (lowerCoyoneda <span class="op">.</span> hoistCoyoneda io) <span class="op">.</span> runAction <span class="kw">where</span></span>
<span id="cb2-42"><a href="#cb2-42" aria-hidden="true" tabindex="-1"></a><span class="ot">  io ::</span> <span class="dt">Spec</span> <span class="dt">Identity</span> <span class="dt">IO</span> x <span class="ot">-&gt;</span> <span class="dt">IO</span> x</span>
<span id="cb2-43"><a href="#cb2-43" aria-hidden="true" tabindex="-1"></a>  io <span class="ot">=</span> \<span class="kw">case</span></span>
<span id="cb2-44"><a href="#cb2-44" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Spec</span> name act&#39; <span class="ot">-&gt;</span> <span class="kw">do</span></span>
<span id="cb2-45"><a href="#cb2-45" aria-hidden="true" tabindex="-1"></a>      <span class="fu">putStrLn</span> <span class="op">$</span> <span class="st">&quot;Running &quot;</span> <span class="op">++</span> name</span>
<span id="cb2-46"><a href="#cb2-46" aria-hidden="true" tabindex="-1"></a>      out <span class="ot">&lt;-</span> runIdentity act&#39;</span>
<span id="cb2-47"><a href="#cb2-47" aria-hidden="true" tabindex="-1"></a>      <span class="fu">pure</span> <span class="op">$</span> <span class="dt">Identity</span> out</span>
<span id="cb2-48"><a href="#cb2-48" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-49"><a href="#cb2-49" aria-hidden="true" tabindex="-1"></a><span class="co">--------------------------------------------------------------------------------</span></span>
<span id="cb2-50"><a href="#cb2-50" aria-hidden="true" tabindex="-1"></a><span class="co">-- Graphable interpretation</span></span>
<span id="cb2-51"><a href="#cb2-51" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-52"><a href="#cb2-52" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">Value</span> (<span class="ot">a ::</span> <span class="dt">Type</span>) <span class="ot">=</span> <span class="dt">Value</span> {<span class="ot"> runValue ::</span> <span class="dt">Const</span> (<span class="dt">Set</span> <span class="dt">String</span>) a }</span>
<span id="cb2-53"><a href="#cb2-53" aria-hidden="true" tabindex="-1"></a>  <span class="kw">deriving</span> (<span class="dt">Functor</span>, <span class="dt">Applicative</span>)</span>
<span id="cb2-54"><a href="#cb2-54" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Show</span> (<span class="dt">Value</span> a) <span class="kw">where</span></span>
<span id="cb2-55"><a href="#cb2-55" aria-hidden="true" tabindex="-1"></a>  <span class="fu">show</span> <span class="ot">=</span> <span class="fu">show</span> <span class="op">.</span> keys</span>
<span id="cb2-56"><a href="#cb2-56" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-57"><a href="#cb2-57" aria-hidden="true" tabindex="-1"></a><span class="ot">runGraph ::</span> <span class="dt">Applicative</span> m <span class="ot">=&gt;</span> <span class="dt">Action</span> <span class="dt">Value</span> m (<span class="dt">Value</span> a) <span class="ot">-&gt;</span> (<span class="dt">Value</span> a, <span class="dt">Map</span> <span class="dt">String</span> (<span class="dt">Set</span> <span class="dt">String</span>))</span>
<span id="cb2-58"><a href="#cb2-58" aria-hidden="true" tabindex="-1"></a>runGraph x <span class="ot">=</span> <span class="fu">flip</span> runState <span class="fu">mempty</span> <span class="op">$</span> graph <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb2-59"><a href="#cb2-59" aria-hidden="true" tabindex="-1"></a>  v <span class="ot">&lt;-</span> x</span>
<span id="cb2-60"><a href="#cb2-60" aria-hidden="true" tabindex="-1"></a>  act <span class="st">&quot;root&quot;</span> (<span class="fu">pure</span> <span class="op">&lt;$&gt;</span> v)</span>
<span id="cb2-61"><a href="#cb2-61" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-62"><a href="#cb2-62" aria-hidden="true" tabindex="-1"></a><span class="ot">graph ::</span> <span class="dt">Action</span> <span class="dt">Value</span> m a <span class="ot">-&gt;</span> <span class="dt">State</span> (<span class="dt">Map</span> <span class="dt">String</span> (<span class="dt">Set</span> <span class="dt">String</span>)) a</span>
<span id="cb2-63"><a href="#cb2-63" aria-hidden="true" tabindex="-1"></a>graph <span class="ot">=</span> foldFree (lowerCoyoneda <span class="op">.</span> hoistCoyoneda go) <span class="op">.</span> runAction <span class="kw">where</span></span>
<span id="cb2-64"><a href="#cb2-64" aria-hidden="true" tabindex="-1"></a><span class="ot">  go ::</span> <span class="dt">Spec</span> <span class="dt">Value</span> m a <span class="ot">-&gt;</span> <span class="dt">State</span> (<span class="dt">Map</span> <span class="dt">String</span> (<span class="dt">Set</span> <span class="dt">String</span>)) a</span>
<span id="cb2-65"><a href="#cb2-65" aria-hidden="true" tabindex="-1"></a>  go <span class="ot">=</span> \<span class="kw">case</span></span>
<span id="cb2-66"><a href="#cb2-66" aria-hidden="true" tabindex="-1"></a>   <span class="dt">Spec</span> string i <span class="ot">-&gt;</span> <span class="kw">do</span></span>
<span id="cb2-67"><a href="#cb2-67" aria-hidden="true" tabindex="-1"></a>    modify (Map.insert string (keys i))</span>
<span id="cb2-68"><a href="#cb2-68" aria-hidden="true" tabindex="-1"></a>    <span class="fu">pure</span> <span class="op">$</span> <span class="dt">Value</span> <span class="op">$</span> <span class="dt">Const</span> (Set.singleton string)</span>
<span id="cb2-69"><a href="#cb2-69" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-70"><a href="#cb2-70" aria-hidden="true" tabindex="-1"></a><span class="ot">keys ::</span>  <span class="dt">Value</span> a <span class="ot">-&gt;</span> <span class="dt">Set</span> <span class="dt">String</span></span>
<span id="cb2-71"><a href="#cb2-71" aria-hidden="true" tabindex="-1"></a>keys <span class="ot">=</span> getConst <span class="op">.</span> runValue</span></code></pre></div>
<p>Example:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- Example:</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="co">-- Run as raw IO:</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="co">-- &gt; runIO example</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="co">-- Running read_file_1</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="co">-- Running read_file_2</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a><span class="co">-- Identity (&quot;hello.txt\n&quot;,&quot;you found me\n&quot;)</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a><span class="co">-- Dependency graph:</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a><span class="co">-- &gt; runGraph example</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a><span class="co">-- (fromList [&quot;root&quot;],fromList [(&quot;read_file_1&quot;,fromList []),(&quot;read_file_2&quot;,fromList [&quot;read_file_1&quot;]),(&quot;root&quot;,fromList [&quot;read_file_1&quot;,&quot;read_file_2&quot;])])</span></span></code></pre></div>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2025-07-11 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Fri, 11 Jul 2025 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[My blog now runs on a Raspberry Pi at home]]></title><link>https://chrisdone.com/posts/pi-blog</link><guid>https://chrisdone.com/posts/pi-blog</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>My blog now runs on a Raspberry Pi at home</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>My blog now runs on a Raspberry Pi at home</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>A mini microblog on Raspberry Pi at home.</p>
<h1>
<a href='/posts/pi-blog/2025-05-09'>2025-05-09</a>
</h1>
<p>I discovered that my new house had <a
href="https://www.ofnl.co.uk/">OFNL</a> internet, which is one of a
handful competing fibre providers in England (others: BT OpenReach,
VirginMedia, Hyperoptic, etc). Some of the infra providers are also the
sole ISP, like VirginMedia and Hyperoptic, whereas BT OpenReach and OFNL
just provide the infra and then companies can offer consumer ISP
services on top of it.</p>
<p>I picked one (<a href="https://www.merula.net/">Merula</a>) who, like
a few others, provide a gigabit connection, and for about £3 per month,
a static IPv4 address.</p>
<p>Some ISPs in the world–even in rich countries–put people behind a <a
href="https://en.wikipedia.org/wiki/Carrier-grade_NAT">CGNAT</a>, as a
way to get more mileage out of the few IPv4 addresses they have. This
means that you can’t listen on a port and have someone directly connect
to you, because the NAT wouldn’t know who to pick. A very sad state of
affairs. I’ve also heard about a German ISP that provides IPv6-only and
then handles all IPv4 connections via a proxy!</p>
<p>In that context, it’s a pretty fortunate situation to be able to get
a static IP at my home address. As a programmer it’s more joyful to have
this.</p>
<p>I grabbed a Raspberry Pi 5 (highly overpowered for a blog), connected
it to my router via gigabit Ethernet, and got it running with a simple
SD card for the root file-system. All logs (journald) are moved to tmpfs
(‘volatile’ storage mode). The blog itself is sync’d via a webhook from
GitHub, and is stored in tmpfs, too. Like this, it should run for a
couple years without the SD card wearing out.</p>
<p>The server is <a href="https://caddyserver.com/">Caddy</a> and the
webhook service is <a
href="https://github.com/adnanh/webhook">webhook</a>, both come as
systemd services, so the effort was very minimal.</p>
<p>There’s no particular technical advantage of you reading this page
from my home, over the Digital Ocean server I’ve had for years, which
only cost me about $10/mo. But it was a fun little project!</p>
<h1>
<a href='/posts/pi-blog/2026-05-09'>2026-05-09</a>
</h1>
<p>It now lives in a little stainless steel T-190 Japanese box.</p>
<p><img src="/images/rasp/IMG_7743.png" /></p>
<p><img src="/images/rasp/IMG_7744.png" /></p>
<p><img src="/images/rasp/IMG_7748.png" /></p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2025-05-09 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Fri, 09 May 2025 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[LLMs]]></title><link>https://chrisdone.com/posts/llms</link><guid>https://chrisdone.com/posts/llms</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>LLMs</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>LLMs</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>This page serves as my place to journal what are hopefully balanced
thoughts on the current AI summer, driven by LLMs.</p>
<h1>
<a href='/posts/llms/2026-07-03'>2026-07-03</a>
</h1>
<p>I enjoyed these quotes by <a
href="https://www.theguardian.com/technology/2023/mar/23/tech-guru-jaron-lanier-the-danger-isnt-that-ai-destroys-us-its-that-it-drives-us-insane">Jaron
Lanier on the topic of AI</a>:</p>
<blockquote>
<p>“A lot of modern enlightenment thinkers and technical people feel
that there is something old-fashioned about believing that people are
special – for instance that consciousness is a thing. They tend to think
there is an equivalence between what a computer could be and what a
human brain could be.” Lanier has no truck with this. “We have to say
consciousness is a real thing and there is a mystical interiority to
people that’s different from other stuff because if we don’t say people
are special, how can we make a society or make technologies that serve
people?”</p>
</blockquote>
<p>In a refreshing twist, his position on LLMs is nuanced. For example,
he seems quite positive about the randomness:</p>
<blockquote>
<p>For Lanier, the classic example of restricted choice is Wikipedia,
which has effectively become the world’s encyclopedia. “Wikipedia is run
by super-nice people who are my friends. But the thing is it’s like one
encyclopedia. Some of us might remember when on paper there was both an
Encyclopedia Britannica and Encyclopedia Americana and they provided
different perspectives. The notion of having the perfect encyclopedia is
just weird.”</p>
<p>So could the new chatbots challenge this? “Right. That’s my point. If
you go to a chatbot and say: ‘Please can you summarise the state of the
London tube?’ you’ll get different answers each time. And then you have
to choose.” This programmed-in randomness, he says, is progress. “All of
a sudden this idea of trying to make the computer seem humanlike has
gone far enough in this iteration that we might have naturally outgrown
this illusion of the monolithic truth of the internet or AI. It means
there is a bit more choice and discernment and humanity back with the
person who’s interacting with the thing.”</p>
</blockquote>
<p>This is an interesting perspective. Though I’m not sure how well it
holds up to scrutiny due to bias easily put into models via
reinforcement learning, which is discussed in <a
href="https://www.economist.com/briefing/2026/06/25/ai-models-values-are-very-different-from-most-peoples"><em>AI
models’ values are very different from most people’s</em></a>. I’m also
not sure how this squares with <a
href="https://en.wikipedia.org/wiki/Digital_Maoism">his criticism of
Wikipedia</a> the bulk of which do apply to LLM models (mainstream
voice, sterile style, abuse by states to manipulate).</p>
<h1>
<a href='/posts/llms/2026-06-24'>2026-06-24</a>
</h1>
<p>Two articles on the same topic about or encompassing workslop, which
I thought were good and helpful:</p>
<ul>
<li><a
href="https://blog.glyph.im/2026/06/adversarial-communication.html">“Adversarial
communication”</a>, great article.</li>
<li><a href="https://tombedor.dev/human-attention-and-human-effort/">If
you are requesting human attention, demonstrate human effort.</a></li>
</ul>
<h1>
<a href='/posts/llms/2026-06-05'>2026-06-05</a>
</h1>
<p>I’m connecting a few areas of thought together in the context of
LLMs.</p>
<ul>
<li>The Mythical Man Month</li>
<li>Worse is Better</li>
<li>Moloch</li>
</ul>
<p>Firstly, some Fred Brooks <a
href="https://chrisdone.com/posts/the-mythical-man-month-insights/">comments</a>
that seem relevant to whether LLMs may fundamentally change sofware
development:</p>
<blockquote>
<p>I believe the hard part of building software to be the specification,
design and testing of this conceptual construct, not the labour of
representing it and testing the fidelity of the representation. […] If
this is true, building software will always be hard. There is inherently
no silver bullet.</p>
</blockquote>
<blockquote>
<p>More seriously, even perfect program verification can only establish
that a program meets its specification. The hardest part of the software
task is arriving at a complete and consistent specification, and much of
the essence of building a program is in fact the debugging of the
specification.</p>
</blockquote>
<p>Separately, <a
href="https://dreamsongs.com/WorseIsBetter.html">commentary</a> by
Richard P. Gabriel indicating that this may not matter for industry, and
so LLM adoption may be inevitable:</p>
<blockquote>
<p>The essay argues simple, hacked-together software that makes it to
market first will often outcompete better and more elegant designs.</p>
<p>Gabriel offers the examples of the adoption of C over Lisp, Unix over
Lisp machines and VMS, and x86 over reduced instruction set computers as
examples of technically worse solutions defeating more elegant ones by
arriving to market first.</p>
</blockquote>
<p>Finally, <a
href="https://slatestarcodex.com/2014/07/30/meditations-on-moloch/">a
deeper meditation on why this happens generally by Nick Land</a>, which
touches on failed collective action, race to the bottom, etc.</p>
<blockquote>
<p>Moloch is exactly what the history books say he is. […]</p>
<p>He always and everywhere offers the same deal: throw what you love
most into the flames, and I can grant you power.</p>
<p>As long as the offer’s open, it will be irresistible.</p>
</blockquote>
<h1>
<a href='/posts/llms/2026-05-25'>2026-05-25</a>
</h1>
<p>A recently recurring thought is that many people criticise LLMs/“AI”
on the wrong terms. I may be accidentally coming back to McLuhan,
arguing that people should be looking at the medium and not the message,
but I see arguments like “LLMs aren’t good at X”, or “good but not human
level good”, etc. at e.g. writing code or reasoning. There’s usually an
anecdote involved.</p>
<p>The questions should, in my view, <em>assume</em> that LLMs will
attain fully realised potential, after presumably a protracted boom/bust
iteration, and then ask whether and how that would affect how we enjoy
life and conduct business.</p>
<!--
Reading/blogroll:

* https://jola.dev/posts/the-social-contract-of-writing
* https://www.seangoedecke.com/steering-vectors/
* https://ratfactor.com/ascetic-computing
* https://jacobharr.is/personal/i-dont-vibe-code
* https://purplesyringa.moe/blog/programming-used-to-be-free/
-->
<h1>
<a href='/posts/llms/2026-03-12'>2026-03-12</a>
</h1>
<p><em>The Medium is the Message</em> keeps coming to mind again and
again, as people seem frequently surprised by the side-effects of the
adoption of LLMs. The content (articles, code, images) produced by LLMs
is not the higher order bit, but how they <em>change</em> the people and
institutions that use them.</p>
<p>No other changes in viewpoints to report this time.</p>
<h1>
<a href='/posts/llms/2026-02-07'>2026-02-07</a>
</h1>
<p>I shared a thought on a big dev call at work, when talking about
agentic “skill” based workflows, that one problem is that you lose Flow,
which is often one of the most enjoyable ways to work as a software dev
(most of the rest is frankly frustration and toil, but valuable). Today
I saw <a
href="https://haskellforall.com/2026/02/beyond-agentic-coding">this
post</a> by Gabriella Gonzalez about the same topic, with examples of
interfaces that try to do a better job of that. I’m not as gung ho about
LLMs as Gabriella is, but I’m enjoying these simple articles that
discuss a particular technical point.</p>
<p>This way of thinking has been on my mind for some time, as generally
I am always working to reduce feedback loops in my work, never increase
them. (This doesn’t follow from using Emacs, but Emacs can help with
that: look at magit.) It’s why slow CI ruins my day, and why most cloud
ops like Terraform are painful (e.g. Amazon resources aren’t content
addressable, so checking for changes to apply is always
O(n)–brutal!).</p>
<p>Separately, but somewhat related; arguably, there’s a certain <a
href="https://en.wikipedia.org/wiki/Psychogeography">psychogeography</a>
to “walking around” a codebase when doing an update or refactor, taking
the scenic route reminds you of the landscape and dark alley ways, it
activates and gently tickles parts of your brain in a way that I imagine
is valuable for the larger work, which is an experience removed by being
teleported from A-Z.</p>
<h1>
<a href='/posts/llms/2026-01-30'>2026-01-30</a>
</h1>
<p>A <a href="https://arxiv.org/abs/2601.20245">paper</a> discusses a
similar topic that I’ve addressed in this microblog, which is the
negative relationship between skill and using GenAI.</p>
<p>I haven’t generated anything since the last update. But I hand wrote
a little <a
href="https://github.com/chrisdone-artificial/llm-parse">experimental
library that uses a free applicative to both declare a GBNF grammar and
consume the output back into Haskell</a>. I didn’t add an
<code>Alternative</code> instance (yet) to support disjunction in the
grammar, but this direction appeals to me. I’ve been dabbling with the
same llama3.2 (3b model) via llama.cpp’s server locally on the same
MacBook Pro M4 Max. It’s quite easy to get reliable outputs. I intend to
dabble more with this in coming weeks.</p>
<p>I’ve been recently thinking that the whole phrasing around
interacting with LLMs has become increasingly anthropomorphic, and
thought of a clever mental hack to avoid it: instead of “talking to
Claude,” say “talking to the computer,” (doesn’t that sound silly!) and
instead of “AI generated” or “LLM generated,” simply say “computer
generated.” (How dull!) I find it thoroughly cuts through the illusion
that we are doing anything more. But YMMV.</p>
<h1>
<a href='/posts/llms/2025-12-20'>2025-12-20</a>
</h1>
<p>Another positive experience I’ve had with LLMs is finding an
opportunity to redo the frontend of a fairly simple web app, which was
previously a server-side app at work. It’s an internal tool, so it’s
highly suited to this kind of mode of working.</p>
<p>I remain uncomfortable shelling out my cognition for load-bearing
code, especially on the backend, and I’m increasingly sure in my
determination that one should only genAI things they could do readily
themselves for work that they back and own.</p>
<p>Elsewhere, I’m poking at formal methods. If, indeed, the trajectory
of software development–in industry–is away from the labor of
implementation, there may perhaps be space for verification. The feeling
might pass, but it feels possible that LLMs may make formal methods
mainstream. That wouldn’t be so bad, as a good subset of programmers
like formal thinking. Whether software, subject to market forces and
competition, will get any better or worse objectively, I’m
skeptical.</p>
<h1>
<a href='/posts/llms/2025-12-03'>2025-12-03</a>
</h1>
<p>My experience with LLMs since my last update has been both positive
and negative.</p>
<p>On the one hand, I’ve seen a quality and comprehension drop in some
programmers. “I vibed it” is becoming a familiar explanation for both.
I’m increasingly concerned.</p>
<p>On the other hand, I have found a workflow with LLMs that works for
me. For those things that I could write myself and practically see in my
head, this flow makes me happy:</p>
<ol type="1">
<li>Prompt a tool like Cursor or Claude Code with a paragraph
description of what to do and where, with the permission to edit
files.</li>
<li>Close it and return to Emacs.</li>
<li>Browse through the diff in magit.</li>
<li>Edit almost everything, rewrite some things, leave others that are
good.</li>
<li>Continue myself by hand as normal.</li>
</ol>
<p>This has been quite effective for me as a means to speed up tasks
which are doing what I’ve done elsewhere with small differences. I’m
using it as glorified autocomplete.</p>
<h1>
<a href='/posts/llms/2025-10-24'>2025-10-24</a>
</h1>
<p>I’ve had what I’d describe as “hole in one” experience where I
generated two Haskell packages, sse-conduit and llm-conduit, from a
single Claude prompt, which both compiled and worked the first time when
pointing it at llama.cpp’s server. This gave me pause as in the past I
would enjoyed sitting down to write these and publishing them. Given
that the whole thing took about 10 minutes, I didn’t do either.</p>
<p>I call this a funny name like “hole in one” because it’s not a normal
experience. I had a few weeks prior implemented the same thing manually
with Emacs Lisp, so I wasn’t entirely robbed of the experience. I
believe I’m arriving at a new standpoint which is that one may “vibe”
projects, but only those things they could do themselves readily. The
exercise of writing is often as valuable as the written thing.</p>
<p>The more things that you vibe that you do not understand, the more
your knowledge will stand still and that muscle will not be exercised,
and atrophy. By contrast, if you only vibe things that you already
understand fully, but do the hard work on everything else, you’ll
continue growing, but will also get the accelerative edge of LLM
vibing.</p>
<h1>
<a href='/posts/llms/2025-09-23'>2025-09-23</a>
</h1>
<p>Harvard published <a
href="https://hbr.org/2025/09/ai-generated-workslop-is-destroying-productivity">this
article defining “workslop”</a>, a new term for when someone substitutes
hard thinking for LLM generated slop. I had been thinking about this
recently, having witnessed it at work, but hadn’t articulated it yet, so
I’m glad for the new term.</p>
<p>I accidentally discovered <a
href="https://jacobin.com/2024/02/holly-herndon-ai-music-composition">this
article</a> while looking up Holly Herndon, I enjoyed the reframing of
LLMs from “artificial intelligence” to “collective intelligence”, which
more accurately describes what a large language model is, and sounds a
bit more positive and inclusive.</p>
<p>I got llama.cpp working from Emacs for both regular queries and
GBNF-constrained outputs. I’m happy with the outputs, though I’ve not
been using it for a couple weeks. Will come back to it.</p>
<p>Current mood: still interested to dabble more. Currently sceptical
that organisations across the board are benefitting from LLMs. I read in
the Economist that more small, boutique models, aka SLMs, are becoming
preferred over the Big models provided by OpenAI, Anthropic, etc. which
makes some sense.</p>
<h1>
<a href='/posts/llms/2025-08-19'>2025-08-19</a>
</h1>
<p>Since the last update, I’ve experimented with local LLM models on my
MacBookPro Max M4, which can run 3b parameter models. I wanted to
approach the whole LLM hype as a tool, like grep or awk, and see whether
there was a niche for it as a way of making free text tractable, rather
than as some kind of sci-fi oracle, as many people seem to treat it. I
wrote a module for Emacs that could stream responses from Ollama.</p>
<p>Those models are very unpredictable as an individual observer. I
tried out Ollama’s “tool use”, which is when a model will reply with a
specific format to call a function when given a prompt of the right
schema. That’s also unreliable (to the extent I discount its viability
for my own purposes), because the mechnism is the same as normal
prompting and generation.</p>
<p>A tool that might be viable is GBNF, which is a BNF grammar format
that llama.cpp supports; it is a filter function that sits very close to
the generation of tokens, and discards tokens that do not match the GBNF
grammar. This is promising because you can at least rely on the output
syntax if not the meaning. It also works well on small models, and is
expensive on larger models. Ollama are not planning to support it, but
llama.cpp does, so I will abandon the former in favor of the latter.</p>
<p>In code generation, I’ve experimented with fully agentic “make a PR
to do x”, to a 50% success rate. Code review bots are hit and miss at
the moment. Failure meaning, it would have been easier and mentally more
nourishing to do a task myself than to deal with the failed
interaction.</p>
<p>I’ve found that cloud LLMs are quite good replacements for Google
search, to discover direct sources. I’ve in contrast found that
exploring ideas like architectures and such to be unhelpful. It has
ironically renewed my interest in theory (TLA+, Liquid Haskell), tools
that make me think better, rather than delegating my thinking.</p>
<p>I had a month of apathy for working on my open source scripting
language, Hell, due to a fairly bleak outlook for niche languages due to
LLMs. But that passed and my interest came back.</p>
<p>I’m not an economist, but hopefully no winter or crash is coming.</p>
<p>Overall, present outlook is: tinkering with mild interest, local
first, so-so performance for job-related tasks, using as a Google++,
avoiding delegating thinking, renewed interest in learning theory.</p>
<h1>
<a href='/posts/llms/2025-06-04'>2025-06-04</a>
</h1>
<p>Small update: I’d presently describe my outlook as sceptical. I go in
cycles, of long troughs of scepticism, with very, very, brief (one-day),
widely spread out, spikes of FOMO and belief that AI is an existential
situation for software developers (see previous 2025-04-18 thought
dump). But those are becoming more infrequent. I think I see which way
the trend for me is going.</p>
<p>Having cut out the final vestige of social media (RSS feeds; BazQux)
from sheer disinterest, and digital devices in the evening entirely, I
am also serene and a little bored by the whole thing. But it still does
play on the minds of some friends.</p>
<p>I might change my mind on the next update, we’ll see.</p>
<h1>
<a href='/posts/llms/2025-04-18'>2025-04-18</a>
</h1>
<p>I’ve been collecting thoughts on LLMs in a peacemeal way. I add to
this document from time to time. It’s not an article as such.</p>
<ul>
<li>Hype: On forums like HN people have long, familiar, arguments about
whether AI is hyped or not. This is consistent with any other hyped
thing, like crypto or micro services or whatever.</li>
<li>Objective value: Tools have gotten very good at generating code,
which means that some people’s work, especially those which involve
generating throwaway things which are iterated on quickly, has been
accelerated, and some tasks which were previously inaccessible to people
who didn’t have the patience to wait through poorly documented APIs is
now accessible.</li>
<li>Not learning: By looking at any topic which is not sufficiently
exposed in the training data, one can see that, for example, an
individual human can learn a given topic and it doesn’t take millions of
examples to learn a thing, because we can use reasoning –symbolic
reasoning/manipulation– to learn a program language which has just one
book, for example. Whereas the LLM doesn’t actually learn the programing
language, but essentially is learning how to parrot it as if it’s a
human language. This is why all the popular models are kind of crap at
Haskell and cannot speak Lojban at all, despite there being a complete
and comprehensive book describing Lojban’s grammar, semantics,
dictionaries and everything like that.</li>
<li>If it’s not written, it doesn’t exist: Essentially, if someone
hasn’t written about it in detail, and posted it online or in a book,
then it’s basically a piece of human insight which is not accessible to
an LLM. For example, if nobody ever talked about print debugging online
or in books, and then you asked an LLM about different ways to debug a
program, I’m quite confident the answer would not mention any concept of
printf debugging because that is a completely human experience which is
interactive and comes from experience.</li>
<li>Objective benefit: LLMs essentially turn human language into code
which is digestible, analysable, translatable, summarizeable and
generable. That means we can apply all of our regular engineering tools
like compression and linting and test suites and DSLs. Modulo
nondeterminism.</li>
<li>Objective limitation: As implemented, we know that LLMs are capable
within their probabilistic transformers to estimate answers to
questions, but, for example, cannot count the individual letters in a
word or do basic arithmetic. (At the time of writing; these leaks will
be plugged eventually by postprocessing and tools, I’m sure.) Update:
see <a href="https://arxiv.org/pdf/2402.14903">Tokenization counts: the
impact of tokenization on arithmetic in frontier LLMs</a>.</li>
<li>Speculation on anthropomorphism: I think the reason that LLMs
appeared to reason is that the base model, which is essentially a
snapshot of the Internet, is then of course trained on millions of
conversations in which a question is posed and an answer is generated,
which can give the appearance and impression of comprehension and an
internal mental model. Clever hans.</li>
<li>Relating to language theory: I’m reminded of a chapter in Stephen
Pinker‘s book The Blank Slate, in which he discusses the case of a young
woman who has a developmental issue such that she is not able to reason
or function independently, but is able to speak and tell long, detailed
stories, which are completely fabricated, but which have an internally
consistent grammar and a consistent storyline. In this chapter Pinker is
pointing out that you can have a grasp of language, but no grasp of
logic reasoning et cetera.</li>
<li>Relation to a consistent pattern of abstraction due to layers of
complexity: the MIT book Structure and Interpretation of Computer
Programs was switched from a from-the-ground-up, principles first,
implementation of various topics, to essentially a goodie bag of
scientific ways of using vast APIs and Python. And this is completely
not a criticism of Abelson or Sussman: in fact, this reflects a deep
insight; that they had the foresight and integrity to accurately reflect
in the education. Hardware was too complex; now it’s been abstracted
away. The operating system is a layer of abstraction, and the
programming language is a layer of abstraction. And now there is a
language which is not only a black box, but it’s also probabilistic… so
it’s yet another layer of unpredictability.</li>
<li>Dijkstra on anthropomorphism:
<ul>
<li>People talking about “asking it..” and “it thinks…” etc. makes me
feel icky.</li>
<li>Quote from EWD854: I think anthropomorphism is worst of all. I have
now seen programs “trying to do things”, “wanting to do things”,
“believing things to be true”, “knowing things” etc. Don’t be so naive
as to believe that this use of language is harmless. It invites the
programmer to identify himself with the execution of the program and
almost forces upon him the use of operational semantics.</li>
</ul></li>
<li>The Lisp Curse: see <a
href="https://chrisdone.com/posts/the-llm-curse">my other
article</a></li>
<li>A prior colleague remarked, “Category theory is white magic, AI is
black magic.” It stuck with me as it succinctly summarises much of the
above.</li>
<li>Humans as machines: Dijkstra and Frank Herbert have this in common:
Dijkstra railed against anthropomorphising machines, but he also argued
against treating humans in mechnistic terms, i.e. <a
href="https://chrisdone.com/posts/ai-machine-thinking">treating them
like machines.</a> It’s a funny way to flip things around.</li>
</ul>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2025-04-18 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Fri, 18 Apr 2025 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[The LLM Curse]]></title><link>https://chrisdone.com/posts/the-llm-curse</link><guid>https://chrisdone.com/posts/the-llm-curse</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>The LLM Curse</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>The LLM Curse</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>I encountered a package, and 99.9% of the Haskell code of that
package was–proudly!–written using Claude. I took a browse through the
code.</p>
<p>Something that came to mind was The Lisp Curse: Broadly speaking, the
Lisp curse is that syntactic abstraction, and extension of the language,
is so powerful that Lisp programmers don’t bother to buy into broader
abstractions. They don’t make compromises with the community in order to
get things built into the language in the same way as, say, Haskell
programmers do. A lot of long discussions in the GHC proposals list
could often just be a macro in Lisp, for example. So, in a way, every
large project in Lisp is kind of reinventing many ideas sui generis, and
you’re not advancing <em>the language</em> forward.<a href="#fn1"
class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a>
Whereas, one could argue, many ideas that have developed in Haskell,
that were put into the language itself, have spread to other languages.
It’s ironic because when you think of assembler or C, that’s
(reinvention) the kind of thing that <em>they</em> suffer with, and it’s
not something that you would imagine a really high-level language like
Lisp would suffer with.</p>
<p>How a language interacts with <em>the people</em> that use it is
quite important.</p>
<p>I am starting to wonder whether this practice of vibe coding,
i.e. having 99% of the code generated by an LLM interaction, may lead to
a similar problem. If it’s so cheap for me to generate walls of code
which have loads of repetition, simply because I can just drop it and
re-create it on a whim, that reduces the value of abstraction and it
reduces another human’s interest in reading that code. (I can’t be the
only one who has zero motivation to read AI-generated code.) In other
words, you start losing interest in actually programming Haskell, and
the particular language matters even less, so now every project out
there will, basically, not have to share any kind of abstractions or
ideas, because you’re just going to use an AI to explain someone else’s
project to you anyway.</p>
<p>Then we’re back to The Lisp Curse. Coming to a language near you. The
LLM Curse?</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Parenthetically, I don’t worry too
much about this for Elisp because I consider Emacs to be entirely about
being selfish and focusing only on your own needs. I’m actively annoyed
if they update the language.<a href="#fnref1" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2025-04-12 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sat, 12 Apr 2025 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Less-Than Estimation]]></title><link>https://chrisdone.com/posts/less-than-estimation</link><guid>https://chrisdone.com/posts/less-than-estimation</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Less-Than Estimation</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Less-Than Estimation</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<h2 id="mechanics">Mechanics</h2>
<p>A method of estimation I’ve used successfully on a bunch of projects
over the years goes like this. Estimations are one of four choices:</p>
<ul>
<li><code>&lt;hour</code></li>
<li><code>&lt;day</code></li>
<li><code>&lt;week</code></li>
<li><code>&lt;month</code></li>
</ul>
<p>I call it “less than estimation” because if a given piece of work is
obviously under an hour, your estimate is <code>&lt;hour</code>. If it’s
not obvious, you bump it up to <code>&lt;day</code>. If it doesn’t
obviously fit within a day, bump it up to a <code>&lt;week</code>. If
you’re not sure it’ll fit into a week, my experience says that it could
take even three weeks, so bump it up to <code>&lt;month.</code></p>
<p>Finally, if it doesn’t obviously fit into a month, your powers of
estimation have been exhausted: break the thing down into smaller tasks
that can be estimated. This also applies to the fact that some people
may think that a task takes about two weeks, so they don’t want to bump
it up to a month. But if it takes 2 weeks, then you can split it into
two tasks.</p>
<h2 id="advantages">Advantages</h2>
<p>There are a few advantages to making estimates like this:</p>
<ol type="1">
<li>You don’t have to be too precise with granular numbers over
something that is inherently imprecise. That makes decision-making
quicker. No dithering!</li>
<li>People think in terms of time units. An hour, a day, a week, or a
month fit neatly into people’s heads without extra thinking
involved.</li>
<li>Time units are also concrete: people can use them directly, unlike
T-shirt sizing that is abstract for people to think about.</li>
<li>Often managers/stakeholders don’t care particularly whether it’s two
or three of something, they just want that when you estimate something
that it’s delivered on time. It’s better to be predictable than fall
short and lose trust.</li>
<li>Less experienced devs have trouble breaking down work into
digestible units, this method encourages that.</li>
</ol>
<h2 id="considerations">Considerations</h2>
<p>One consideration is that this can either be considered non-additive
(like T-shirt sizing), or can be additive, but needs special software to
add them up. E.g. 1 month = 4 weeks, 1 week = 5 days, 1 day = 8 hours,
etc. Either works for me. I think on paper organizations like to work
without adding up estimates, but in practice that’s what everybody needs
anyway.</p>
<p>A handy way to think about the priorities in this scheme is: unit up,
split down. I.e. estimates always jump up to the next unit if they grow.
But your estimates should never be reduced in unit (by e.g. being
pressured by stakeholders), and instead be split into separate
estimates, if possible. If it’s easy to split a week up into two days,
great! If it’s not, perhaps the week was the right choice after all.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2025-02-04 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Tue, 04 Feb 2025 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Registers of code authoring]]></title><link>https://chrisdone.com/posts/code-register</link><guid>https://chrisdone.com/posts/code-register</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Registers of code authoring</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Registers of code authoring</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>I’ve recently been thinking about the fact that there are very
distinct <a
href="https://en.wikipedia.org/wiki/Register_(sociolinguistics)">registers</a>
(for lack of a better word) of authoring code, for me, depending on the
type of project.</p>
<ul>
<li>Work codebases: in my experience over a couple decades, are of
medium standard; we do our best with expedience coming first, and code
reviews attend to quality.</li>
<li>Open source projects: especially libraries, tend to be exhibitions
of your best, beauty and good taste is emphasised, you often see
innovation, idealism, yak shaving, going down the garden path.</li>
<li>My personal Emacs config: tidy in my own way, but I don’t need to
impress anyone, I don’t need to make anything reusable. I inline all
dependencies because I have no need to stay up to date. In fact
stability is the #1 priority. It’s like slow food. It’s my own little
work bench and home at the same time.</li>
<li>Shell scripts: they never really grow beyond one file and can be
wasteful, avoid any abstraction or reuse, and generally just do the job
and don’t worry about modelling the domain too much. I’ve gotten a lot
more enjoyment out of this since making <a
href="https://chrisdone.github.io/hell">Hell</a>.</li>
</ul>
<p>These all tend to talk about how style and aesthetics and quality are
balanced based on the user of the code, and there’s intent in there
somewhere. A possible new register (or complete lack of one) may be AI
generated projects, but we’ll see. They all have their respective
merits.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2025-02-01 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sat, 01 Feb 2025 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Hell (Haskell shell): Year in Review]]></title><link>https://chrisdone.com/posts/hell-year-in-review-2025</link><guid>https://chrisdone.com/posts/hell-year-in-review-2025</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Hell (Haskell shell): Year in Review</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Hell (Haskell shell): Year in Review</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p><a href="https://chrisdone.github.io/hell/">Hell</a> is my little
shell scripting language which is a thin layer<a href="#fn1"
class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a>
over Haskell, using its syntax, its standard library and runtime, with a
simpler static type system. You can find <a
href="https://chrisdone.github.io/hell/examples/">examples here</a>.</p>
<p>Over the year of 2024, I’ve written a few non-trivial shell scripts
in Hell at work, and now a few colleagues have used it, too. Now I can
use that to evaluate strengths and weaknesses of it as a tool. I can’t
really share those shell scripts because it’s not open source, but I’ll
drop in some contrived example code at the start of each heading as an
amuse-bouche. The short version of work scripts is:</p>
<ul>
<li>Generating an HTML page summarising deployments by talking to Git
and Terraform and pushing it somewhere to be served up as a web page.
Like a small, read-only version of ArgoCD.</li>
<li>Triggering notifications when deploys happen.</li>
<li>Script to import many “things” via our own customer API in an
idempotent way.</li>
<li>Running end-to-end tests involving launching processes together and
coordinating where they write and what happens when one fails, etc.</li>
<li>Generally; talking to various APIs (Notion, Intercom, GitHub,
etc.).</li>
</ul>
<p>In Hell, I also implemented type inference, record types, sum types,
and added a whole bunch of library functions.</p>
<h2 id="practical">Practical</h2>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Run two things concurrently and return both results</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>  (left, right) <span class="ot">&lt;-</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>    Async.concurrently</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>       (Main.curl <span class="st">&quot;https://worldtimeapi.org/api/timezone/Europe/London&quot;</span>)</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>       (Main.curl <span class="st">&quot;https://worldtimeapi.org/api/timezone/Europe/Rome&quot;</span>)</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>  Text.putStrLn left</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>  Text.putStrLn right</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Run two things concurrently and return the one that completes first</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>  result <span class="ot">&lt;-</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>    Async.race</span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>       (Main.curl <span class="st">&quot;https://worldtimeapi.org/api/timezone/Europe/London&quot;</span>)</span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>       (Main.curl <span class="st">&quot;https://worldtimeapi.org/api/timezone/Europe/Rome&quot;</span>)</span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Either</span><span class="op">.</span><span class="fu">either</span> Text.putStrLn Text.putStrLn result</span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>curl <span class="ot">=</span> \url <span class="ot">-&gt;</span> <span class="kw">do</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>  (out, err) <span class="ot">&lt;-</span> Text.readProcess_ (Process.proc <span class="st">&quot;curl&quot;</span> [url])</span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>  <span class="dt">IO</span><span class="op">.</span><span class="fu">pure</span> out</span></code></pre></div>
<p>I’ve seen that it scales quite well e.g. to scripts that are a few
hundred lines, without feeling that the file is getting out of hand.
That’s not a surprise and is the main reason I decided to make this
project in the first place.</p>
<p>Because the runtime performance is about as good as GHCi, it seems to
be fast enough for all purposes I’ve used so far. Really, scripting
languages only need to be nimble enough not to show themselves as being
slower than the I/O and sub-process work they inevitably perform.</p>
<p>Concurrency in Haskell is very good. Some say “best in class,” which
is debatable, but it’s had green threads for decades and has a maturity
and predictability about it. Hell grabs that power tool from the shelf
and puts it under your belt. So, things like “race” or “map
concurrently” are things you often want in a shell script, because many
things are just I/O intensive and can sometimes be embarrassingly
parallel jobs. The other benefit is that you often want to run N
sub-processes concurrently for a long time, such as web services and
attendant jobs, and structured concurrency with <code>Async</code> makes
that neat and tidy.</p>
<p>Another absolute win, which I’m sure the PowerScript and Oil Shell
people will tell you, is that using <em>real</em> data structures in a
script is phenomenal. I’ve got a script at work (The Deploy Dashboard)
that uses <code>Map</code> and <code>Set</code> in non-trivial ways to
compute time slices over a Git commit history, for example. They’re
ample efficient, but mostly the benefit comes from using a sensible data
structure that has a predictable behaviour about it.</p>
<h2 id="ergonomic">Ergonomic</h2>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  env <span class="ot">&lt;-</span> Environment.getEnvironment</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Maybe monad works!</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Maybe</span><span class="op">.</span><span class="fu">maybe</span> (Text.putStrLn <span class="st">&quot;Oops!&quot;</span>) Text.putStrLn</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>     (<span class="kw">do</span> path <span class="ot">&lt;-</span> List.lookup <span class="st">&quot;PATH&quot;</span> env</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>         home <span class="ot">&lt;-</span> <span class="dt">Functor</span><span class="op">.</span><span class="fu">fmap</span> Text.reverse <span class="op">$</span> List.lookup <span class="st">&quot;HOME&quot;</span> env</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>         <span class="dt">Monad</span><span class="op">.</span><span class="fu">return</span> (Text.concat [path, <span class="st">&quot; and &quot;</span>, home]))</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Either monad works!</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Either</span><span class="op">.</span><span class="fu">either</span> Text.putStrLn Text.putStrLn</span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>    (<span class="kw">do</span> x <span class="ot">&lt;-</span> Main.parse <span class="st">&quot;foo&quot;</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>        y <span class="ot">&lt;-</span> Main.parse <span class="st">&quot;foo&quot;</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Monad</span><span class="op">.</span><span class="fu">return</span> (Text.concat [x,y]))</span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>parse <span class="ot">=</span> \s <span class="ot">-&gt;</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a>  <span class="kw">if</span> <span class="dt">Eq</span><span class="op">.</span>eq s <span class="st">&quot;foo&quot;</span></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a>     <span class="kw">then</span> <span class="dt">Either</span><span class="op">.</span><span class="dt">Right</span> <span class="st">&quot;foooo :-)&quot;</span></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a>     <span class="kw">else</span> <span class="dt">Either</span><span class="op">.</span><span class="dt">Left</span> <span class="st">&quot;oh noes!&quot;</span></span></code></pre></div>
<p>As the syntax is familiar, it’s pretty ergonomic. It’s a very, very
small subset of Haskell, as can be seen in <a
href="https://chrisdone.github.io/hell/examples/">the examples.</a> I
think when I write it, I’m mostly checking what’s in <a
href="https://chrisdone.github.io/hell/api/">this small page</a> of API
functions. I think the familiarity and small scope makes it predictable
and that means one can approach a task using it with confidence.</p>
<p>As a Haskeller, being easy to write is great. But the larger part is
being easy to read. It was easy at the start of this project in early
2024 to say I like reading the code, because I was the only user. Now,
after reading the code of a few colleagues, I still find it very easy to
read the code. That’s a big win for me.</p>
<p>When writing scripts for work, I use the <code>--check</code> flag to
typecheck it regularly. (Pairing with
<code>watchexec</code>/<code>entr</code> is snappy.) The type system
saves me time, as often scripts will run something that’s sluggish like
Terraform that takes ages to do anything, and then you find out you made
a silly mistake after all that. So it improves the feedback loop.</p>
<h2 id="low-risk">Low risk</h2>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>  Temp.withSystemTempFile <span class="st">&quot;example&quot;</span> \filePath handle <span class="ot">-&gt;</span> <span class="kw">do</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    Text.putStrLn <span class="op">$</span> Text.concat [<span class="st">&quot;Created temp file &quot;</span>, filePath]</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> proc <span class="ot">=</span> Process.setStdout (Process.useHandleClose handle) <span class="op">$</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>         Process.proc <span class="st">&quot;ls&quot;</span> [<span class="st">&quot;-al&quot;</span>]</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>    Process.runProcess_ proc</span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>    contents <span class="ot">&lt;-</span> Text.readFile filePath</span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>    Text.putStrLn contents</span></code></pre></div>
<p>The nice thing about this project is that because it doesn’t
deviate<a href="#fn2" class="footnote-ref" id="fnref2"
role="doc-noteref"><sup>2</sup></a> from Haskell, one could easily
translate any script literally to Haskell by adding some imports and
then compile it to a binary. So any scripts written in Hell has a low
bus factor: you can always just “lift” it into Haskell and be on a
maintained ecosystem. This is incidentally the same answer to the
question: what if my script isn’t fast enough? Haskell compiles to
competitive machine code with a high throughput garbage collector, so if
down the line a Hell script became part of some core infra and also
became a performance problem, you could compile it to get a huge
performance boost, at the cost of more complicated build infrastructure
vs Hell which is just a single-binary interpreter.</p>
<p>The other part is that I haven’t added any backwards-incompatible
changes, because I made it easy for myself not to, in two ways.</p>
<p>The first way to do that is to just Learn to Stop Worrying and let
things stay in that I don’t like. I’ve written about this <a
href="https://chrisdone.com/posts/ipp/">elsewhere</a>; not breaking
things for your users doesn’t come naturally, because, ew, I hate this
function and regret it being born! In the long-run, though, it makes
everything easier to just accept that some small blemishes.</p>
<p>The other way is to defer 95% of design decisions to the host
language (Haskell) and its libraries. So, if you see any API in Hell
that you don’t like, well, it’s not <em>my</em> design, sorry! It’s
standard Haskell! None of the above code sample is my design, it’s all
lifted from Haskell. Getting into API design is tempting, and a sign of
hubris… it can drive some to madness!</p>
<p>A final benefit of not diverging is that one can use any regular
Haskell source formatter. A source formatter is a huge undertaking for
any language with a big surface area like Haskell. So Hell gets that for
free. Use ormolu the standard Haskell formatter.</p>
<h2 id="weaknesses">Weaknesses</h2>
<p>It has no editor support.<a href="#fn3" class="footnote-ref"
id="fnref3" role="doc-noteref"><sup>3</sup></a> I don’t plan on writing
editor support for it. That’s a very large undertaking; larger than
writing the language itself, I expect. So this aspect of the tool might
remain rubbish.</p>
<p>The error messages aren’t great. They’re okay, but they’re a bit
barebones. The type errors might point out a location that isn’t
obvious. This can be improved and I do want to improve it over time. See
the discussion on GitHub here: <a
href="https://github.com/chrisdone/hell/discussions/75">Reproduction of
a bad type error message</a></p>
<h2 id="future-work">Future work</h2>
<p>For the year 2025, I will probably work on these over the course of
the year:</p>
<ul>
<li>Better error messages.</li>
<li>Move from haskell-src-exts (a Haskell parser) to GHC’s own parser,
to reduce any possible deviations from the norm, and to get recent
syntactic goodies. This is a big job, but I’ve got the whole year.</li>
<li>Move to an efficient unifier for the inference pipeline.</li>
<li>Probably a steady but decreasing pace of adding library
functions.</li>
</ul>
<p>Otherwise, I think my plans are more orientated around using it to
write automation, rather than adding any new features.</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>AKA shallow embedding: The object
language reuses as many features of the meta language as possible. Many
aspects are delegated to the meta language.<a href="#fnref1"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p>Not much. There are a few library
functions that differ and the type-system is dumber.<a href="#fnref2"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn3" role="doc-endnote"><p>Well, it has an Emacs module I wrote
for myself. But nothing shared for other people to use.<a href="#fnref3"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2025-01-12 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sun, 12 Jan 2025 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Adding sum types (variants) to Hell]]></title><link>https://chrisdone.com/posts/variants</link><guid>https://chrisdone.com/posts/variants</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Adding sum types (variants) to Hell</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Adding sum types (variants) to Hell</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p><a href="https://chrisdone.github.io/hell/">Hell</a> is my little
shell scripting language that’s a thin layer over Haskell’s own standard
library and runtime. This post is for people that like language
implementation details. It has a simply typed system, without polytypes
(no <code>forall</code>).</p>
<p>It has classic Haskell 98-ish records, this is a valid Hell
program:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Person</span> <span class="ot">=</span> <span class="dt">Person</span> {<span class="ot"> age ::</span> <span class="dt">Int</span>,<span class="ot"> name ::</span> <span class="dt">Text</span> }</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>  Text.putStrLn <span class="op">$</span> Record.get <span class="op">@</span><span class="st">&quot;name&quot;</span> Main.person</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>  Text.putStrLn <span class="op">$</span> Record.get <span class="op">@</span><span class="st">&quot;name&quot;</span> <span class="op">$</span> Record.set <span class="op">@</span><span class="st">&quot;name&quot;</span> <span class="st">&quot;Mary&quot;</span> Main.person</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>  Text.putStrLn <span class="op">$</span> Record.get <span class="op">@</span><span class="st">&quot;name&quot;</span> <span class="op">$</span> Record.modify <span class="op">@</span><span class="st">&quot;name&quot;</span> Text.reverse Main.person</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>person <span class="ot">=</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a> <span class="dt">Main.Person</span> { name <span class="ot">=</span> <span class="st">&quot;Chris&quot;</span>, age <span class="ot">=</span> <span class="dv">23</span> }</span></code></pre></div>
<p>It’s built upon the following “classic” anonymous records definition
in Haskell:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">List</span> <span class="ot">=</span> <span class="dt">NilL</span> <span class="op">|</span> <span class="dt">ConsL</span> <span class="dt">Symbol</span> <span class="dt">Type</span> <span class="dt">List</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Record</span> (<span class="ot">xs ::</span> <span class="dt">List</span>) <span class="kw">where</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">NilR</span><span class="ot">  ::</span> <span class="dt">Record</span> <span class="dt">&#39;NilL</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">ConsR</span><span class="ot"> ::</span> <span class="kw">forall</span> k a xs<span class="op">.</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>    a <span class="ot">-&gt;</span> <span class="dt">Record</span> xs <span class="ot">-&gt;</span> <span class="dt">Record</span> (<span class="dt">ConsL</span> k a xs)</span></code></pre></div>
<p>The record is a linked list type that is indexed by a type which
itself is also a linked list, and in both cases we keep both a key
<code>k</code> and a value <code>a</code>.</p>
<p>This exact representation is used in Hell. It’s defined in the meta
language (Haskell) and used in the object language (Hell) directly and
is manipulated in a type-safe way; so accessor functions are all total
(they don’t have an “otherwise throw an error” case). I cover this in a
bit more detail in <a
href="https://chrisdone.com/posts/tour-of-hell/">Tour of Hell</a>.</p>
<p>This week I added a very rudimentary implementation of sum types, so
the following is a valid Hell program:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Value</span> <span class="ot">=</span> <span class="dt">Text</span> <span class="dt">Text</span> <span class="op">|</span> <span class="dt">Number</span> <span class="dt">Int</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">let</span> printIt <span class="ot">=</span> \x <span class="ot">-&gt;</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>        Text.putStrLn <span class="kw">case</span> x <span class="kw">of</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>          <span class="dt">Number</span> i <span class="ot">-&gt;</span> <span class="dt">Show</span><span class="op">.</span><span class="fu">show</span> i</span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>          <span class="dt">Text</span> t <span class="ot">-&gt;</span> t</span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>  printIt <span class="op">$</span> <span class="dt">Main.Number</span> <span class="dv">123</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>  printIt <span class="op">$</span> <span class="dt">Main.Text</span> <span class="st">&quot;abc&quot;</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Monad</span><span class="op">.</span><span class="fu">mapM_</span> printIt [<span class="dt">Main.Number</span> <span class="dv">123</span>,<span class="dt">Main.Text</span> <span class="st">&quot;abc&quot;</span>]</span></code></pre></div>
<p>The runtime representation of a constructor is shaped like a
combination of <code>Either</code> and <code>Record</code>:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Variant</span> (<span class="ot">xs ::</span> <span class="dt">List</span>) <span class="kw">where</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">LeftV</span><span class="ot"> ::</span> <span class="kw">forall</span> k a xs<span class="op">.</span> a <span class="ot">-&gt;</span> <span class="dt">Variant</span> (<span class="dt">ConsL</span> k a xs)</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">RightV</span><span class="ot"> ::</span> <span class="kw">forall</span> k a xs k&#39;&#39; a&#39;&#39;<span class="op">.</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Variant</span> (<span class="dt">ConsL</span> k&#39;&#39; a&#39;&#39; xs) <span class="ot">-&gt;</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Variant</span> (<span class="dt">ConsL</span> k a (<span class="dt">ConsL</span> k&#39;&#39; a&#39;&#39; xs))</span></code></pre></div>
<p>The trick here is to note that the index of kind <code>List</code> is
only ever <code>ConsL ..</code> meaning it cannot be ever
<code>NilL</code> (empty).</p>
<p>The challenging question in defining a case analysis on this type is
how to make it total, and not require an “or else throw” case. I went
with a simple accessor data structure that looks like a case:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Accessor</span> (<span class="ot">xs ::</span> <span class="dt">List</span>) r <span class="kw">where</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">NilA</span><span class="ot">  ::</span> <span class="dt">Accessor</span> <span class="dt">&#39;NilL</span> r</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">ConsA</span><span class="ot"> ::</span> <span class="kw">forall</span> k a r xs<span class="op">.</span> (a <span class="ot">-&gt;</span> r) <span class="ot">-&gt;</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Accessor</span> xs r <span class="ot">-&gt;</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Accessor</span> (<span class="dt">ConsL</span> k a xs) r</span></code></pre></div>
<p>It’s basically the same as <code>Record</code> except that every
field is <code>(a -&gt; r)</code> instead of just <code>a</code>,
meaning we have a record of functions.</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="ot">runAccessor ::</span> <span class="dt">Variant</span> xs <span class="ot">-&gt;</span> <span class="dt">Accessor</span> xs r <span class="ot">-&gt;</span> r</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>runAccessor (<span class="dt">LeftV</span> a) (<span class="dt">ConsA</span> f _) <span class="ot">=</span> f a</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>runAccessor (<span class="dt">RightV</span> xs) (<span class="dt">ConsA</span> _ ys) <span class="ot">=</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>  runAccessor xs ys</span></code></pre></div>
<p>This function is total and GHC is happy that it is exhaustive.</p>
<p>From here, Hell’s runtime didn’t need to be touched. The desugarer
simply replaces</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Value</span> <span class="ot">=</span> <span class="dt">Number</span> <span class="dt">Int</span> <span class="op">|</span> <span class="dt">Text</span> <span class="dt">Text</span></span></code></pre></div>
<p>with something like:</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>_Number <span class="ot">=</span> Variant.left <span class="op">@</span><span class="st">&quot;Number&quot;</span> x)</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>_Text <span class="ot">=</span> Variant.right (Variant.left <span class="op">@</span><span class="st">&quot;Text&quot;</span> x))</span></code></pre></div>
<p>(I sort the constructors alphabetically for a canonical
ordering.)</p>
<p>And replaces</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">case</span> <span class="op">..</span> x <span class="kw">of</span> <span class="dt">Number</span> i <span class="ot">-&gt;</span> <span class="dt">Show</span><span class="op">.</span><span class="fu">show</span> i; <span class="dt">Text</span> t <span class="ot">-&gt;</span> t</span></code></pre></div>
<p>with</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>Variant.run</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>  x</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>  <span class="op">$</span> Variant.cons <span class="op">@</span><span class="st">&quot;Main.Number&quot;</span> (\i <span class="ot">-&gt;</span> <span class="dt">Show</span><span class="op">.</span><span class="fu">show</span> i) <span class="op">$</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>     Variant.cons <span class="op">@</span><span class="st">&quot;Main.Text&quot;</span> (\t <span class="ot">-&gt;</span> t) <span class="op">$</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>       Variant.nil</span></code></pre></div>
<p>I thought this was pretty neat, because it’s very simple and very
clean, and total!</p>
<p>(To be entirely precise, Hell wraps both records and variants defined
with <code>data Foo</code> with a <code>Tagged "Foo"</code> to keep some
semblance of nominal typing. In case someone reads the code and thinks
the tagged part is important.)</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2024-11-23 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sat, 23 Nov 2024 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[A modest critique of Htmx]]></title><link>https://chrisdone.com/posts/htmx-critique</link><guid>https://chrisdone.com/posts/htmx-critique</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>A modest critique of Htmx</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>A modest critique of Htmx</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>At work, we really like the basic simple idea of Htmx. Based on using
Htmx in a non-trivial user interface, across a team, we’ve found that
the following cases are actually not simple and are quite
complicated.</p>
<h2
id="inheritance-of-htmx-properties-is-a-definite-mistake">Inheritance of
Htmx properties is a definite mistake</h2>
<p>Across pieces of code, it’s very surprising and it’s implicit. Like
in CSS, inheritance is a cheap hack but you get what you pay for.</p>
<p>It contradicts <a
href="https://htmx.org/essays/locality-of-behaviour/">the author’s
reasonable argument of locality of behaviour.</a> It’s not local, it
comes from all the way up there or some other module. Pretty much
dynamic binding.</p>
<p>Default inheritance differs across various properties
(e.g. <code>hx-delete</code> is not inherited, but
<code>hx-confirm</code> and <code>hx-ext</code> are). So you have to
remember these exceptions and you end up just being explicit about
everything, which means inheritance is pointless.</p>
<h2
id="most-interesting-web-apps-cannot-replace-wholesale-a-dom-element">Most
interesting web apps cannot replace wholesale a DOM element</h2>
<p>Because DOM elements almost always have browser-local state, such as
the open/closed state of a <code>&lt;details&gt;</code> element, the
input of an <code>&lt;input&gt;</code> element, the open/close state of
a dropdown element (which, note, is not encoded by an attribute of the
element when you click it). All of this state is lost if you replace
outerHTML directly with the naive happy path of Htmx.</p>
<p>Even <a
href="https://v1.htmx.org/extensions/morphdom-swap/">morphdom</a>
overwrites some things you’d expect it not to, so we had to patch it to
avoid messing with input elements, and details elements.</p>
<h2 id="storing-state-in-the-dom-element-itself-is-a-bad-idea">Storing
state in the DOM element itself is a bad idea</h2>
<p><a href="https://v1.htmx.org/extensions/morphdom-swap/">Morphdom</a>
is intended to correct the pains of the previous heading, but we
discovered that the way that Htmx works <em>assumes</em> it’s based on
replacing elements wholesale: it stores the request queue for the
element on the DOM element itself. When you kick off a request, either
from this element or from another that points to it, you have a request
queue. Some bad failure modes are avoided by wholesale-replacing the DOM
element, as the queue is reset. But with morphdom, the queue is retained
because the element is retained. You’re now in a sort of <a
href="https://en.wikipedia.org/wiki/Undefined_behavior">undefined
behavior land</a>, where the designs of Htmx are violated.</p>
<h2 id="the-default-queuing-mode-is-bonkers">The default queuing mode is
bonkers</h2>
<p>By default, Htmx will cancel requests that are in-flight if you
trigger another request on the same queue (element). That’s the default
strategy. We discovered this afterwards. It’s highly unintuitive, it
meant we were losing work.</p>
<h2 id="event-triggers-are-non-local">Event triggers are non-local</h2>
<p>Event triggers often help to make things happen, but they’re a
non-local effect, and suffer from similar issues as property
inheritance. A bit of DSL work in the server-side language can help with
this, but it feels like old-school JavaScript callback-based programming
to some extent; where you “subscribe” to an event happening and do
something.</p>
<h2 id="component-state-cannot-be-maintained-very-well">Component state
cannot be maintained very well</h2>
<p>A broader problem, similar to the DOM element state issue, is that
your own components have their own state. E.g. if you want a page that
consists of three sections that have their own state that the server
needs (e.g. which page of a set of results) and state that some
e.g. React or WebComponents need, then you have a problem of
synchronising state between a parent component and the child
component.</p>
<p>Htmx does not provide a good story for this. We have some ideas, but
they all have big caveats: use query parameters, use hidden form inputs,
use event triggers.</p>
<p>React and Halogen (see also <a
href="https://chrisdone.com/posts/halogen-is-better-than-react/">Halogen
is better than React at everything</a>) <em>do</em> have an answer to
this. In both cases, child components have their own state, and parents
can give them “props” which are pretty much “advice”, and they also have
their own internal state, and can choose to ignore/take precedence over
props. The props are typically sourced from the server or derived from
the server, and the state is usually some client-side state.</p>
<p>We often do need to use React for off-the-shelf components or
components that we have to use that are just provided as React. React
and Htmx do not interact nicely.</p>
<ul>
<li>We’ve done some unsatisfying work with WebComponents, but those
things have bizarre limitations that are surprising.</li>
<li>We’ve also made a bridge directly to React components that we use
from our server-side language, but in general Htmx and React fight for
control over the flow of state and management of DOM elements.</li>
<li>We’ve played with Alpine, which is nice, but it represents <em>yet
another</em> client-side-programming library and is therefore redundant
if React is already in your codebase.</li>
</ul>
<h2 id="the-up-sides">The up sides</h2>
<p>Our current thinking is that being able to use your server side
language is <strong>a huge obvious and uncontroversial win</strong>, no
one on the team would want to go back to writing all this business logic
in TypeScript:</p>
<ul>
<li>No serialisation from our DB types to frontend types is needed.
<ul>
<li>No data leaks, and no GraphQL needed.</li>
</ul></li>
<li>We can use our (in our opinion) more powerful abstraction facilities
of the server-side language.</li>
<li>We can use the form builder in our server side language; instead of
doing one frontend <em>and also</em> one backend implementation of the
same validations.</li>
</ul>
<p>But the above downsides are real.</p>
<h2 id="htmx-in-react">Htmx-in-React?</h2>
<p>An attractive future direction might be to re-implement Htmx in
React:</p>
<ul>
<li>The server sends a JSON blob that React converts into virtual DOM
components.</li>
<li>That would solve the component state problem.</li>
<li>It would mean we require no special bridge to use React
components.</li>
<li>It would let us use our React-connected web fetching library, and
carefully avoid the queuing choices made by Htmx.</li>
<li>It would solve the morphdom problems and browser DOM input elements
problem, too, which is pretty much a solved problem in React.</li>
</ul>
<p>In this way, we could drop the Htmx dependency but retain the
benefits of the idea. That is, given a budget to embark on such a big
piece of work.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2024-08-20 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Tue, 20 Aug 2024 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Naming sum types is often hard]]></title><link>https://chrisdone.com/posts/naming-is-hard</link><guid>https://chrisdone.com/posts/naming-is-hard</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Naming sum types is often hard</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Naming sum types is often hard</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>After doing quite a lot of software design in systems which encourage
use of enumeration types, I’ve noticed that there’s a common challenge
in naming both the type and the cases of the type. It usually exposes a
painful inadequacy in the English language and my grasp of it, assuming
any kind of aesthetic appreciation.</p>
<p>To take a trivial example, it’s only thanks to George Boole that we
have an elegant and concise name for the type of terms that consist of
either true or false. If we went for “truth” or “truthiness” we’d be
left unsatisfied because this name is biased towards one of the two
choices.</p>
<p>A more realistic example is the type of terms that consist of either
“local” or “remote.” If we call this “locality” then we are both biased
towards the local and overlap with a common, political understanding of
the word “locality.” “Remoteness” presents similar problems. The word
“location” doesn’t capture the modality. I’ll stop here because I’m just
upsetting myself.</p>
<p>Another example is the challenge of expressing whether something is
qualified or not qualified, in the sense of prefixed or suffixed with
some extra term. It’s really grating to have to express the thing in
terms of not-something. We prefer to say static versus dynamic, and not
static versus non-static or, above, local versus non-local. Ignoring
this, what do we call the type of these terms? “Qualified” is biased.
“Qualification” overlaps with a recognised achievement. We frown and
move on with something rubbish.</p>
<p>I probed an LLM to search for more obvious, satisfying answers to
these, in vain. But these are mere examples of a common experience. I
know that one of the two hard problems of computer science is naming
things, but this feels like a particularly bothersome flavour of it.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2024-07-09 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Tue, 09 Jul 2024 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Portals in Emacs]]></title><link>https://chrisdone.com/posts/portals</link><guid>https://chrisdone.com/posts/portals</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Portals in Emacs</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Portals in Emacs</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>I’ve been working on a new way to launch and manage processes in
Emacs in <a
href="https://github.com/chrisdone/emacs-config/blob/00e0d01b7f28cff4f16ac2ec5e98581f2969de84/packages/portal/portal.el">my
personal repo</a>. It’s an alternative to shells. A bit like a notebook.
It also partially serves the same need that Prodigy-mode does. The name
is evocative of that video game Portal from 2007.</p>
<p>It has a major mode, where <code>M-!</code> is rebound to Portal’s
way of running shell scripts. It inserts a nano-ID for the portal,
e.g. <code>portal_abc123456sdkjfal</code>, as text into the buffer at
the current point. It creates a corresponding directory under
<code>~/.portals/</code>. All stdout and stderr are redirected to files
under
<code>~/.portals/$portalid/{stdout,stderr,command,directory,env}</code>.</p>
<p>The purpose of this is that Emacs can lock up a bit when you run a
very long running process, or one that spews output very quickly.
Instead of storing it in a buffer or displaying all of it, Portal just
writes it all to a file and displays a little preview of it anywhere in
the buffer that the portal’s nano-ID is.</p>
<p>The preview is updated every couple seconds, it’s not instant. That
design is intentional, so that no process can ever really overwhelm
Emacs. It’s an extremely aggressive design. Even the line length in the
preview is limited to 80 columns.</p>
<p>Another motivation is simply UX-based, which is that I run a lot of
commands at work that spit out a bunch of useless output. Like
Terraform, Cabal, GHC, etc. Most of the output is not of interest, but
occasionally, one does want to read the output.</p>
<p>Example, below:</p>
<pre><code>portal_M2FjMjMyZWIxZjI4MTNmN
# (0) ls
# package.yaml
# readme.md
# scripts
# stack.yaml
# stack.yaml.lock

portal_ZmZhZThiMmFiNzQ1Y2E3N
# (run) stack build
# Preparing to download ghc-tinfo6-libc6-pre232-9.4.8 ...
# ghc-tinfo6-libc6-pre232-9.4.8: download has begun
# ghc-tinfo6-libc6-pre232-9.4.8:  256.00 KiB / 178.01 MiB (  0.14%) downloaded..
# ghc-tinfo6-libc6-pre232-9.4.8:  432.00 KiB / 178.01 MiB (  0.24%) downloaded..
# ghc-tinfo6-libc6-pre232-9.4.8:  736.00 KiB / 178.01 MiB (  0.40%) downloaded..</code></pre>
<p>The (0) indicates a successful exit. The command, stdout and stderr
have different colours. In the major mode, you put your cursor over them
and hit RET and it’ll pop open the file for you.</p>
<p>The other reason for storing all of this is that one can restart
Emacs and re-open a file containing portals and see what was ran, and
re-launch them if desired, with the same arguments, directory, etc.</p>
<p>I often use <code>M-x portal-edit</code> to tweak a command line,
which prompts in the mini-buffer with the existing text to edit. After
hitting RET, it restarts the portal for you.
<code>M-x portal-rerun</code> does what you’d expect.</p>
<p>All newly ran portals get a new nano-ID, so you can always go back
and find the outputs of a previously ran portal.</p>
<p>Emacs handles all the stdout and stderr, so it could in theory be
possible to pipe from one portal to another. One could even attach and
detach portals to/from one another, or edit arguments and restart, while
some of the processes are still running. But I haven’t explored this
because it’s more of a side-effect of my design than an intentional part
of it.</p>
<p>It also works perfectly with envrc mode, which is how Emacs
integrates with direnv.</p>
<p><code>C-c C-c</code> on a portal will interrupt the process, as
expected.</p>
<p>I’ve been using this for a few weeks and frankly I’m surprised how
well it works and fits my workflow. At work I have a foo.portals buffer
which has 30 portals in it. Of those, 3 are presently running, the rest
are things I can scroll through and re-run when I feel like it. I save
the file, so I can always restart Emacs and lose nothing.</p>
<p>I’m not interested in maintaining it as a “package.” But in the
spirit of Emacs, I am interested in sharing the code, so that others can
rip, riff and remix! Hope someone found this fun!</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2024-06-17 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Mon, 17 Jun 2024 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[All my projects (2008-2023)]]></title><link>https://chrisdone.com/posts/projects</link><guid>https://chrisdone.com/posts/projects</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>All my projects (2008-2023)</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>All my projects (2008-2023)</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>It might be a “getting old[-er]” thing, but I’ve recently started
feeling like documenting the complete set of software projects I’ve
worked on that I remember. Not as a CV (an advertisement of paid work),
but a comprehensive list of <em>everything</em>.</p>
<p>I’m done for now for 2008-2023. I filled out all the headings of my
projects with blank bodies. I started with the old stuff and
continuously made updates a little bit per day. After a month I was
done. At somepoint I was saying “oh for god sake, there’s still more
left”, which, if I may boast a little, indicates I did a lot of things
over the years.</p>
<p>Some of these projects are trivial, frivolous, very dubious, and some
of them are genuinely interesting, novel, or high quality. But it’s all
me.</p>
<!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-refresh-toc -->
<p><strong>Table of Contents</strong></p>
<ul>
<li><a href="#2023">2023</a>
<ul>
<li><a href="#copy-paste-sync">copy-paste-sync</a></li>
<li><a href="#hell">hell</a></li>
</ul></li>
<li><a href="#2022">2022</a>
<ul>
<li><a href="#envy">envy</a></li>
</ul></li>
<li><a href="#2021">2021</a>
<ul>
<li><a href="#proclog">proclog</a></li>
<li><a href="#lexx">lexx</a></li>
<li><a href="#hag">hag</a></li>
</ul></li>
<li><a href="#2020">2020</a>
<ul>
<li><a href="#inflex">inflex</a></li>
</ul></li>
<li><a href="#2019">2019</a>
<ul>
<li><a href="#novella">novella</a></li>
<li><a href="#streaming-parsers">streaming-parsers</a></li>
<li><a href="#forge">forge</a></li>
<li><a href="#env-args">env-args</a></li>
<li><a href="#dynamic">dynamic</a></li>
<li><a href="#webshow">webshow</a></li>
</ul></li>
<li><a href="#2018">2018</a>
<ul>
<li><a href="#lpaste">lpaste</a></li>
<li><a href="#odbc">odbc</a></li>
<li><a href="#hex-server">hex-server</a></li>
<li><a href="#sdl2-sprite">sdl2-sprite</a></li>
<li><a href="#caseof">caseof</a></li>
<li><a href="#rocksdb-haskell-ng">rocksdb-haskell-ng</a></li>
<li><a href="#phase">phase</a></li>
<li><a href="#audit">audit</a></li>
<li><a href="#codeparty">codeparty</a></li>
<li><a href="#duta">duta</a></li>
<li><a href="#prana">prana</a></li>
<li><a href="#intero">intero</a></li>
<li><a href="#cron-daemon">cron-daemon</a></li>
</ul></li>
<li><a href="#2017">2017</a>
<ul>
<li><a href="#xeno">xeno</a></li>
<li><a href="#profile-query">profile-query</a></li>
<li><a href="#snappy">snappy</a></li>
<li><a href="#liquid-post">liquid-post</a></li>
<li><a href="#tdiff">tdiff</a></li>
<li><a href="#vado-1">vado</a></li>
<li><a href="#jl">jl</a></li>
<li><a href="#duet">duet</a></li>
</ul></li>
<li><a href="#2016">2016</a>
<ul>
<li><a href="#purify">purify</a></li>
<li><a href="#labels">labels</a></li>
<li><a href="#org-focus">org-focus</a></li>
</ul></li>
<li><a href="#2015">2015</a>
<ul>
<li><a href="#descriptive">descriptive</a></li>
<li><a href="#stack">stack</a></li>
<li><a href="#path">path</a></li>
<li><a href="#xinput-conduit">xinput-conduit</a></li>
<li><a href="#conditions">conditions</a></li>
<li><a href="#haskell-trace">haskell-trace</a></li>
</ul></li>
<li><a href="#2014">2014</a>
<ul>
<li><a href="#clockin">clockin</a></li>
<li><a href="#present">present</a></li>
<li><a href="#ace">ace</a></li>
<li><a href="#hl">hl</a></li>
<li><a href="#formatting">formatting</a></li>
<li><a href="#hindent">hindent</a></li>
<li><a href="#foreign-store">foreign-store</a></li>
<li><a href="#shell-conduit">shell-conduit</a></li>
<li><a href="#lucid">lucid</a></li>
<li><a href="#gmail">gmail</a></li>
<li><a href="#osdkeys">osdkeys</a></li>
<li><a href="#ghc-server">ghc-server</a></li>
<li><a href="#ats-examples">ats-examples</a></li>
<li><a href="#carvo">carvo</a></li>
</ul></li>
<li><a href="#2013">2013</a>
<ul>
<li><a href="#z">z</a></li>
<li><a href="#ini">ini</a></li>
<li><a href="#pure-io">pure-io</a></li>
<li><a href="#god-mode">god-mode</a></li>
<li><a href="#structured-haskell-mode">structured-haskell-mode</a></li>
<li><a href="#haskellnews">haskellnews</a></li>
<li><a href="#ircbrowse">ircbrowse</a></li>
<li><a href="#snap-app">snap-app</a></li>
<li><a href="#cabal-sign">cabal-sign</a></li>
</ul></li>
<li><a href="#2012">2012</a>
<ul>
<li><a href="#sourcemap">sourcemap</a></li>
<li><a href="#fay">fay</a></li>
<li><a href="#scrobble">scrobble</a></li>
<li><a href="#bdo">bdo</a></li>
</ul></li>
<li><a href="#2011">2011</a>
<ul>
<li><a href="#numbergeddon">numbergeddon</a></li>
<li><a href="#pdfinfo">pdfinfo</a></li>
<li><a href="#chrisdone-xmonad">chrisdone-xmonad</a></li>
<li><a href="#flo">flo</a></li>
<li><a href="#freenect">freenect</a></li>
<li><a href="#hulk">hulk</a></li>
<li><a href="#ji">ji</a></li>
<li><a href="#pgsql-simple">pgsql-simple</a></li>
<li><a href="#css">css</a></li>
<li><a href="#url-generic">url-generic</a></li>
<li><a href="#hog">hog</a></li>
</ul></li>
<li><a href="#2010">2010</a>
<ul>
<li><a href="#tryhaskell">tryhaskell</a></li>
<li><a href="#jquery-console">jquery-console</a></li>
<li><a href="#lisk">lisk</a></li>
</ul></li>
<li><a href="#2009">2009</a>
<ul>
<li><a href="#asp-mode">asp-mode</a></li>
</ul></li>
<li><a href="#2008">2008</a>
<ul>
<li><a href="#kibro">kibro</a></li>
<li><a href="#lojbot">lojbot</a></li>
</ul></li>
<li><a href="#2006">2006</a>
<ul>
<li><a href="#slsksoulski">slsk/soulski</a></li>
<li><a href="#wdn">wdn</a></li>
</ul></li>
</ul>
<!-- markdown-toc end -->
<h1 id="section">2023</h1>
<h2 id="copy-paste-sync">copy-paste-sync</h2>
<p>I wrote this trivial tool called <a
href="https://github.com/chrisdone-archive/copy-paste-sync">copy-paste-sync</a>
that can copy/paste between systems by always keeping the clipboard in
sync. It basically just watches the clipboard for changes and then POSTs
the content to interested parties. At work I use a MacBook, but I also
have my Linux laptop next to it, so being able to copy/paste between the
two is handy.</p>
<h2 id="hell">hell</h2>
<p><a href="https://github.com/chrisdone/hell">Hell</a> is a shell
scripting language that is a tiny dialect of Haskell that I wrote for my
own shell scripting purposes. Full blog post about it <a
href="https://chrisdone.com/posts/hell/">here.</a></p>
<h1 id="section-1">2022</h1>
<h2 id="envy">envy</h2>
<p>I found myself using tools that want to control my shell environment
at work in order to run commands properly. This makes it annoying to
simply run a command from Emacs. So I wrote a mini tool called <a
href="https://github.com/chrisdone-archive/envy">envy</a> that simply
saves the environment generated by such a tooling setup, and then
execute any command with the same environment later.</p>
<h1 id="section-2">2021</h1>
<h2 id="proclog">proclog</h2>
<p>While consulting on a project that ran executables deeply within it,
I wrote <a
href="https://github.com/chrisdone-archive/proclog">proclog</a> as a
kind of ‘smarter tee’. I haven’t used this for a while and it isn’t
maintained anymore, but it was handy in the moment.</p>
<h2 id="lexx">lexx</h2>
<p>I wrote a project called <a
href="https://github.com/chrisdone-archive/lexx">lexx</a>, which lexes
Haskell code, specifically <code>Show</code> instances, but it can
handle fairly unstructured input, and still pretty print it with colours
nicely. It’s good for dev logs or general pretty printers.</p>
<h2 id="hag">hag</h2>
<p>I fiddled about with a project called <a
href="https://github.com/chrisdone-archive/hag">hag</a>, “Haskell ag”,
which would let one “grep” Haskell files for identifiers, and exclude
strings, comments, etc. by lexing them properly. I haven’t used this for
a while, it’s currently in the freezer.</p>
<h1 id="section-3">2020</h1>
<h2 id="inflex">inflex</h2>
<p>This was my dream project that I planned on being The Big One for my
30s. It involves all my skills: web, services, parsers, type checkers,
interpreters, UI, etc. I had a business, a registered trademark, lawyers
draft up Ts&amp;Cs and a privacy policy, accountant, Stripe account,
etc. It was going to be an online spreadsheet competitor. <a
href="https://chrisdone.com/posts/inflex/">Inflex</a> was going to be a
big hit.</p>
<p>I had a kid and then it took a back seat, I couldn’t financially
justify paying an accountant and for all the services when I only had an
hour a week to dabble in it. So I packed it in.</p>
<p>However, it has some of my best work. The compiler pipeline is
beautiful. Some of the implementation is wonderful. The design
trade-offs are brilliant and I researched everything over 2 years. The
<a href="https://github.com/chrisdone-archive/inflex">archive repo is
here</a>.</p>
<!-- ## early -->
<h1 id="section-4">2019</h1>
<h2 id="novella">novella</h2>
<p>For some bizarre reason, I thought it would be a good idea to make a
structured editor in the terminal called <a
href="https://github.com/chrisdone-archive/novella">novella</a>: the big
idea was to define a simple grammar for any language and get a
structured editor out of it, like this:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">grammar ::</span> <span class="dt">Grammar</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>grammar <span class="ot">=</span> <span class="op">$</span>(checkGrammar <span class="op">$</span> runDefine <span class="op">$</span> mdo</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- General expression</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>  expression       <span class="ot">&lt;-</span> rule <span class="st">&quot;Expression&quot;</span> (<span class="dt">ChoiceSchema</span> [variable, constructor, parentheses</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>                                                      ,tuple, let&#39;, application, string])</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>  application      <span class="ot">&lt;-</span> rule <span class="st">&quot;Application&quot;</span> (<span class="dt">CompositeSchema</span> [expression, expression])</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>  parentheses      <span class="ot">&lt;-</span> rule <span class="st">&quot;Parentheses&quot;</span> (<span class="dt">CompositeSchema</span> [openParenSchema, expression, closeParenSchema])</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Tuple</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>  tuple            <span class="ot">&lt;-</span> rule <span class="st">&quot;Tuple&quot;</span> (<span class="dt">CompositeSchema</span> [openParenSchema, tupleElements, closeParenSchema])</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>  tupleElements    <span class="ot">&lt;-</span> rule <span class="st">&quot;Tuple elements&quot;</span> (<span class="dt">ListSchema</span> expression <span class="st">&quot;,&quot;</span>)</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Identifiers</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>  variable         <span class="ot">&lt;-</span> rule <span class="st">&quot;Variable&quot;</span> (<span class="dt">IdentifierSchema</span> <span class="st">&quot;Variable&quot;</span>)</span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>  constructor      <span class="ot">&lt;-</span> rule <span class="st">&quot;Constructor&quot;</span> (<span class="dt">IdentifierSchema</span> <span class="st">&quot;Constructor&quot;</span>)</span></code></pre></div>
<h2 id="streaming-parsers">streaming-parsers</h2>
<p>I wrote, along with Michael Snoyman, some streaming JSON/YAML
parsers, in a package I called <a
href="https://github.com/chrisdone-archive/streaming-parsers">streaming-parsers</a>,
with the express intent to avoid security issues implied by packages
like <code>aeson</code> which consume the whole input given by the user.
This package never got used, but I did end up using
<code>reparsec</code> elsewhere, which was like a parsec that streams
like attoparsec, but works on any token rather than Text/ByteString.
Arguably megaparsec fits that niche these days, although I find
megaparsec kind of awkward and I can never remember how to use it.</p>
<h2 id="forge">forge</h2>
<p>I wrote <a
href="https://github.com/chrisdone-archive/forge">forge</a> as my answer
to modernizing formlets,<a href="#fn1" class="footnote-ref" id="fnref1"
role="doc-noteref"><sup>1</sup></a> after the world forgot about
multi-page web apps and switched to frontend/backend stratification.</p>
<p>However, it introduces a few novel ideas:</p>
<ul>
<li>Static checking of the uniqueness of names within a form</li>
<li>Errors can go both up <em>and</em> down in the form, meaning you can
“send” a validation error from above down to the input that caused
it</li>
<li>Selective-like behavior</li>
<li>Typed handling of optional vs required fields, which in other
libraries is a bit wishy-washy</li>
</ul>
<h2 id="env-args">env-args</h2>
<p>A simple tool called <a
href="https://github.com/chrisdone-archive/env-args">env-args</a> that
would convert environment variables to program arguments. With this, it
became trivial to either pass –foo arguments or PROGRAM_FOO variables.
Used for a client.</p>
<h2 id="dynamic">dynamic</h2>
<p>Partly as a joke, partly serious, I made a package called <a
href="https://github.com/chrisdone-archive/dynamic">dynamic</a> which
gives you dynamic types in Haskell. It makes it trivial to explore
unknown data in Haskell. I’ve never used it, but in principal it is
interesting.</p>
<h2 id="webshow">webshow</h2>
<p>I made a simple tool to generate a hierchical data structure browser
for Haskell <code>Show</code> output (similar to <a
href="#present">present</a>), and called it <a
href="https://github.com/chrisdone-archive/webshow">webshow</a>. I have
occasionallly resurrected this, when I need to explore really hairy
Haskell data structures.</p>
<h1 id="section-5">2018</h1>
<h2 id="lpaste">lpaste</h2>
<p>Back before GitHub’s gist took over, I wrote a service called <a
href="https://github.com/chrisdone-archive/lambda-paste">lpaste</a>
which sat at lpaste.net, and superceded hpaste.org (Haskell paste), for
pasting code samples. It was mostly IRC-driven. It actually featured
some useful features, where e.g. pasting a revision would notify users
on IRC in a given channel. That facilitated a lot of discussion about a
given piece of code, with people able to make suggestions and
improvements.</p>
<p>Spam became a large problem, and after I stopped using IRC I didn’t
feel like continuing to run it.</p>
<h2 id="odbc">odbc</h2>
<p>For a client, I needed to interact with SQL Server, but it was clear
that the libraries out there were all quite badly put together. So I
took Microsoft’s own now-native Linux driver and wrote a from-scratch
Haskell library to talk to it, <a
href="https://github.com/chrisdone-archive/odbc">here</a>. This one is
still maintained and used as far as I’m aware, but a few companies. I
put special care and attention into stability and performance, and I
think did a good job on that.</p>
<h2 id="hex-server">hex-server</h2>
<p>I can’t explain some of the motivations for my projects. I wrote <a
href="https://github.com/chrisdone-archive/hex-server">hex-server</a>
which was a ground-up implementation of Xorg-server in Haskell. I have
no idea why. Curiosity, I guess.</p>
<h2 id="sdl2-sprite">sdl2-sprite</h2>
<p>I was fiddling about with sdl2 at this time. <a
href="https://github.com/chrisdone-archive/sdl2-sprite">sdl2-sprite</a>
just repeats a sprite for you (see the README gif). I think there are
other tools around for this, but I found this one just did exactly what
I wanted while making a sprite in InkScape.</p>
<h2 id="caseof">caseof</h2>
<p>The <a href="https://github.com/chrisdone-archive/caseof">caseof</a>
package is just a proof of concept to test whether I could avoid lens
and get what I wanted: trivially ask whether a value is of a particular
constructor and if so, return a <code>Maybe</code> of the slots. Answer
is: yes, you can. Does anyone use it? No, lens is too popular.</p>
<h2 id="rocksdb-haskell-ng">rocksdb-haskell-ng</h2>
<p><a
href="https://github.com/chrisdone-archive/rocksdb-haskell-ng">rocksdb-haskell-ng</a>
was needed for some cryptocurrency client, who were inadvisedly using
rocksdb, in Haskell, and the existing package was, well, neither stable
or efficient. I rewrote it from scratch, with stability and performance
in mind. I’m quite proud of the work I did on this, it was good
work.</p>
<h2 id="phase">phase</h2>
<p>Another case of having too much time on my hands perhaps. <a
href="https://github.com/chrisdone-archive/phase">phase</a> basically
provides a frontend to Emacs in your browser. It’s not as native as the
GTK or terminal frontends, but the latency wasn’t too bad. I’m not sure
I’ll ever pick this up again. But it was surprisingly usable.</p>
<h2 id="audit">audit</h2>
<p>I had to audit a number of projects at FP Complete. This <a
href="https://github.com/chrisdone-archive/audit">emacs mode</a> helped
me interactively mark any selection of any file as viewed, accepted or
problematic, with comments. I would still use this today if I need to
audit or heavily review a project.</p>
<h2 id="codeparty">codeparty</h2>
<p>When teaching Haskell to companies at FP Complete, it was handy to
have everyone type out the answer to an exercise live on screen. For
that I made <a
href="https://github.com/chrisdone-archive/codeparty">codeparty</a>,
which was a bit like a mass screen share, but more efficient, and
ensured everyone had the same editing experience. I would use this again
if I needed to teach Haskell again.</p>
<h2 id="duta">duta</h2>
<p>I wrote my own email server called <a
href="https://github.com/chrisdone-archive/duta">duta</a>, which was
about being able to self-host email. I actually ran it for years; it was
only because LetsEncrypt at the time was harder to use and required
upgrades and maintenance that I gave up on it, but for a while I was
reading my mail with my own Haskell-made email web and Emacs client.</p>
<h2 id="prana">prana</h2>
<p>I was really into the idea of being able to interpret Haskell within
Haskell, so I made a project called <a
href="https://github.com/chrisdone-archive/prana">prana</a> which would
compile GHC Haskell down to STG, convert that STG to an internal format,
and then interpret it. It turns out, there are quite a few “implicit”
things in STG that you just have to know, figure out or ask around
about. The GHC internals change far too often, so I gave up on this. But
I took a good crack at it.</p>
<h2 id="intero">intero</h2>
<p><a href="https://github.com/chrisdone-archive/intero">intero</a> was
my “complete” (<em>intero</em> is Italian for ‘whole’) Haskell IDE in
Emacs. I was given space at FP Complete to work on it as a product to
solve the whole Haskell tooling issue. It was actually a brilliant
project, and worked on almost everything, and rarely if ever broke.
There was a lot of Emacs Lisp, and a modicum of Haskell in a GHCi fork I
called <code>intero</code>.</p>
<p>Some of that Elisp still lives on in my Emacs config, but the project
itself I sunsetted some years ago after I was subjected to one final GHC
upgrade and could not bare to port my code over to yet another GHC API
API change. I just gave up.</p>
<p>But on the whole it was a great project and had 1k users at
least.</p>
<h2 id="cron-daemon">cron-daemon</h2>
<p>I wanted a handy way to have a ‘service’ run and re-run easily, which
I called <a
href="https://github.com/chrisdone-archive/cron-daemon">cron-daemon</a>.
This was my first tool that I statically built with musl. I haven’t used
this for a while, but I might use it in the future. It can be used in
combination with
<code>stack build --file-watch --exec 'cron-daemon ..'</code> to cause a
service to restart after recompiling.</p>
<h1 id="section-6">2017</h1>
<h2 id="xeno">xeno</h2>
<p>After seeing that Neil Mitchell had written a fast XML parser by
using C for the parsing, I was motivated to use it as a <a
href="https://chrisdone.com/posts/fast-haskell-c-parsing-xml/">demonstration
of writing fast parsers in Haskell.</a> The resulting demonstration
library, I called <a
href="https://github.com/chrisdone-archive/xeno">xeno</a>, but left it
for someone else to pick and maintain, which Marco Z took up. It was
100x faster than the other “fast” Haskell XML parser called Hexpat. It
was faster than the C one at SAX parsing, and 2x slower at allocating a
DOM, but this also predates the introduction of proper Word8, Word16,
etc. types in GHC.</p>
<h2 id="profile-query">profile-query</h2>
<p>I wrote a tool at FP Complete called <a
href="https://github.com/chrisdone-archive/profile-query">profile-query</a>
to parse GHC’s profiler output (.prof) and to provide aggregated
summaries of cost centres, with sorting by e.g. time or allocations.</p>
<p>It was a handy tool, but isn’t maintained today. I expect it would
still work, though.</p>
<h2 id="snappy">snappy</h2>
<p>A brief experiment called <a
href="https://github.com/chrisdone-archive/snappy">snappy</a> to try out
Reflex-like FRP with SVG. It’s not as easy as you think to do this, and
there are all sorts of gotchas. Where possible, don’t DIY FRP. It’s
hard.</p>
<h2 id="liquid-post">liquid-post</h2>
<p>I wrote a post about Liquid Haskell for FP Complete, but <a
href="https://github.com/chrisdone-archive/liquid-post">this repo</a>
shows all the examples and they are quite good, I think.</p>
<h2 id="tdiff">tdiff</h2>
<p>I still use this sometimes. <a
href="https://github.com/chrisdone-archive/tdiff">tdiff</a> just gives
you timing between lines of output from a process. This can be really
good for checking timings of other programs than your own.</p>
<h2 id="vado">vado</h2>
<p>In an exhibition of sorts, I made a 90s-style web browser called <a
href="https://github.com/chrisdone-archive/vado">vado</a> (“I go” in
Italian), which can show rich text documents and browse around. I think
it’s pretty cool that I was able to do this in a few hundred lines of
code, and it works/worked on Windows, macOS and Linux, too!</p>
<h2 id="jl">jl</h2>
<p>I like <code>jq</code> a bit, but I always found myself just wishing
I had a basic mini lambda calculus/Haskell. So I wrote a small
statically typed mini language called <a
href="https://github.com/chrisdone-archive/jl">jl</a>. I used it for a
while, but somehow I’ve managed to go years and years without needing to
do JSON munging in scripts or anything. So this project died due to lack
of use. I otherwise think the design and implementation are both
good.</p>
<h2 id="duet">duet</h2>
<p>I have no idea why I started working on this, but I wrote a <a
href="https://github.com/chrisdone-archive/duet">small Haskell
implementation</a> called Duet, which is helpful for teaching because it
has a substitution-based interpreter. It was based on Typing Haskell in
Haskell, which was refactored a bit, more types added, etc. It’s quite a
viable Haskell implementation. Great for teaching.</p>
<p>I never found other uses for it, because frankly I don’t fully
understand the type-checker, because I didn’t author it from scratch.
Future projects involved writing one from scratch, which I do
understand. See <a href="#inflex">Inflex</a> or <a
href="#hell">Hell</a>.</p>
<!-- ## xeno -->
<h1 id="section-7">2016</h1>
<h2 id="purify">purify</h2>
<p>I was doing more PureScript dev in 2016, so I made <a
href="https://github.com/chrisdone-archive/purify">purify</a>, which was
basically stackage+stack, but for PureScript. It was popular for a
while, but then the main PureScript package manager gained these
capabilities and it wasn’t necessary anymore. But it was a solid
project, I think.</p>
<h2 id="labels">labels</h2>
<p>As part of proving out whether Haskell could really be useful as a
data analysis language (answer: not really), I wrote <a
href="https://github.com/chrisdone-archive/labels">labels</a>, which is
an extensible records package, along with CSV, JSON capabilities. It
worked, actually, but nothing much came of it after that.</p>
<h2 id="org-focus">org-focus</h2>
<p>In an effort to track all my time on projects, I wrote <a
href="https://github.com/chrisdone-archive/org-focus">org-focus</a> for
Emacs. It was a bit like org-agenda, but included time spent, estimates,
and stuff that a consultant might need. I don’t track my time with such
fine-grain detail these days, so I stopped using it.</p>
<h1 id="section-8">2015</h1>
<h2 id="descriptive">descriptive</h2>
<p>I noticed that optparse-applicative, formlets, yaml/json parsing,
etc. were all a type of self-describing parser. Hence <a
href="https://github.com/chrisdone-archive/descriptive">descriptive</a>.
I think the task of generalizing all of these under one framework is
harder than I anticipated, despite the grand vision, and the project
died.</p>
<h2 id="stack">stack</h2>
<p>At FP Complete, clients wanted a tool that covered all their
use-cases, which typically involved multi-package projects and wanting
to avoid the cabal solver. Motivated by previous success with internal
tools,<a href="#fn2" class="footnote-ref" id="fnref2"
role="doc-noteref"><sup>2</sup></a> we decided to make a proper tool and
decided the name would be ‘stack’ (from stackage). I made <a
href="https://github.com/chrisdone-archive/stack/commit/cb95f21855e23c715a106bb484b307623529e323">the
first commit for Stack</a>. I worked on it for a year or two, alongside
many people at FP Complete like Michael Sloan, Manny Borsboom, Dan
Burton and Michael Snoyman, and I have used it ever since. Most everyone
else did the bulk of the work, I only kick started the basics (reading
cabal files, GHCi support, things like that).</p>
<p>The first version used Shake, but we discovered it was very hard to
reason about what it was doing. Michael rewrote the scheduler to not
need Shake, and did further work to basically make Stack a bit like Nix
and lock down all packages, package sets into with SHA256 hashes. I
wrote <a href="https://casa.stackage.org/">casa.stackage.org</a> to
store content-addressed blobs of package files for Stack to later
retrieve.</p>
<p>It went on to become the build tool of choice for Haskell projects
for some years. It’s only in recent years that cabal-install has caught
up with feature parity and the sentiment seems to be shifting back to
cabal-install. I still use stack because the ergonomics are more
designed for my workflow.</p>
<h2 id="path">path</h2>
<p>As part of my work on stack, we deal with filepaths a lot, so I wrote
the <a href="https://github.com/chrisdone-archive/path">path
package</a>, <a href="https://chrisdone.com/posts/path-package/">with a
blog post motivating it</a>. I was pretty happy with this package, it
solved a real need that initially a lot of people were sceptical of, but
colleagues told me it saved their asses a few times.</p>
<p>That package is still maintained to my knowledge.</p>
<h2 id="xinput-conduit">xinput-conduit</h2>
<p><a
href="https://github.com/chrisdone-archive/xinput-conduit">This</a>
package simply converts the <code>xinput</code> output (which yields all
keys pressed in Xorg), and provides them as a Haskell source conduit. I
was using it for keypress analysis back then. I still think it’s a nifty
trick.</p>
<h2 id="conditions">conditions</h2>
<p>Conditions are a Common Lisp idea. Unlike exceptions which unwind the
stack, they call a function which is bound in the dynamic scope, which
gives the option of providing a different value for the calling code to
use. There are whole workflows built around them in Lisp. You can be
reading from a bunch of files in a loop, encounter a problem, fix it,
and then continue running the program.</p>
<p>I was inspired to demonstrate that <a
href="https://github.com/chrisdone-archive/conditions">in Haskell.</a>
But it’s not as good as in Lisp, which embraces it fully.</p>
<h2 id="haskell-trace">haskell-trace</h2>
<p>I wrote <a
href="https://github.com/chrisdone-archive/haskell-trace">a small
tool</a> to add trace calls in one’s Haskell code. This is something
that Haskell sorely lacks, and I can’t see acquiring any time soon.</p>
<h1 id="section-9">2014</h1>
<h2 id="clockin">clockin</h2>
<p>I wrote <a
href="https://github.com/chrisdone-archive/clockin">clockin</a> as a
command-line app to be able to clockin and clockout of any task. I used
this for a while, maybe a year, before losing interest in clocking my
time so accurately.</p>
<h2 id="present">present</h2>
<p>After looking at CLIM (Common Lisp Interface Manager), I really liked
the idea of being able to <em>present</em> a value with multiple
interpretations. That’s what <a
href="https://github.com/chrisdone-archive/present">present</a> was
about. I used template-haskell to inspect any type and derive a
representation for it. Even <code>ByteString</code> had multiple views,
e.g. as a list of bytes, as UTF-8 text, hex, a pointer, etc.</p>
<p>I kind of ran myself into the ground with this when it came to higher
kinded types. I got stuck and lost interest. I would love to pick it up
again some day.</p>
<h2 id="ace">ace</h2>
<p>In the afterglow of growing bored of Lojban, but still enamoured by
formal human languages, I got into Attempto (Latin for ‘I dare’)
Controlled English. I ended up writing a parser package for it in
Haskell <a href="https://github.com/chrisdone-archive/ace">here</a>.
It’s surprisingly comprehensive, I wrote <a
href="https://chrisdone.com/posts/attempto-controlled-english/">a blog
post on it</a>. It even permits passing a record of parsers, permitting
the user to define their own vocabulary and syntax for terms.</p>
<p>When I wrote it, use of such things was questionable. Combine it with
a logic database and <em>poof</em>, magic understanding! In reality, not
quite. Arguably, the use for such a thing in today’s brave new world of
LLMs is even more questionable.</p>
<p>But I suppose there still lies a small place in my heart for a formal
language that is also readable by anyone who speaks English.</p>
<h2 id="hl">hl</h2>
<p>The Haskell web site has already been a bit crap. Today, it’s okay.
It’s been much worse. During that period of much-worseness, I wrote <a
href="https://github.com/chrisdone-archive/hl">hl</a>, an alternative
Haskell homepage, complete with <a
href="https://chrisdone.com/posts/haskell-lang/">reasoning</a>, which I
launched at haskell-lang.org as an alternative competing page, due to
making no progress at all for years in trying to get access to
haskell.org itself. Eventually, it did become the Haskell homepage due
to some diplomatic heroics. In that sense, I suppose the project was a
success. There was, as expected, lots of politics surrounding it, but
that’s always the case with home pages of community projects.</p>
<h2 id="formatting">formatting</h2>
<p>I thought that the <a
href="https://hackage.haskell.org/package/HoleyMonoid">HoleyMonoid</a>
package was very neat, and decided it would make a perfect type-safe
printf-like package. I called it <a
href="https://github.com/chrisdone-archive/formatting">formatting</a>,
after Common Lisp’s FORMAT.</p>
<p>Actually, it turned out that despite the neat trick, I really doing
like the position-dependent style of printf/FORMAT at all. I prefer just
writing <code>x &lt;&gt; " and " &lt;&gt; y</code> instead, or
<code>concat [x, "and", y]</code>. So the whole thing became an
experiment in novelty, but ultimately I lost interest and passed the
maintainership onto someone else.</p>
<h2 id="hindent">hindent</h2>
<p><a href="https://github.com/chrisdone-archive/hindent">hindent</a>
was my bold attempt to make a complete pretty printer for Haskell, so
that manual code formatting would be a thing of the past. This was quite
a substantial project and took a lot of work. <a
href="https://chrisdone.com/posts/hindent/">The blog post</a> explains
the motivations, but I just wanted to type less and get autoformatting.
I later went one step further and limited it to a single style (which is
what gofmt famously did), which I documented <a
href="https://chrisdone.com/posts/hindent-5/">here</a>. I even chose a
style that I didn’t like, but that was popular. The decision to enforce
just one style made a lot of people mad.</p>
<p>Years later, there was a remake project called Ormolu<a href="#fn3"
class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a>,
which also enforced one style. There was subsequently a fork called
Fourmolu, which permitted more style configuration.<a href="#fn4"
class="footnote-ref" id="fnref4" role="doc-noteref"><sup>4</sup></a></p>
<h2 id="foreign-store">foreign-store</h2>
<p>The <a
href="https://github.com/chrisdone-archive/foreign-store">foreign-store</a>
package is a simple bit of C code wrapped in a Haskell package that lets
you keep a reference to a Haskell object between GHCi reloads, which I
wrote <a href="https://chrisdone.com/posts/ghci-reload/">for the purpose
of hot reloading.</a> It’s actually still used to this day and
maintained by someone else. There are 12 direct dependencies of it on
Hackage, mostly various different ways of doing code reloading.<a
href="#fn5" class="footnote-ref" id="fnref5"
role="doc-noteref"><sup>5</sup></a> They’re all fancy wrappers around
this.</p>
<p>10 years after it had been published and not been touched for just as
long, someone found and fixed a segfaulting bug in the C code. Can you
believe it?</p>
<h2 id="shell-conduit">shell-conduit</h2>
<p>I’ve been wanted to write shell scripts since 2014. This attempt, <a
href="https://github.com/chrisdone-archive/shell-conduit">shell-conduit</a>,
was to get all available names in the <code>PATH</code>, available as
real Haskell identifiers to run. And then “scripts” would be regular
Haskell programs.</p>
<p>I’ve since changed my mind that this is a good idea, and see above
for the <a href="#hell">Hell</a> project.</p>
<h2 id="lucid">lucid</h2>
<p><a href="https://github.com/chrisdone/lucid">Lucid</a> is still
actively developed, and was motivated by have a uniformity of
combinators, like HTML handling in Common Lisp.</p>
<p>It’s also a proper monad transformer, which has a small theoretical
satisfaction to it.</p>
<p>It’s one of my projects that is using the <a
href="https://chrisdone.com/posts/ipp/">Immutable Publishing
Policy</a>.</p>
<h2 id="gmail">gmail</h2>
<p>When Google released a new mail app, that was a smaller version of
GMail, with an API, I rejoiced and <a
href="https://github.com/chrisdone-archive/gmail">made an Emacs mode for
it</a>. Google would later kill it, as they killed all things
eventually. One of many lessons learned about depending on any kind of
public software service.</p>
<h2 id="osdkeys">osdkeys</h2>
<p><a href="https://github.com/chrisdone-archive/osdkeys">A simple
tool</a> that would display keys pressed on the screen, for
screencasting.</p>
<h2 id="ghc-server">ghc-server</h2>
<p><a
href="https://github.com/chrisdone-archive/ghc-server">ghc-server</a>
was my attempt to make a language server before “language server” was a
meaningful term, inspired by SWANK for Common Lisp, that powers the
SLIME Emacs package. It had a good start, but I encountered a lot of
lockups and issues. Also, I couldn’t make GHC stop outputting things to
stdout. I found it really hard to bring the GHC API under control.
Eventually, I just gave up.</p>
<h2 id="ats-examples">ats-examples</h2>
<p>ATS is a fascinating C-like programming language with linear types
and proofs, it has linear memory management (track malloc/free’s), among
other features like unpacked data, and tail recursion, and macros. It
could have been Rust before Rust. But its author, Hongwei Xi, didn’t do
the best job of presenting it well. I made <a
href="https://github.com/chrisdone-archive/ats-examples">these
examples</a> based on reading the book.</p>
<h2 id="carvo">carvo</h2>
<p>Part of a “Maker Space” place, we wanted to make some visual
representation of poetry, so I made <a
href="https://chrisdone.com/toys/corvo/">this one</a> which “handwrites”
Poe’s <em>The Raven</em>.</p>
<h1 id="section-10">2013</h1>
<h2 id="z">z</h2>
<p>I wrote a post called <a href="/posts/z">z</a> and accompanying <a
href="https://github.com/chrisdone-archive/z">source</a> which
demonstrated an idea that a language could be built upon a macro system
which is based on indentation rather than delimiters like
<code>( )</code> or <code>[| .. |]</code>. I still think it’s a fun
idea, because it has unlimited extent. I might return to it one day.</p>
<h2 id="ini">ini</h2>
<p>Back before YAML took over, there wasn’t a winning configuration
format. XML had lost its lustre. So I wrote <a
href="https://github.com/chrisdone-archive/ini/">ini</a>, which parsed
the simple INI format.</p>
<p>Since, YAML is now de-facto standard (although TOML is floating
around), so I stopped using this.</p>
<h2 id="pure-io">pure-io</h2>
<p>A small project called <a
href="https://github.com/chrisdone-archive/pure-io">pure-io</a> that
provided a little IO monad that would run as a pure function. I used
this for tryhaskell.org.</p>
<h2 id="god-mode">god-mode</h2>
<p>After suffering from RSI for a while, I had decided with Emacs I’d
look at my typing with statistics. After a week or so of full day typing
every day, I found that I made a significant proportion of key chords in
succession. I evaluated vim modes and realised that they depart from
Emacs quite a bit or lacked a story for many modes. In the end I had the
thought to make the Ctrl implicitly on all the time, and this turned out
to be undeniably productive and practical in the form of <a
href="https://github.com/chrisdone-archive/god-mode">god-mode</a>.</p>
<p>I’m still using it to this day, although it has been folded into my
Emacs config.</p>
<h2 id="structured-haskell-mode">structured-haskell-mode</h2>
<p>In similar themes to god-mode, I made a structured editor for Emacs’s
haskell-mode that would essentially let one edit Haskell code like
paredit. That used a Haskell parser via haskell-src-exts, and produced a
set of s-expressions for Emacs to convert to a set of markers. The minor
mode was called <a
href="https://github.com/chrisdone-archive/structured-haskell-mode">structured-haskell-mode</a>.</p>
<h2 id="haskellnews">haskellnews</h2>
<p><a
href="https://github.com/chrisdone-archive/haskellnews">haskellnews</a>
was a simple web app to list all the sources of blogs, posts, tweets,
etc. about Haskell. I sort of lost interest in social Mead and therefore
stopped running it. But for a while I enjoyed using it.</p>
<h2 id="ircbrowse">ircbrowse</h2>
<p>I wrote <a
href="https://github.com/chrisdone-archive/ircbrowse">ircbrowse</a> at
ircbrowse.net to be a replacement to the much older ircbrowse.com.</p>
<p>ircbrowse.com was a great web site for browsing chat logs of various
IRC channels, it was also infamously slow as hell. So a fundamental
motivator was to make something that would be instant, and I succeeded
on that, much to my personal pride.</p>
<p>It could handle about 30 million lines of chat across a few channels
for about 10 years of logs. There were something in the order of 30k
lines of chat from the #haskell channel per month.</p>
<p>I stopped running it after I lost interest in IRC, but it was a very
satisfying project and I learned a lot about PostgreSQL’s performance
characteristics in the process.</p>
<h2 id="snap-app">snap-app</h2>
<p><a href="https://github.com/chrisdone-archive/snap-app">snap-app</a>
was my small library to wrap the Snap web framework (for Haskell), with
an MVC structure, so that there would be Model and Controller monads,
and some associated functions.</p>
<p>After that, Snap became irrelevant and Yesod remained the only real
web framework for a while.</p>
<h2 id="cabal-sign">cabal-sign</h2>
<p>There was an old discussion in Haskell about signed packages. So I
made a demo tool called <a
href="https://github.com/chrisdone-archive/cabal-sign">cabal-sign</a>
which, given a .tar.gz, would sign it, and then inject the signature
into the .tar.gz. It was never used by anyone, but it did contribute to
a discussion.</p>
<h1 id="section-11">2012</h1>
<h2 id="sourcemap">sourcemap</h2>
<p>For <a href="#fay">fay</a>, I thought it’d be good to include <a
href="https://github.com/chrisdone-archive/sourcemap">sourcemaps</a>, so
I wrote this package as a more or less line-by-line translation of the
reference implementation. The spec itself was very informal. It worked,
though, and performed fairly well.</p>
<h2 id="fay">fay</h2>
<p>I wrote a language called Fay, which was a Haskell without
type-classes that compiled to JavaScript, and used GHC’s type system for
the type-checking.</p>
<p>It ended up being quite popular, it garnered its own <a
href="https://github.com/faylang/">organisation</a>, and I had a
co-maintainer called Adam Bergmark, who was very nice and smart.<a
href="#fn6" class="footnote-ref" id="fnref6"
role="doc-noteref"><sup>6</sup></a></p>
<p>I was invited to and went to a conference in Lisbon to give a talk on
it.</p>
<p>FP Complete used it for their IDE which was a web based Haskell IDE,
which is pretty much how I got the job at FP Complete in 2013. A couple
years or so later, after the IDE project petered out, we stopped using
it. There were better options by then (PureScript, etc.).<a href="#fn7"
class="footnote-ref" id="fnref7" role="doc-noteref"><sup>7</sup></a></p>
<ul>
<li><a href="/posts/fay">Blog post</a></li>
</ul>
<h2 id="scrobble">scrobble</h2>
<p>Like many people, I used Last.fm/Audioscrobbler, and would ‘scrobble’
all my music listens to the service, and get back in response
recommendations. I wrote <a
href="https://github.com/chrisdone-archive/scrobble">a Haskell
library</a> to do it. It’s irrelevant these days, nobody scrobbles.</p>
<h2 id="bdo">bdo</h2>
<p><a href="https://github.com/chrisdone-archive/bdo">This Emacs
library</a> permits one to update .js/.css files in the browser live.
This predates many “modern” tools like Vite or whatever. I don’t use it
these days, because all web programming exists inside of a build system.
But there was a glorious period in which that wasn’t the case.</p>
<h1 id="section-12">2011</h1>
<h2 id="numbergeddon">numbergeddon</h2>
<p>I wrote a fun game called <a
href="https://chrisdone.com/toys/numbergeddon/">Numbergeddon</a>, on the
basis that one could rote learn arithmetic by typing it. I think I got
inspiration from games at the time that involved typing out words to
destroy ships, in order to practice touch-typing.</p>
<h2 id="pdfinfo">pdfinfo</h2>
<p>This <a
href="https://github.com/chrisdone-archive/pdfinfo">utility</a> package
just launches pdfinfo and parses the output. I needed it for work at the
time.</p>
<h2 id="chrisdone-xmonad">chrisdone-xmonad</h2>
<p>I was using xmonad in 2011, hence <a
href="https://github.com/chrisdone-archive/chrisdone-xmonad">my
config</a> of course was published on GitHub. Like your Emacs config,
it’s traditional to publish your XMonad. I don’t use tiling window
managers anymore. But XMonad is a good one.</p>
<h2 id="flo">flo</h2>
<p>I wrote a small tool that would let you annotate your source code and
project a flow diagram, called <a
href="https://github.com/chrisdone-archive/flo">flo</a>. This could
still be used today with relative ease, I think. It’s language-agnostic.
I never advertised it, though.</p>
<h2 id="freenect">freenect</h2>
<p>I bought a Kinect, which was Microsoft’s XBox
camera/infra-red-distance viewer hardware. There were C libs, so I wrote
Haskell bindings to it and called it <a
href="https://github.com/chrisdone-archive/freenect">freenect</a>. There
were some fun things I made with it.</p>
<h2 id="hulk">hulk</h2>
<p>I wrote an IRC server for use at work for us to chat on. We used it
for some years after we all left, until we eventually migrated to an app
called Wire (also written in Haskell).</p>
<p>This was my first proper experience using threading in Haskell and
working on a sockets server in Haskell. I would note that architecting
an IRC server in a nice way remains an unsolved problem in my head. In
any language.</p>
<ul>
<li><a href="https://github.com/chrisdone-archive/hulk">GitHub
archive</a></li>
<li><a href="/posts/hulk-haskell-irc-server">Blog post</a></li>
</ul>
<h2 id="ji">ji</h2>
<p>I wrote a library called <a href="/posts/ji-haskell-web/">Ji</a>,
which is a simple concept to write a web app in Haskell that sends
commands to a browser of what DOM changes to make and what events to
listen to.</p>
<p>It was taken over by Heinrich Apfelmus and renamed to <a
href="https://github.com/HeinrichApfelmus/threepenny-gui">threepenny-gui</a>,
after which he added many FRP-based things and has likely rewritten all
of it by this point.</p>
<h2 id="pgsql-simple">pgsql-simple</h2>
<p><a
href="https://github.com/chrisdone-archive/pgsql-simple">pgsql-simple</a>
was my naive, although fairly successful, attempt to talk to the
PostgreSQL protocol directly from Haskell, without any C library. It
worked, and some people used it at work. But it was slow, and not
featureful. And I wasn’t interested in maintaining it as a real, serious
project, with serious users. Still, it was quite fun.</p>
<h2 id="css">css</h2>
<p><a href="https://github.com/chrisdone-archive/css">css</a> is a
miniature DSL letting one write CSS in Haskell. Similar to SASS and
Tailwind. Nothing special, but I did use it on at least one app.</p>
<h2 id="url-generic">url-generic</h2>
<p>This is <a href="https://github.com/chrisdone-archive/url-generic">a
fully worked out package</a> that would, given a type that’s an instance
of <code>Data</code>, produce a parser/printer as a URL. No one ever
used it, including myself. But it was a nice exercise.</p>
<h2 id="hog">hog</h2>
<p>I wrote an IRC logger called <a
href="https://github.com/chrisdone-archive/hog">hog</a>, which I used
for years on my personal IRC server with friends. There isn’t much
special in here, but I used it.</p>
<h1 id="section-13">2010</h1>
<h2 id="tryhaskell">tryhaskell</h2>
<p><a href="https://tryhaskell.org/">tryhaskell.org</a></p>
<p>This was a big splash when I made it, it hit the top of some big
subreddits and Hacker News. It was inspired by tryruby.org, which was
made by _whytheluckystiff, the mysterious Rubyist who disappeared from
the community. It runs you through an interactive tutorial about Haskell
basics and checks your answers.</p>
<p>I’ve been meaning to rewrite this one day, but so far haven’t been
sufficiently inspired to do so.</p>
<p>It’s been running for 14 years, which is quite a long time.</p>
<h2 id="jquery-console">jquery-console</h2>
<p>Written for Try Haskell, this is <a
href="https://github.com/chrisdone-archive/jquery-console">was</a> dumb
terminal/console-like experience in the browser using JQuery. It still
works correctly to this day, on tablets, phones and computers. I stopped
maintaining it as a separate package years and years ago, but tryhaskell
still works fine.</p>
<h2 id="lisk">lisk</h2>
<p>I had enough hubris to think I would be able to write a Lisp syntax
on top of Haskell, and called it <a
href="/posts/lisk-lisp-haskell">Lisk</a>.</p>
<p>I was happy with Haskell, but bummed out by its syntax compared to
the beauty of Lisp. That hasn’t changed today in 2024.</p>
<ul>
<li><a href="https://github.com/chrisdone-archive/lisk">GitHub
archive</a></li>
</ul>
<h1 id="section-14">2009</h1>
<h2 id="asp-mode">asp-mode</h2>
<p>I wrote a lot of ASP and PHP in my early career, so I had a small
Emacs mode called <a
href="https://github.com/chrisdone-archive/asp-mode">asp-mode</a>.
Nothing interesting in here, other than to note how seriously I was
using ASP enough to warrant a mode, but obstinantly refused to use
Dreamweaver or whatever was popular at the time. Now-a-days the
equivalent would be Visual Studio Code.</p>
<h1 id="section-15">2008</h1>
<h2 id="kibro">kibro</h2>
<p>In 2008 I was working for a small sum on a hair salon’s new web site,
in Haskell. And I made a very trivial web library called “Kibro” (from
the Lojban “cyberspace”), which sat upon CGI and could be ran from PHP,
which is how I was running it.</p>
<ul>
<li>Source code archive: <a
href="/archives/2008/kibro-0.5.0.tar.gz">kibro-0.5.0.tar.gz</a></li>
<li>Other links: <a
href="https://chrisdone.com/posts/kibro-refactoring/">Kibro
refactoring</a></li>
</ul>
<h2 id="lojbot">lojbot</h2>
<p>Around this time I was an enthusiastic Lojban hobbyist, so I wrote an
IRC bot with various capabilities.</p>
<ul>
<li><a href="https://github.com/chrisdone-archive/lojbot">GitHub
archive</a></li>
<li><a href="https://chrisdone.com/posts/lojbot/">Blog post</a></li>
</ul>
<h1 id="section-16">2006</h1>
<h2 id="slsksoulski">slsk/soulski</h2>
<p>A project for the Soulseek music sharing network. Web site, which may
not remain long-term: <a
href="https://slsk.sourceforge.net/">slsk.sourceforge.net</a>.
Amusingly, it still looks great. <a
href="/images/blog/slsk-screenshot-2007.png">Here’s a screenshot.</a> <a
href="/images/blog/slsk.jpeg">Another</a>. I started writing a C library
for Soulseek: <a
href="/archives/2006/soulski/soulseek-library-0.01.zip">soulseek-library-0.01.zip</a>
I started writing a GUI library in C for it: <a
href="/archives/2006/soulski/exgui-library-0.1.zip">exgui-library-0.1.zip</a>
I started writing a CSS parser in C for it: <a
href="/archives/2006/soulski/css-library-prototype-0.01.zip">css-library-prototype-0.01.zip</a></p>
<p>I originally had big ambitions for this, but later lost interest. It
looks like I planned to rewrite it in Common Lisp, but got bored of the
project before I did.</p>
<h2 id="wdn">wdn</h2>
<p>I had a project called ‘windows desktop notes’ (WDN), that I
originally <a href="/archives/2006/wdm/slsk-code-r110-wdm.zip">wrote in
C</a>. It would overlay some plain text notes on your desktop and you
could click it and get an edit box and then hit Enter to save again.</p>
<p>Then I ported it, or tried to, <a
href="/archives/2006/wdn/wdn.lisp">to Lisp</a>.</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Ezra Cooper, Samuel Lindley, Philip
Wadler and Jeremy Yallop “An idiom’s guide to formlets” Technical
Report, EDI-INF-RR-1263.<a href="#fnref1" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p>Michael had previously built a tool
called fpbuild which basically was kind of like a big lock file and was
unreasonably effective at building very large Yesod-based projects.<a
href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn3" role="doc-endnote"><p>It just had a small technological
advantage of being based on GHC’s parser, rather than haskell-src-exts,
which is always playing catch-up.<a href="#fnref3" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn4" role="doc-endnote"><p>Which I consider a bit of a setback
towards the dream of making style choices a thing of the past. But I
think Ormolu will win eventually. Maintaining forks is hard work.<a
href="#fnref4" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn5" role="doc-endnote"><p>componentm-devel, espial,
essence-of-live-coding, essence-of-live-coding-gloss,
essence-of-live-coding-pulse, ghci-websockets, halive, jsaddle-warp,
monomer, nvim-hs, rapid<a href="#fnref5" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn6" role="doc-endnote"><p>In retrospect I mishandled a
situation where Fay was being used in production and we were breaking
its APIs too often, and I blocked Adam’s <code>master</code> push access
to the repo to give me some breathing room to slow things down, but this
was obviously the wrong move, and not how you should treat early
collaborators. That was my first experience managing a project, so I cut
my younger self some slack. However, he was very gracious about it in
the moment.<a href="#fnref6" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn7" role="doc-endnote"><p>See a complete history <a
href="https://chrisdone.com/posts/clientside-programming-haskell/">here.</a><a
href="#fnref7" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2024-05-12 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sun, 12 May 2024 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Halogen is better than React at everything]]></title><link>https://chrisdone.com/posts/halogen-is-better-than-react</link><guid>https://chrisdone.com/posts/halogen-is-better-than-react</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Halogen is better than React at everything</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Halogen is better than React at everything</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>I wrote these notes in 2022, but found that they still hold up in
2024.</p>
<p>Having used TypeScript + React with its hooks in a code base that
fully embraces them for more than a year, I return to my original
assessment that PureScript + Halogen is better at almost everything.</p>
<p>PureScript has a sensible, type class based notion of equality, and
JavaScript/TypeScript does not, and this comes up regularly, causing
both logic bugs and cache invalidation issues.</p>
<p>Halogen components have a clear explicit reason that a re-render
occurs: calling the modify function in the command evaluator. Inputs
(“props”) generate a command, which means one can trivially implement
custom (i.e. efficient) re-rendering conditions.</p>
<p>Halogen components also have a trivial, built-in way for information
messages to travel both upwards and downwards, outside of the input
mechanism (“props”), which is exceedingly useful. It’s all in the type
signature, too.</p>
<p>Halogen has elegant ways to interact with foreign (non-frameworked)
libraries. The built-in event streams lets you react to out of band
changes (webhook, CodeMirror edits,…). The explicit life cycle and
evaluation-vs-execution distinction makes the interplay predictable.</p>
<p>Halogen sits on an explicit effect monad, meaning you can write async
imperative code with the same syntax as synchronous imperative code, and
know the difference at the type level. It’s harder for things to go
wrong.</p>
<p>In contrast, in React everything is hard and experienced users are
regularly baffled. Re-rendering, caching, execution of effects,
lifecycle, message bubbling and broadcasting, state, are all
marvellously unhelpful by comparison. Asyncs make things even worse!</p>
<p>TypeScript’s type checker regularly falls over, its inference is
brittle in ways that interrupt work, type errors unhelpful, union types
only make things harder. It doesn’t even have sum types. PureScript’s
got all these basic things and were pretty well done from the start.</p>
<p>All in all, my conclusion is that TypeScript + React is a bad
investment. It will cost you in dev time, bugs, maintenance,
performance. Generally, I think the SPA trend is broadly misapplied, I
prefer something like Htmx these days, but if I’m playing the SPA game
(lower latency GUIs), there are far better tools out there.</p>
<p>If you know Haskell then PureScript is better than TypeScript at
everything, and isn’t a dead-end like Elm. For full context on Haskell
frontend, see my other post <a
href="https://chrisdone.com/posts/clientside-programming-haskell/">Client-side
web programming in Haskell: A retrospective</a>.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2024-02-23 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Fri, 23 Feb 2024 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Reports of RSS/Atom's death are greatly exaggerated]]></title><link>https://chrisdone.com/posts/death-of-rss-greatly-exaggerated</link><guid>https://chrisdone.com/posts/death-of-rss-greatly-exaggerated</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Reports of RSS/Atom’s death are greatly exaggerated</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Reports of RSS/Atom’s death are greatly exaggerated</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>I’m not old, but I remember when people said “my web log.” That then
became “blog.”<a href="#fn1" class="footnote-ref" id="fnref1"
role="doc-noteref"><sup>1</sup></a></p>
<p>I subscribe via a feed reader<a href="#fn2" class="footnote-ref"
id="fnref2" role="doc-noteref"><sup>2</sup></a> to a collection of
individual blogs, and a few aggregators (but only the top posts of the
week).</p>
<p>This strikes a good balance of interesting reads (mostly technology
and programming related), and keeping my finger on the pulse of what the
tech world is excited about (big data, IoT, NoSQL, cloud, VR, crypto,
AI, insert trend du jour here).</p>
<p>It also means I only have about 30 or so new posts per day appearing
in my feed, and they can be flicked through in a few minutes. I’ll
bookmark ones that sound interesting to read for when I’m at home and
sitting comfortably. “Screen time” and FOMO are not problems for me.<a
href="#fn3" class="footnote-ref" id="fnref3"
role="doc-noteref"><sup>3</sup></a> I can also setup filters for
bullshit content mill authors.<a href="#fn4" class="footnote-ref"
id="fnref4" role="doc-noteref"><sup>4</sup></a></p>
<p>However, about once a fortnight–on my RSS feed–I regularly see a post
debating why RSS has died, or why it’s making a comeback. There’s
usually related discussion about adoption, the user experience, or
corporate interests (Google Reader, or $popular_newspaper).<a
href="#fn5" class="footnote-ref" id="fnref5"
role="doc-noteref"><sup>5</sup></a></p>
<p>For people who digest things over a course of days or weeks, rather
than doom scrolling and posting their knee-jerk reactions, the situation
for a very broad set of people is that RSS/Atom is in the background
doing what it’s supposed to. No VC-backed endless growth, or
decline.</p>
<p>Feeds continue to serve their modest purpose.</p>
<p>For people lamenting the death of Google Reader, or that Mozilla
dropped the built-in feed icon and reader from Firefox: don’t. Be
thankful that the Great Eye of Business has lost interest in RSS and
does not want to meddle in it anymore.</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Which I thought was “so lame” at the
time. But I’ve grown up since then. A little bit.<a href="#fnref1"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p>I get my other news from more
traditional sources in dead tree format. And I don’t use Facebook,
Instagram, TikTok, Twitter, Threads, or other drugs. According to The
Economist, people are no longer posting or getting their news from
social networks anyway; it’s all happening in private chat groups.<a
href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn3" role="doc-endnote"><p>Partly thanks to Musk completely
bungling Twitter, which was already on thin ice for me. I (along with
many others) migrated to Mastodon, and then lost interest in any kind of
“microblogging” at all. Other people have just deleted their accounts.
Similar to Reddit, really. Tech communites have largely moved to
Discourse.<a href="#fnref3" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn4" role="doc-endnote"><p>Such as Substack, Medium, etc. For
future readers who might not know what these platforms were, they’re
just another type of blogging service, but are extremely aggressive at
bothering you to “sign up to my newsletter” (literally–not a joke), and
the posts are almost all inflammatory, self-promotion, or attempts to
direct you to a product or service.<a href="#fnref4"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn5" role="doc-endnote"><p>You’ll see a similar pattern of
discussion about email, another distributed internet standard.
Unfortunately Big Business is presently a spectre looming over email.<a
href="#fnref5" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2024-02-16 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Fri, 16 Feb 2024 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Hell: Shell scripting Haskell dialect]]></title><link>https://chrisdone.com/posts/hell</link><guid>https://chrisdone.com/posts/hell</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Hell: Shell scripting Haskell dialect</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Hell: Shell scripting Haskell dialect</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p><a href="https://github.com/chrisdone/hell">Hell</a> is a shell
scripting language that is a tiny dialect of Haskell that I wrote for my
own shell scripting purposes. As of February, I’m using Hell to <a
href="https://github.com/chrisdone/hell/blob/main/examples/19-blog-generator.hell">generate
this blog</a>, instead of Hakyll.<a href="#fn1" class="footnote-ref"
id="fnref1" role="doc-noteref"><sup>1</sup></a></p>
<p><strong>Update:</strong> As of 3rd Oct 2024, I’m using it on various
large (2k line) scripts at work in combination with Terraform and
various APIs.</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#!/usr/bin/env hell</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  Text.putStrLn <span class="st">&quot;Please enter your name and hit ENTER:&quot;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>  name <span class="ot">&lt;-</span> Text.getLine</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>  Text.putStrLn <span class="st">&quot;Thanks, your name is: &quot;</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>  Text.putStrLn name</span></code></pre></div>
<p>My 2024 New Year’s Resolution is to write more shell scripts in the
name of automation. I’ve always avoided this because of the downsides of
bash. And <a href="https://danluu.com/cli-complexity/#maven">other
problems.</a></p>
<p>Bash, zsh, fish, etc. have problems:</p>
<ul>
<li>They’re incomprehensible gobbledegook.</li>
<li>They use quotation (<code>x=$(ls -1) ..</code>) which makes it easy
to make mistakes.</li>
<li>They lean far too heavily on sub processes to do basic things.</li>
<li>Therefore things like equality, arithmetic, ordering, etc. are
completely unprincipled. Absolutely full of pitfalls.<a href="#fn2"
class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a><a
href="#fn3" class="footnote-ref" id="fnref3"
role="doc-noteref"><sup>3</sup></a></li>
</ul>
<p>But, bash does have some upsides: It’s stable, it’s simple, and it
works the same on every machine. You can write a bash script and keep it
running for years while never having to change any code. The code you
wrote last year will be the same next year, which is not true of most
popular programming languages. <a
href="http://h2.jaguarpaw.co.uk/posts/ghc-8.10-9.6-experience-report/">Look
at Haskell.</a></p>
<p>So in the interest of defining a language that I <em>would</em> like
to use, let’s discuss the anatomy of a shell scripting language:</p>
<ul>
<li>It should be very basic.</li>
<li>It should run immediately (no visible compilation steps).</li>
<li>It should have no module system.</li>
<li>It should have no package system.<a href="#fn4" class="footnote-ref"
id="fnref4" role="doc-noteref"><sup>4</sup></a></li>
<li>It should have no abstraction capabilities (classes, fancy data
types, polymorphic functions, etc.).</li>
<li>It should not change in backwards-incompatible ways.<a href="#fn5"
class="footnote-ref" id="fnref5"
role="doc-noteref"><sup>5</sup></a></li>
</ul>
<p>Why no module or package system? They make it harder for a system to
be “done.” There’s always some other integration that you can do; some
other feature to add. I’d prefer Hell to be <a
href="https://dubroy.com/blog/cold-blooded-software/">cold-blooded
software</a>, there’s <a
href="https://josem.co/the-beauty-of-finished-software/">beauty in
finished software</a>.</p>
<p>Based on the above, I can define a <em>scripting threshold</em>,
meaning, when you reach for a module system or a package system, or
abstraction capabilities, or when you want more than what’s in the
standard library, then you probably want a general purpose programming
language instead.</p>
<p>Taking this into consideration, I opted for making a Haskell
dialect<a href="#fn6" class="footnote-ref" id="fnref6"
role="doc-noteref"><sup>6</sup></a> because of the following
reasons:</p>
<ul>
<li>I know Haskell.</li>
<li>It’s my go-to.</li>
<li>It has a good story about equality, ordering, etc.</li>
<li>It has a good runtime capable of trivially doing concurrency.</li>
<li>It’s garbage collected.</li>
<li>It distinguishes bytes and text properly.</li>
<li>It can be compiled to a static Linux x86 binary.</li>
<li>It performs well.</li>
<li>It has static types!</li>
</ul>
<p>I made the following decisions when designing the language:</p>
<ul>
<li>Use a faithful Haskell syntax parser.</li>
<li>It’s better that way; you get re-use.</li>
<li>It has no imports/modules/packages.</li>
<li>It doesn’t support recursive definitions, but you can use
<code>fix</code> to do so.</li>
<li>It supports basic type-classes (Eq, Ord, Show, Monad), which are
needed for e.g. List.lookup and familiar equality things.</li>
<li>It does not support polytypes. That’s a kind of abstraction and not
needed.</li>
<li>It use all the same names for things (List.lookup, Monad.forM,
Async.race, etc.) that are already used in Haskell, which lets me re-use
intuitions.</li>
</ul>
<p>You can download statically-linked Linux binaries from <a
href="https://github.com/chrisdone/hell/releases">the releases page.</a>
To read about the implementation internals, see <a
href="https://chrisdone.com/posts/tour-of-hell/">Tour of Hell</a> which
is a set of slides I made for presenting Hell at work.</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>I’m tired of issues like <a
href="https://discourse.haskell.org/t/hakyll-error-watching-and-building/8834">this</a>.<a
href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p>Just check out the huge list of <a
href="https://github.com/koalaman/shellcheck">linting issues in
ShellCheck.</a><a href="#fnref2" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn3" role="doc-endnote"><p>See <a
href="https://yossarian.net/til/post/some-surprising-code-execution-sources-in-bash/">this
blog post about code execution</a><a href="#fnref3"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn4" role="doc-endnote"><p>This excludes scripting languages
like <a href="https://github.com/google/zx">zx</a>, which sits,
unbelievably, on the nodejs ecosystem.<a href="#fnref4"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn5" role="doc-endnote"><p>See also: <a
href="https://stevelosh.com/blog/2018/08/a-road-to-common-lisp/#s4-escaping-the-hamster-wheel-of-backwards-incompatibility">Escaping
the Hamster Wheel of Backwards Incompatibility</a><a href="#fnref5"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn6" role="doc-endnote"><p>And not using some other alt. shell
scripting language or <a
href="https://arathunku.com/b/2024/shell-scripting-with-elixir/">using
Elixir</a>, or <a
href="http://www.oilshell.org/blog/2018/01/28.html">Oil</a>.<a
href="#fnref6" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2023-12-26 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Tue, 26 Dec 2023 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[A spectrum of web dev abstraction]]></title><link>https://chrisdone.com/posts/spectrum-web-dev-htmx-react</link><guid>https://chrisdone.com/posts/spectrum-web-dev-htmx-react</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>A spectrum of web dev abstraction</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>A spectrum of web dev abstraction</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>There’s a spectrum of web dev with two sides:</p>
<ol type="1">
<li><p><strong>Abstraction</strong>: blur the lines between client and
server, pretend you’re writing an offline desktop app with no server, no
latency, no RPC calls, etc. as much as possible. Poster child:
<strong>React</strong>.</p></li>
<li><p><strong>Non-abstraction</strong>: write code like it’s the 90s.
Admit there is a server, use GET/PUT/DELETE/POST end-points, that serve
HTML, use <code>&lt;form&gt;</code>, etc. Poster child:
<strong>Htmx</strong>.</p></li>
</ol>
<p>Over 10 years,<a href="#fn1" class="footnote-ref" id="fnref1"
role="doc-noteref"><sup>1</sup></a> the more I have done (1), the more
I’ve regretted it and wished I’d done (2).</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>See also <a
href="https://chrisdone.com/posts/clientside-programming-haskell/">this
retrospective</a>.<a href="#fnref1" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2023-10-04 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Wed, 04 Oct 2023 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Codebases and love]]></title><link>https://chrisdone.com/posts/codebases-and-love</link><guid>https://chrisdone.com/posts/codebases-and-love</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Codebases and love</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Codebases and love</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Returning to <a
href="https://pages.cs.wisc.edu/~remzi/Naur.pdf">Theory Building (by
Peter Naur)</a>, and why rewrites are inevitable (developer/maintainer
churn = loss of theory), I have a related thought: In the spirit of “a
face only a mother could love”, most (if not all) code-bases larger than
a page are inherently unlikeable to anyone but the original author, and
absent said author, are doomed to be rewritten, either entirely or in
part (Ship of Theseus style), or abandoned, as quickly as is
possible.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2023-10-04 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Wed, 04 Oct 2023 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[AI and Machine Thinking]]></title><link>https://chrisdone.com/posts/ai-machine-thinking</link><guid>https://chrisdone.com/posts/ai-machine-thinking</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>AI and Machine Thinking</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>AI and Machine Thinking</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>AI might take our jobs. That’s bad for us, just like it was for the
Luddites.</p>
<p>But I think Herbert had it right when he, through his Dune books,
proposed that the problem with “machine minds” is not the machine
itself, it’s “machine thinking” which humans are perfectly capable
of.</p>
<p>Related quotes from the books:</p>
<blockquote>
<p>What do such machines really do? They increase the number of things
we can do without thinking. Things we do without thinking — there’s the
real danger. (Leto Atreides II)</p>
</blockquote>
<blockquote>
<p>“The target of the Jihad was a machine-attitude as much as the
machines,” Leto said.</p>
</blockquote>
<p>The brutal, uncompromising, inflexible, tyranny of, as Little Britain
condensed it, “the computer says no.” I’m more afraid of the
encroachment of this chilling effect in my life than losing my job.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2023-09-23 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sat, 23 Sep 2023 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Pickling: The really obvious missing feature of all web browsers]]></title><link>https://chrisdone.com/posts/browser-pickling</link><guid>https://chrisdone.com/posts/browser-pickling</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Pickling: The really obvious missing feature of all web
browsers</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Pickling: The really obvious missing feature of all web
browsers</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Browsers already provide an excellent delivery mechanism for single
page apps. Web apps already have a security model around accessing local
files, microphones, webcams, etc. It’s better than anything on macOS,
Windows or Linux and any phone’s App Store: you can just run an app
instantly and anyone can publish.</p>
<p>The only thing browsers lack is the ability to freeze the page and
cut off its internet access, so that the user can block auto-updates and
spying. If a web page’s contents can be hashed and pinned, Nix-style, it
can be tracked by a community and rated.</p>
<p>Why can’t I download an encryption app or a todo list app on my
browser and just use it, without worrying about trust issues and needing
an internet connection?</p>
<p>I’m surprised I haven’t seen this discussed at all anywhere. If
you’re working on this please email me.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2023-09-07 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Thu, 07 Sep 2023 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Tamagotchi tooling]]></title><link>https://chrisdone.com/posts/tamagotchi-tooling</link><guid>https://chrisdone.com/posts/tamagotchi-tooling</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Tamagotchi tooling</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Tamagotchi tooling</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Remember those tamagotchis that were popular in the early 2000s?
Little devices with a screen showing a pet that needed constant
maintenance; cleaning, feeding, petting, etc.</p>
<p>Some tools are like tamagotchis. They’re a tool, so they have some
use. But that’s not all, they also require substantial upkeep to not
break down, and the owner takes some pleasure in the process. It’s no
surprise when they fail, it’s part of daily experience.</p>
<p>Other tools are more like an old digital watch. They show the time
and don’t require any upkeep at all, are robust, and they work for ages.
They’re so reliable that the owner takes them for granted, and it’s a
shock when they fail. They require no “updates.”</p>
<p>Sometimes, it’s easy to confuse usefulness of a tool with the
enjoyment derived from its upkeep. That can lead to reasoning violently.
A project that sometimes needs the old digital watch can plod along
sluggishly when a tamagotchi is used instead.</p>
<p>The trick is being able to tell the difference.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2023-08-04 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Fri, 04 Aug 2023 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Reasoning violently]]></title><link>https://chrisdone.com/posts/reasoning-violently</link><guid>https://chrisdone.com/posts/reasoning-violently</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Reasoning violently</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Reasoning violently</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>The old bash.org joke goes, “XML is like violence, if it doesn’t
solve the problem, just use more.”</p>
<p>This generalises well. I’ve seen a lot of people choose to continue
using tools that are obviously running counter to their ability to get
work done, even almost paraphrasing the above, but without irony!</p>
<p>It seems to apply strongly to formal languages (XML, Nix, Terraform,
Kubernetes YAML), some architectures (microservices, the cloud, SPAs,
OO), and type systems (dependent types, effect systems, the borrow
checker), and methodologies (scrum, open source). All quite good used in
moderation, but tend to be used like violence.</p>
<p>All downsides become mere setbacks, all potholes become user error or
ignorance, alternative hammers are black holes of complexity! It’s quite
hard to reason with people who are doing this. <em>O ye, of little
faith!</em></p>
<p>That’s reasoning violently.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2023-08-04 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Fri, 04 Aug 2023 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Three questions of language design]]></title><link>https://chrisdone.com/posts/three-questions-of-lang-design</link><guid>https://chrisdone.com/posts/three-questions-of-lang-design</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Three questions of language design</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Three questions of language design</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>There seem to be three interesting questions when I look at a new
(mainstream/practical) programming language:</p>
<ol type="1">
<li>How does it deal with equality/ordering?</li>
<li>How does it deal with arithmetic and operators for the
arithmetic?</li>
<li>How does it handle errors?</li>
</ol>
<p>The typical answers in reply are (1) inconsistently, (2) it’s magic,
(3) at least two, incompatible, ways.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2023-01-07 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sat, 07 Jan 2023 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Things I've changed my mind about]]></title><link>https://chrisdone.com/posts/things-ive-changed-my-mind-on</link><guid>https://chrisdone.com/posts/things-ive-changed-my-mind-on</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Things I’ve changed my mind about</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Things I’ve changed my mind about</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Here’s a small blog post to end 2022. I’ve put together a list of
things I’ve changed my mind about over the past few years, since the
epoch (covid). I’m likely to flesh out each of these in future
posts.</p>
<p>Things I have a new appreciation for:</p>
<ol type="1">
<li>Excel</li>
<li>Rich Hickey</li>
<li>Model checkers, TLA+</li>
<li>Federation</li>
<li>Kubernetes</li>
<li>Email</li>
<li>Alan Kay</li>
<li>REST/Hypermedia</li>
<li>Go</li>
<li>RSS, blogging</li>
<li>Error handling in Erlang</li>
<li>Code vs data</li>
</ol>
<p>Things I view more negatively:</p>
<ol type="1">
<li>Product types (as opposed to record types)</li>
<li>Static types, dependent types</li>
<li>Haskell and Haskellers, Rust</li>
<li>The cloud and SaaS</li>
<li>Fat clients/ the SPA</li>
<li>React</li>
<li>macOS: it isn’t that great</li>
<li>Open source, copyleft, GitHub</li>
<li>“Performance is easy”</li>
<li>Kubernetes (yaml)</li>
<li>Modules</li>
<li>Effect systems</li>
<li>Twitter, and microblogging</li>
</ol>
<p>New things I believe/in:</p>
<ol type="1">
<li>Longevity in software</li>
<li>Stability in packages</li>
<li>Content Addressable Storage, Unison</li>
<li>Conservativism</li>
<li>Parsimony</li>
<li>Common Lisp is valuable because it does everything it does, without
ever changing or evolving.</li>
</ol>
<p>Things I still believe/in:</p>
<ol type="1">
<li>Emacs reigns supreme</li>
<li>No-code isn’t good</li>
<li>Nix is not ready yet</li>
</ol>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2022-12-20 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Tue, 20 Dec 2022 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Inflex]]></title><link>https://chrisdone.com/posts/inflex</link><guid>https://chrisdone.com/posts/inflex</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Inflex</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Inflex</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1306.039 389.638">
<path d="M245.695 48.91L198.18 1.393a4.746 4.746 0 00-6.72 0L1.394 191.46a4.746 4.746 0 000 6.719L191.46 388.246a4.739 4.739 0 003.36 1.392 4.739 4.739 0 003.359-1.392l47.516-47.517a4.746 4.746 0 000-6.719l-44.157-44.157 44.157-44.157a4.746 4.746 0 000-6.72l-44.157-44.157 44.157-44.157a4.746 4.746 0 000-6.719l-44.157-44.157 44.157-44.157a4.746 4.746 0 000-6.719zM194.82 378.167l-84.75-84.75h81.595l43.953 43.952zm-3.155-91.878h-88.723l-40.389-40.39h169.501zm-136.24-47.517l-40.389-40.389h176.63l40.388 40.39zm136.24-47.516H15.035l40.39-40.39h176.628zM62.552 143.739l40.39-40.39h88.722l40.39 40.39zm129.112-47.517H110.07l84.75-84.75 40.798 40.797z" fill="#fff"/><path d="M428.992 323.774v-182.38h11.594v182.38zm5.621-230.172q-4.567 0-8.08-3.339-3.514-3.338-3.514-7.906 0-4.92 3.337-8.258 3.338-3.339 8.257-3.339 4.568 0 8.082 3.339 3.513 3.338 3.513 7.906 0 4.569-3.513 8.083-3.514 3.514-8.082 3.514zm170.057 46.385q34.082 0 53.758 19.855 19.676 19.855 19.676 56.752v107.18h-11.595V217.297q0-32.33-16.338-49.373t-46.555-17.043q-34.081 0-53.757 20.206-19.676 20.206-19.676 54.293v98.394h-11.595v-182.38h11.243v44.628q8.784-21.436 28.284-33.735 19.5-12.3 46.555-12.3zm315.168 206.628l1.054 9.84q-8.784 3.865-19.325 3.865-21.784 0-33.379-12.65-11.595-12.651-11.595-34.087V124.877q0-26.707-11.243-39.71-11.243-13.001-32.676-13.001t-32.676 13.002q-11.244 13.002-11.244 39.709v16.516h60.082v10.19h-60.082v172.19H757.16v-172.19h-34.433v-10.19h34.433V125.58q0-31.627 14.582-47.616 14.581-15.989 40.933-15.989 26.703 0 41.109 15.813 14.405 15.814 14.405 47.792v185.894q0 38.304 33.73 38.304 10.19 0 17.92-3.163zm110.326-32.33q18.622 0 34.433-6.852t26.352-20.206l7.027 7.731q-11.946 14.76-29.69 22.315-17.743 7.555-38.473 7.555-26.352 0-47.434-11.772-21.081-11.772-33.027-32.857-11.946-21.084-11.946-47.791 0-26.707 11.243-47.792 11.244-21.084 31.095-32.856 19.852-11.773 45.15-11.773 23.19 0 41.811 11.07 18.622 11.07 29.69 30.045 11.068 18.976 12.473 41.818L951.46 254.195q6.676 27.41 27.757 43.75 21.082 16.34 50.947 16.34zm-5.27-163.755q-22.136 0-39.352 10.366-17.217 10.367-27.055 28.816-9.838 18.449-9.838 41.641 0 4.92.703 13.354l147.57-28.815q-2.46-17.57-11.946-32.506-9.487-14.935-24.947-23.895-15.46-8.961-35.135-8.961zm266.329 173.244h-14.406l-66.055-85.744-66.055 85.744h-13.703l73.082-94.178-69.217-88.203h13.702l62.19 79.77 61.84-79.77h13.351l-68.514 88.203z" fill="#fff"/><path d="M333.375-.027v389.665" fill="none" stroke="#fff" stroke-width="11.54"/>
</svg>
<style>h1{display:none}
body{background-color:#15263b;color:#aaa;font-family:sans-serif} a { color: #a7bdd9;
text-decoration: none; } footer { display: none } a:hover {   text-decoration: underline;
            color: #fff;}</style>
<p>Inflex<a
href="https://trademarks.ipo.gov.uk/ipo-tmcase/page/Results/1/UK00003503076">®</a>
was a new creative digital workspace: powerful functional language
(Haskell-inspired), rich data structures (no grid!), browser-based.</p>
<p>Inflex was a project that I had been working on in my spare time,
along with my partner, Giulia Costa, for 2 years. Progress ground to a
halt when I had a kid.</p>
<p>I’m no longer working on it.</p>
<p>There is an archive of its source code available under AGPL (that
means running it as a service counts as distribution) license:</p>
<ul>
<li>https://github.com/chrisdone/inflex</li>
<li>https://git.sr.ht/~chrisdone/inflex</li>
</ul>
<p>The compiler source might be of interest to language implementation
nerds.</p>
<p>You can checkout the [dead] Twitter account <a
href="https://twitter.com/InflexHQ">InflexHQ</a> feed for screenshots,
videos.</p>
<p>Related posts where you can get more of a feel of where my head was
at:</p>
<ul>
<li><a
href="https://chrisdone.com/posts/language-of-spreadsheets-is-bad/">The
language of spreadsheets is bad</a></li>
<li><a
href="https://chrisdone.com/posts/whats-wrong-with-the-grid/">What’s
wrong with the grid?</a></li>
<li><a
href="https://chrisdone.com/posts/inflex-bibliography/">Bibliography</a></li>
<li><a
href="https://docs.google.com/presentation/d/10aw_x3NbJSwDA9rIBhTa1CfdJS-aKwu7UyDIE4g8vQU/edit#slide=id.p">Tech
talk slides</a> - these are very technical.</li>
</ul>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2022-10-21 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Fri, 21 Oct 2022 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Immutable Publishing Policy]]></title><link>https://chrisdone.com/posts/ipp</link><guid>https://chrisdone.com/posts/ipp</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Immutable Publishing Policy</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Immutable Publishing Policy</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<h2 id="summary">Summary</h2>
<p>This is a policy for publishing Haskell packages. It was published in
<strong>February of 2022</strong>. The aim of this policy is to remove
all breaking changes to downstream users of packages, where feasible. It
is most applicable to packages which have users, and/or have a more or
less stable API. It prioritizes downstream users at the expense of
author convenience.</p>
<p>It has been implemented in the <a
href="https://github.com/chrisdone/lucid">lucid</a> package.</p>
<h3 id="terms">Terms</h3>
<p>By “levels” in this description, we mean “module” is the first level,
and “package” is the level above.</p>
<h3 id="rules">Rules</h3>
<ul>
<li>If you <strong>require more</strong>, that’s a break.
<ul>
<li>E.g. adding an extra field to a record or requiring a class
constraint, add an extra constructor which users can pattern match on,
or another package dependency or newer major version of a package that
wasn’t needed before.</li>
</ul></li>
<li>If you <strong>provide less</strong>, that’s a break.
<ul>
<li>E.g. if you remove an export or a field of a record, return less or
different from a function, remove a module, or an instance of an exposed
type.</li>
</ul></li>
<li>If you <strong>change something</strong>, that’s a break of the next
level up.
<ul>
<li>E.g. if you change the type signature of an exposed function, or
change a data type’s definition which is exposed.</li>
</ul></li>
<li>If you <strong>just add</strong> something, then just bump the minor
version (which is the only thing that changes in this scheme) of the
package; you can use the current date e.g. <code>0.0.20210101</code>.
<ul>
<li>E.g. a non-orphan instance of a type from your own package.</li>
</ul></li>
</ul>
<p>Haskell-specific note:</p>
<ul>
<li>If you add an orphan instance in your library–which you
<strong>should not do</strong>–that’s definitely a breaking change for
the whole package, <strong>bump the package.</strong></li>
<li>A user may have written an orphan instance for one of your types,
but this is a departure from standard practice, and therefore isn’t
protected from breaking change. You should feel free to <strong>add new
instances</strong> for your own types.</li>
<li><a href="https://pvp.haskell.org/#leaking-instances">Be careful
about leaking instances</a>. If you bump your package when you bump your
dependencies major versions, then you should be safe from this.</li>
</ul>
<h3 id="steps">Steps</h3>
<p>This <strong>differs substantially to <a
href="https://pvp.haskell.org/">the PVP</a>.</strong> ⚠️</p>
<ul>
<li>If you want to change a thing <code>foo</code>, just make a copy of
it and call it <code>foo2</code>.</li>
<li>If it’s impractical to add another version of a thing (because,
e.g. you changed a class or a data type that’s used in many places),
then copy the whole module <code>Foo</code> to <code>Foo2</code>.</li>
<li>If it’s impractical to just copy a module, then it’s time to copy
the package, <code>foo</code> to <code>foo2</code>.</li>
<li>If you want to rename or remove something from a module, clone the
module. If you want to remove or rename a module, clone the
package.</li>
</ul>
<h3 id="rationale">Rationale</h3>
<ul>
<li>It’s more effort for an author to make breaking changes. The author
pays a price, and has to think twice about whether it’s worth it.</li>
<li>The user <strong>optionally</strong> pays a small price to upgrade
to new functionality, rather than a <em>mandatory tax</em> for changes
they don’t want, which is the PVP system.</li>
<li>For more elaboration, watch Rich Hickey’s video <a
href="https://www.youtube.com/watch?v=oyLBGkS5ICk">Spec-ulation</a>.</li>
<li>Related mantra of the Linux kernel: <em><a
href="https://unix.stackexchange.com/questions/235335/why-is-there-a-linux-kernel-policy-to-never-break-user-space">don’t
break user-space</a></em></li>
<li>I don’t agree at all with <a
href="http://blog.ezyang.com/2016/12/thoughts-about-spec-ulation-rich-hickey/">this
post</a> by ezyang</li>
</ul>
<h3 id="long-term-steps">Long-term steps</h3>
<ul>
<li>You can publish additions to your old versions of modules and
packages.</li>
<li>You can choose to stop maintaining them at some point. For example,
a duplicate module hierarchy. You can just drop the old one and publish
a new package.</li>
<li>By the PVP, packages that use your package will force their users to
use your newer API, which will make them unhappy. By following the IPP,
you give your users the chance to import both library versions and maybe
write some migrations between the two versions.</li>
</ul>
<h3 id="infrastructuretechnical-support">Infrastructure/technical
support</h3>
<ul>
<li>Hackage supports deprecating a package in favour of something else.
That’s your means to tell users of newer versions.</li>
<li>GHC lets you mark declarations and modules as deprecated, which is
issued as a warning.</li>
<li>Users can use
<code>module Lib (module Lib2) where import Lib2</code> to try newer
versions of module hierarchies as “drop-ins”.</li>
<li>For a package following the IPP, you can just depend on
<code>package &gt;= 0.0.n</code> where <code>n</code> is the feature
that you need. You never need an upper bound because there are no
breaking changes.</li>
<li>Both Hackage and Stackage will allow you to upload package1,
package2, etc. and so your users can continue to use the package1 if
they’re not interested in package2, and if they’re not forced by
PVP-following maintainers of other packages that they’re using.</li>
</ul>
<h3 id="compatibility-with-the-pvp">Compatibility with the PVP</h3>
<p>You can do both, the IPP is a subset of behavior within the PVP (but
upper bounds aren’t required or needed by the IPP). In practice, people
following just the PVP and not the IPP will be a pain for you as
Haskellers change things and cause breakage all the time. But don’t
bother people about it. Just do your best.</p>
<h3 id="when-to-use-this-policy">When to use this policy</h3>
<p>I propose that you should:</p>
<ul>
<li>Put new experimental packages on GitHub/GitLab/sourcehut, etc. and
using Stack or Cabal you can specify dependencies on that package by a
commit hash. At this stage, authors can change as much as they want and
users can pin to commits.</li>
<li>If your design becomes stable and you want to support the package,
put it on Stackage or Hackage. Now apply IPP.</li>
</ul>
<p>For packages already published, you can apply IPP immediately.</p>
<h3 id="faqs">FAQs</h3>
<h4 id="do-you-just-want-unison">Do you just want Unison?</h4>
<p>Sure, but that’s a whole new language. Haskell is our language of
choice, so let’s do our best to make it nicer to use.</p>
<h4
id="its-not-worth-doing-because-we-should-have-machines-automate-dependencies-based-on-fine-grained-uses">It’s
not worth doing because we should have machines automate dependencies
based on fine grained uses</h4>
<p>That’s true. Here in the real world, however, no such automation
exists.</p>
<h4
id="security-fixes-can-be-breaking-changes-we-should-make-bad-code-go-away">Security
fixes can be breaking changes, we should make bad code go away</h4>
<p>You don’t know how and in what setting your users are using your
libraries. It’s not your place to bully them into changing their
programs because you know better.</p>
<h4 id="shouldnt-old-code-be-garbage-collected">Shouldn’t old code be
garbage collected?</h4>
<p>Yes, I covered deprecation above. I also covered removing old code
and the ending of maintenance above.</p>
<h4
id="what-if-i-add-a-constructor-to-a-type-id-have-to-duplicate-my-whole-api">What
if <em>I</em> add a constructor to a type? <em>I’d</em> have to
duplicate my whole API!</h4>
<p>Yes. If <em>you</em> add a new constructor then <em>you’ll</em>
indeed <strong>require more</strong> of the consumer of your package to
form a complete pattern match. Duplicate the type. <em>You</em> changed
a namespace.</p>
<p>I’ll repeat myself: the IPP is about valuing the user’s time over the
maintainer’s time. <em>It’s not all about you and your needs.</em> Think
about others who have to consume your work.</p>
<p>Even the containers package authors plan to <a
href="https://github.com/haskell/containers/pull/1049/files">remove old
names</a>, despite there being no reason to do so.</p>
<h4
id="why-have-package-versions-when-you-are-going-to-duplicate-an-entire-module-or-package-when-you-make-a-breaking-change">Why
have package versions when you are going to duplicate an entire module
or package when you make a breaking change?</h4>
<p>I already covered this above, but let’s rewrite in a different way:
Package versions in Haskell are broken. They force all package
maintainers to move in lock step. You can only practically use
<strong>one</strong> version of a package in your installed package
scope.</p>
<p>If you want to keep using foo-1.2.3 and another package you’re using
wants foo-2.0.0, you shouldn’t be forced to change all your code. You
should be given the option to migrate between them.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2022-02-11 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Fri, 11 Feb 2022 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[A plain English description of monads without Haskell code]]></title><link>https://chrisdone.com/posts/monads</link><guid>https://chrisdone.com/posts/monads</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>A plain English description of monads without Haskell
code</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>A plain English description of monads without Haskell code</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<blockquote>
<p>“That’s actually the first time I read an explanation about monads
that I understand.” – Commenter</p>
</blockquote>
<blockquote>
<p>“I just read your explanation, and suddenly I think I understand
monads.” – Reviewer</p>
</blockquote>
<p>Monads are notorious in the programming world for their use in the
Haskell programming language and for being hard to grasp. There’s even a
joke that writing a “monad tutorial” is a rite of passage for new
Haskellers, and been described as pointless.<a href="#fn1"
class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a>
I’ve been using Haskell for over a decade and have refrained from
writing yet another monad tutorial.</p>
<p>A friend asked for an easy explanation of them that doesn’t involve
Haskell code.<a href="#fn2" class="footnote-ref" id="fnref2"
role="doc-noteref"><sup>2</sup></a> That’s easier.</p>
<p>You can re-use your intuition from existing common place chaining of
things in other popular languages:</p>
<ul>
<li>Async chains (<a
href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">JS</a>)</li>
<li>Parser combinator chains (<a
href="https://github.com/Geal/nom">Rust</a>, JS)</li>
<li>Optional or erroneous value chains (TypeScript, <a
href="https://doc.rust-lang.org/std/result/">Rust</a>)</li>
<li>Continuation passing style (you can do this in Lisp and JS)</li>
<li>Cartesian products/SQL (<a
href="https://en.wikipedia.org/wiki/Language_Integrated_Query">C#’s
LINQ</a>)</li>
</ul>
<p>One of the Haskell designers<a href="#fn3" class="footnote-ref"
id="fnref3" role="doc-noteref"><sup>3</sup></a> in the 90s just came up
with a <strong>class/interface that worked for all of these</strong>. As
he was into category theory, he related it to the idea of a “monad”. The
types also sort of match the theory if you squint hard enough.</p>
<p>Then they came up with a syntax (actually, two<a href="#fn4"
class="footnote-ref" id="fnref4" role="doc-noteref"><sup>4</sup></a>)
that was syntactic sugar for calling the class methods to make it feel
more ergonomic.</p>
<p>Parsers, CPS, async, optional chaining, all look more or less like
this in most modern popular programming languages:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>getThing<span class="op">.</span><span class="fu">and_then</span>(x <span class="kw">=&gt;</span> <span class="fu">putThingElsewhere</span>(x<span class="op">+</span><span class="dv">4</span>))<span class="op">.</span><span class="fu">and_then</span>(<span class="op">..</span>)</span></code></pre></div>
<p>For a parser you track the position in the string and plumb that
through. For an “optional” it just short circuits if the left hand side
of <code>and_then</code> is nil/null/undefined. For async it would do
something async, like make a web request to get the thing, and then call
the callback, etc.</p>
<p><strong>Monad is the name of the class</strong> for “and_then”,<a
href="#fn5" class="footnote-ref" id="fnref5"
role="doc-noteref"><sup>5</sup></a> defined in a sensible way, with some
laws for how it should behave predictably, and then a bunch of library
code works on anything that implements “and_then”.</p>
<p>Apart from F# or Haskell (or descendants), no other language<a
href="#fn6" class="footnote-ref" id="fnref6"
role="doc-noteref"><sup>6</sup></a> embraces the abstraction with syntax
so it’s hard to find a good explanation without them. It’s like
explaining Lisp macros without using a Lisp, the explanation tends to be
awkward and unconvincing.</p>
<p>If you have mutation, you might not bother plumbing stuff for a
parser, you might just update the position in place, and throw an
exception on a parse error. If your language supports returning early
from functions then you can just use that to short circuit (Rust does
this). If your language puts in a special case for async with “await”
syntax (JS, Rust, C#), you’ll just use that. Other ways of doing things
just make the idea of a monad abstraction kind of unnecessary.</p>
<p>Haskellers don’t like to throw exceptions, or use mutation, and
functions can’t return early, etc. Suddenly Monad and syntactic sugar
for it looks pretty attractive to them.</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p><a
href="https://byorgey.wordpress.com/2009/01/12/abstraction-intuition-and-the-monad-tutorial-fallacy/">Abstraction,
intuition, and the “monad tutorial fallacy”</a><a href="#fnref1"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p>I understand, almost any explanation
of them uses Haskell types to aid their explanation. <a
href="https://en.wikipedia.org/wiki/Monad_(functional_programming)">Wikipedia’s
article is garbage.</a><a href="#fnref2" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn3" role="doc-endnote"><p><a
href="https://homepages.inf.ed.ac.uk/wadler/papers/marktoberdorf/baastad.pdf">Monads
for functional programming</a><a href="#fnref3" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn4" role="doc-endnote"><p>Either do-notation or list
comprehensions (yes, like in Python), which can be generalised to monad
comprehensions. You can look that up if interested.<a href="#fnref4"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn5" role="doc-endnote"><p>There happen to be a plethora of
other things that implement the Monad class–some really weird stuff–but
linking to them would just give you a big list of Haskell type
signatures, which you need to know Haskell to understand. It’s not
called “and_then”, either but that’s an implementation detail.<a
href="#fnref5" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn6" role="doc-endnote"><p>Well, OCaml and other ML-descendents
do dabble with this these days.<a href="#fnref6" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2022-01-31 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Mon, 31 Jan 2022 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Thoughts on type class implementation]]></title><link>https://chrisdone.com/posts/typeclass-implementation</link><guid>https://chrisdone.com/posts/typeclass-implementation</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Thoughts on type class implementation</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Thoughts on type class implementation</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>While designing and implementing Inflex, I discovered that there’s a
lot of space in design decisions around type classes. Haskell’s
implementation of them has a number of pre-made decisions built into
Haskell 98. Many extensions (multiple type params, functional
dependencies, associated types) have been added to support type level
programming since then. Inflex’s needs are more modest.</p>
<p><a href="https://okmij.org/ftp/Haskell/TypeClass.html#Haskell1">Oleg
Kiselyov has shown</a> that in practice you only really need one type
class, with clever use of instances. So you could imagine that a
language with just a single type class and open instances would be
called ClosedClassOpenInstances.</p>
<p>You might not permit new classes and instances, only built in ones.
So an alternative language might be called ClosedClassesClosedInstances.
A language that would benefit from this would be Elm.</p>
<p>I decided not to support multiple methods for a single class. This
makes the feature more like “generic functions.” For any multi method
class in Haskell, I can often find a type that would be an instance if
it weren’t for one method.</p>
<p>Another consideration is whether to permit superclasses. Haskellers
are very tempted to make class hierarchies. People like <a
href="https://github.com/fsharp/fslang-suggestions/issues/243#issuecomment-916079347">Don
Syme would argue</a> that this urge leads nowhere good. Haskell’s own
Prelude has a very questionable hierarchy. I decided against
superclasses too.</p>
<p>Elsewhere there are other surprises. A really simple compiler like
Inflex goes through stages like this:</p>
<ul>
<li>Lex, parse, rename</li>
<li>Generate constraints (elaboration)</li>
<li>Solve constraints</li>
<li>Generalize (insert poly types)</li>
<li>Resolve (resolve class method calls to instances)</li>
<li>Defaulter</li>
</ul>
<p>This is reasonable enough. Very easy to understand each stage.</p>
<p>But there’s a non-obvious limitation in this approach which is that
if you want to support instance contexts, then, after resolving an
instance, you need to add the constraints from the context, and then go
back to solving constraints again. Inflex doesn’t support instance
contexts, but if it did, it would need a different pipeline.</p>
<p>There’s a bunch of papers about type classes, especially getting
inference to work well for them. Other things like <a
href="https://dl.acm.org/doi/abs/10.1145/1932681.1863596">instance
chains</a> as implemented in PureScript are also a departure from
Haskell.</p>
<p>I’ll write more another time with more code examples.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2022-01-09 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sun, 09 Jan 2022 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[My negative views on Rust]]></title><link>https://chrisdone.com/posts/rust</link><guid>https://chrisdone.com/posts/rust</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>My negative views on Rust</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>My negative views on Rust</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p><strong>2023-10-13:</strong> Edited based on feedback, but preserves
the same opinions.</p>
<p>This is a little summary of my current thoughts on Rust. I wonder
whether I’ll look back in five years and see if my views have
changed.</p>
<h2 id="the-good">The Good</h2>
<p>So that Gentle Reader knows that I’m not entirely biased against the
language, there are obviously positive things to appreciate about
it:</p>
<ul>
<li>Rust’s macros are very good. They act like Lisp’s macros, unlike
Haskell’s.</li>
<li>The fact that Rust has type-classes (“traits”) and sum types
(“enums”) and pattern matching is very attractive. Making orphans
package-wide rather than module-wide is a very good decision.</li>
<li>I like its treatment of records.</li>
<li>Its standard library does a few things well, like handling strings
as UTF-8.</li>
<li>Distinguishing mutability has its advantages, it’s easy to see that
a function is “morally” pure–if not actually pure–and that’s good for
reading.</li>
</ul>
<h2 id="unsafe-and-panic">Unsafe and panic</h2>
<p>The use of unsafe is a little disturbing, because many libraries
feature it, and people are tempted to use it on private work projects to
quickly get around the language’s limitations. But it’s not much
different to using an FFI. I don’t see this is a big downside.</p>
<p><code>panic</code> is a little more bothersome, because Rust
libraries go to great pains (with many syntactic tricks like
<code>?</code> and auto-conversions from smaller error types to larger
ones) to handle errors explicitly, but then panics unwind the stack to
the top of the process, and panics inside a panic don’t run destructors,
etc. The overall effect is that, like <a
href="https://chrisdone.com/posts/three-questions-of-lang-design/">my
three questions of language design</a>, the answer to “how you handle
errors” is “at least two, incompatible ways.”</p>
<h2 id="take-sugar">Take Sugar?</h2>
<p>Rust’s use of magical sugar constructs, where the compiler will
automatically insert dereferences and copies and drops for you has an
initial appealing “it’s all simple underneath” quality to it, but in
practice this leads to bad compile errors: The worst kind of compile
error is the one where the compiler is complaining about something that
it generated for you, rather than something you explicitly wrote.</p>
<p>This can be compared with Haskell’s use of monads, that provide
syntactic sugar. The more magic you introduce, the harder it is for
newbies to learn and to talk about.</p>
<h2 id="fetishization-of-efficient-memory-representation">Fetishization
of Efficient Memory Representation</h2>
<p>I’ve watched people on calls that are a couple years into Rust spend
20 minutes attempting to understand why their perfectly reasonable code
doesn’t fit into Rust’s tight memory restrictions.</p>
<p>I’ve also been Rust-splained, by people with white in their hair,
with an air of misty-eyed revelation, that once you “get” Rust’s memory
model of the stack and the heap,<a href="#fn1" class="footnote-ref"
id="fnref1" role="doc-noteref"><sup>1</sup></a> that things just all fit
together wonderfully. There’s nothing wrong with that, but it’s a
theme.</p>
<p>This touches on another topic I’d like to write about elsewhere: the
difference between practice and theory and how users of languages like
Rust and Haskell that make big promises and require big sacrifices don’t
seem to distinguish the difference. <a
href="https://chrisdone.com/posts/reasoning-violently/">It’s not the
technology that’s working poorly, it’s that you’re using it
wrongly.</a></p>
<p>In practice, people just want to be able to write a tree-like type
without having to play Chess against the compiler. I predict that
tracing garbage collectors will become popular in Rust eventually.</p>
<p>This is both Rust’s main goal–be like C, no garbage collection,<a
href="#fn2" class="footnote-ref" id="fnref2"
role="doc-noteref"><sup>2</sup></a> but safe–and also its main downside.
People waste time on trivialities that will never make a difference.</p>
<h2 id="the-rewrite-fallacy">The Rewrite Fallacy</h2>
<p>I see a lot of “we rewrote X in Rust and it got faster” posts. I
think that if you rewrite anything from scratch with performance in
mind, you’ll see a significant performance improvement. I’m suspicious
of how much Rust itself is needed versus the developers having some
performance discipline.</p>
<h2 id="complexity">Complexity</h2>
<p>Rust has arrived at the complexity of Haskell and C++, each year
requiring more knowledge to keep up with the latest and greatest. Go was
designed as the antidote to this kind of endlessly increasing language
surface area. Endless libraries re-treading existing patterns (web
services, parsers, etc.) in Rust. As a long-term Haskeller, I’ve done
more than 15 years of riding a hamster wheel like that. It is fun for a
while, but at some point I grew tired of it. This aspect of Rust puts me
off. I don’t need another <a
href="https://chrisdone.com/posts/tamagotchi-tooling/">tamagotchi</a>.</p>
<h2 id="the-friendly-community">The “Friendly” Community</h2>
<p>All new language communities are nice. When things don’t matter much,
people have no reason to get mad.</p>
<p>As soon as people have a stake in something, that’s when things heat
up and tempers come out. You get a stake in a programming language by
writing a lot of code in it, or by building a business on it. When you
have a stake in how a language works, you’re highly sensitive to changes
that will make you do more work than needed, or will limit your
goals.</p>
<p>I’ve seen this play out for Haskell. Around 2007, when I started with
Haskell, the community was friendly as anything, evangelic, open. People
praised it for this. Everyone just felt blessed to be able to use this
exciting language. Today, it’s more like any other community. What
happened? People started using Haskell for real, that’s all.</p>
<p>Rust is going through the same thing, much more rapidly. Is it a
reason to avoid Rust? No. But a “nice” community isn’t a reason to join
an upcoming language, either.</p>
<p>Since I wrote this, people are already trying to <a
href="https://news.ycombinator.com/item?id=36122270">fork Rust</a>
because they’re not happy with the governance of it. This doesn’t mean
anything deep other than that people are using Rust now, as stated
above, and the “friendly, welcoming” starts to become mixed with more
diverse moods and motivations.</p>
<h2 id="async-is-highly-problematic">Async is highly problematic</h2>
<p>Rust’s choice to exclude a runtime/scheduler blessed and built-in to
the language means they had to develop alternative strategies in the
language itself. This is not turning out well.</p>
<p><a
href="https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/">Coloured
Functions</a> is a powerful metaphor for the incompatibility between
async and synchronous functions and the awkward situations that mixing
them introduces. Some blog posts have attempted to downplay the
situation by focusing on technical aspects of specific syntactic forms.
That doesn’t really matter, though, because the reality is much simpler:
Async code is easier to use when dependencies are in an async form.</p>
<p>People will choose libraries that are async over libraries that are
not. However, maintainers that have written good, maintained code, are
also resistant to adopt async.</p>
<ul>
<li><p>One conversation I’ve overhead:</p>
<blockquote>
<p>Person 1: Another difference between diesel and sqlx is that diesel
is not async yet and from looking at the issues it doesn’t seem to be
priority yet.</p>
<p>Person 2: That sounds like a major issue</p>
</blockquote></li>
</ul>
<p>As the saying goes, the proof of the pudding is in the eating of the
pudding. Async introduces <a
href="https://github.com/diesel-rs/diesel/issues/399">long, heated
discussions.</a></p>
<p>The problem for Rust is that its users want a runtime, but want the
option of not having one. The result is a mess. When combined with
iterators, I think understanding such code is quite difficult.</p>
<p>Generally, I think Go, Erlang and Haskell are the better choice here
for general purpose use. A tracing garbage collector and green threads
make programmers more productive for general purpose programming (not
systems programming). Which brings me to the next section.</p>
<h2 id="as-a-general-purpose-language">As a general purpose
language</h2>
<p>I feel like Rust is self-defined as a “systems” language, but it’s
being used to write web apps and command-line tools and all sorts of
things.</p>
<p>This is a little disappointing, but also predictable: the more
successful your language, the more people will use your language for
things it wasn’t intended for.</p>
<p>This post still offends <a
href="http://www.paulgraham.com/identity.html">many who have tied Rust
to their identity</a>, but that’s their problem, not mine.</p>
<h2 id="conclusions-if-any">Conclusions, if any</h2>
<p>I won’t be using Rust for any of my own personal projects for the
above stated reasons. But it was used at my job at the time of writing,
so I felt the need to express myself about it.</p>
<p>But I wouldn’t mind using it as a replacement for single-threaded C
if I just use the standard library, that might be fun, although I don’t
do any embedded work, so I wouldn’t hold my breath.</p>
<p>I think that the excellent tooling and dev team for Rust, <a
href="https://www.youtube.com/watch?v=XZ3w_jec1v8">subsidized by Big
Tech</a>, pulls the wool over people’s eyes and convinces them that this
is a good language that is simple and worth investing in. There’s danger
in that type of thinking.</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Having done my fair share of C code,
there’s nothing new here for me.<a href="#fnref1" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p>Of course, <code>Rc</code> and
<code>Arc</code> are reference counters, which is a form of garbage
collection. See <em>The Garbage Collection Handbook: The Art of
Automatic Memory Management</em> published in 1996. But most developers
have a superficial understanding of garbage collection as a technical
subject, and therefore “garbage collection” for them means “tracing
garbage collector.” Hence bizarre discussions that pit “garbage
collecion versus reference counting.” It’s like saying fruit versus
apples.<a href="#fnref2" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2021-12-22 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Wed, 22 Dec 2021 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Inflex Bibliography]]></title><link>https://chrisdone.com/posts/inflex-bibliography</link><guid>https://chrisdone.com/posts/inflex-bibliography</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Inflex Bibliography</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Inflex Bibliography</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<h2 id="direct-influences">Direct influences</h2>
<ul>
<li><a
href="http://erlang.org/pipermail/erlang-questions/2011-May/058768.html">Why
do we need modules at all?</a></li>
<li><a
href="https://caml.inria.fr/pub/papers/garrigue-polymorphic_variants-ml98.pdf">Polymorphic
variants</a></li>
<li><a href="https://qfpl.io/posts/reflex/basics/behaviors/">Behaviors
of Reflex</a></li>
<li><a href="https://www.researchgate.net/profile/Ray-Panko">Ray Panko’s
work on spreadsheets and bugs</a></li>
<li><a href="http://lighttable.com/2014/05/16/pain-we-forgot/">Pain We
Forgot</a></li>
<li><a href="https://www.haskell.org/">Haskell</a> (classes, pure)</li>
<li><a href="https://chrisdone.com/toys/duet-delta/">Duet</a>
(stepper)</li>
<li><a href="https://www.purescript.org/">PureScript</a> (row
types)</li>
<li><a href="https://www.unisonweb.org/">Unison</a> (CAS code)</li>
<li><a href="https://clojure.org/">Clojure</a></li>
<li><a href="https://www.youtube.com/watch?v=hIZxTQP1ifo">Type classes
vs the world</a> (coherence)</li>
<li><a href="https://www.youtube.com/watch?v=oytL881p-nQ">Simple made
easy</a> (names over positioning)</li>
<li><a href="https://m.youtube.com/watch?v=oyLBGkS5ICk">Spec-ulation</a>
(specifically, dependencies)</li>
</ul>
<h2 id="reading-list">Reading list</h2>
<ul>
<li><a
href="https://www.semanticscholar.org/paper/Haxcel-A-spreadsheet-interface-to-Haskell-written-Malmström/739998d4b2cd3b389f1593f20ca326f0025b3a32?p2df">Haxcel</a></li>
<li><a
href="http://hirzels.com/martin/papers/ecoop14-activesheets.pdf">Streaming
spreadsheets</a></li>
<li><a
href="http://www.bitsavers.org/pdf/xerox/xsis/XSIS_Smalltalk_Products_Apr87.pdf">Smalltalk
spreadsheet</a></li>
<li><a href="http://rmf.vc/implementingvisicalc">Implementing
VisiCalc</a> - some things in Inflex coincidentally match VisiCalc’s
original design: <span class="citation" data-cites="func">@func</span>
for functions, fixed precision numbers</li>
<li><a href="https://www.notboring.co/p/excel-never-dies">Excel will
never die</a></li>
<li><a
href="https://pchiusano.github.io/2018-02-13/typeclasses.html">The
trouble with typeclasses</a></li>
</ul>
<h2 id="consulted">Consulted</h2>
<ul>
<li><a href="https://arxiv.org/abs/1906.11422">Stepping OCaml</a></li>
<li><a href="https://web.cecs.pdx.edu/~mpj/thih/thih.pdf">Typing Haskell
in Haskell</a></li>
<li><a
href="http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.42.3091&amp;rep=rep1&amp;type=pdf">Type
Inference with Polymorphic Recursion</a></li>
<li><a
href="http://reasonableapproximation.net/2019/05/05/hindley-milner.html">A
reckless introduction to Hindley-Milner type inference</a></li>
<li><a
href="http://blog.ezyang.com/2014/07/type-classes-confluence-coherence-global-uniqueness/">Type
classes: confluence, coherence and global uniqueness</a></li>
<li><a
href="http://okmij.org/ftp/Haskell/TypeClass.html#Haskell1">Haskell with
only one typeclass</a></li>
<li><a
href="https://reasonablypolymorphic.com/blog/algorithmic-sytc/">Algorithmically
Scrapping Your Typeclasses</a></li>
</ul>
<h2 id="similar-space-research-projects">Similar space research
projects</h2>
<ul>
<li><a href="http://mesh-spreadsheet.com/">Mesh</a></li>
<li><a
href="https://www.cs.cmu.edu/~shihpinc/gneiss.html">Gneiss</a></li>
<li><a href="https://plutojl.org/">Plutojl</a></li>
<li><a href="https://www.apogeejs.com/">Apogee</a></li>
<li><a href="https://chrisuehlinger.com/LambdaBubblePop/">Bubble
Pop!</a></li>
<li><a href="http://people.cs.uchicago.edu/~rchugh/">Ravi Chugh’s
work</a> (Sketch-n-Sketch, Ivy)</li>
</ul>
<h2 id="vaguely-similar-market-products">Vaguely similar market
products</h2>
<ul>
<li><a href="https://trymito.io/launch">Mito</a></li>
<li><a href="https://bamboolib.8080labs.com/">Bamboo</a></li>
<li><a href="https://blockpad.net/">Blockpad</a></li>
<li><a href="https://cubeweaver.com/">CubeWeaver</a></li>
<li><a href="https://github.com/livebook-dev/livebook">Livebook</a></li>
<li><a href="https://coda.io/welcome">Coda</a></li>
<li><a href="https://blog.rows.com/p/rows-beta">Rows</a> (previously
dashdash)</li>
<li><a href="https://grid.is/">Grid</a></li>
<li><a href="https://ellx.io/">Ellx</a></li>
<li><a href="https://baserow.io/">Baserow</a></li>
<li><a href="https://cloudtables.com/">CloudTables</a></li>
<li><a href="https://www.basedash.com/">BaseDash</a></li>
<li><a href="https://seatable.io/en/">SeaTable</a></li>
<li><a href="https://www.causal.app/">Casual</a></li>
<li><a href="https://gridstudio.io/">Grid Studio</a></li>
<li><a href="https://patera.io/">Patera</a></li>
<li><a href="https://www.visor.us/">Visor</a></li>
<li><a href="https://airtable.com/">AirTable</a></li>
<li><a href="https://www.lido.app/">Lido</a></li>
</ul>
<h2 id="dead-products">Dead products</h2>
<p>The irony of some of these link names is not lost on me.</p>
<ul>
<li><a href="https://ethersheet.org/">https://ethersheet.org/</a></li>
<li><a href="http://getpermanent.com/">http://getpermanent.com/</a></li>
<li><a
href="https://stenci.la/stencila/blog/introducing-sheets/spreadsheets-are-dead-long-live-reactive-programming-environments-">https://stenci.la/stencila/blog/introducing-sheets/spreadsheets-are-dead-long-live-reactive-programming-environments-</a></li>
<li><a href="http://dtab.io/">http://dtab.io/</a></li>
<li><a href="https://www.herculus.io/">https://www.herculus.io/</a>
(Haskell spreadsheet)</li>
<li><a
href="https://www.resolversystems.com/">https://www.resolversystems.com/</a></li>
</ul>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2021-09-08 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Wed, 08 Sep 2021 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[The Movement Principle]]></title><link>https://chrisdone.com/posts/the-movement-principle</link><guid>https://chrisdone.com/posts/the-movement-principle</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>The Movement Principle</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>The Movement Principle</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>A language design principle I wanted to highlight in a page of its
own is what I’m calling the movement principle.</p>
<p>In particular, for statically-typed languages, type-classes are what
I have in mind for this post.</p>
<h2 id="type-classes">Type-classes</h2>
<p>We can write a piece of code like this:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>thing <span class="ot">=</span> <span class="ch">&#39;a&#39;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>example <span class="ot">=</span> <span class="fu">length</span> (<span class="fu">show</span> thing) <span class="op">*</span> <span class="dv">2</span> <span class="op">+</span> <span class="dv">7</span></span></code></pre></div>
<p>There’s a type for this <code>example</code> expression:
<code>Int</code></p>
<p>The language compiler infers that. Some observations:</p>
<ul>
<li>The operators <code>*</code> and <code>+</code> are generic
functions that will work on any numeric type.</li>
<li>The <code>length</code> function returns the length of a sequence as
a specific <code>Int</code> type.</li>
<li>The <code>show</code> function is a generic function that will show
a value as a string.</li>
</ul>
<p>Now I can perform a step to move this logic out of this function into
its own:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>thing <span class="ot">=</span> <span class="ch">&#39;a&#39;</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>example <span class="ot">=</span> work thing</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>work x <span class="ot">=</span> <span class="fu">length</span> (<span class="fu">show</span> x) <span class="op">*</span> <span class="dv">2</span> <span class="op">+</span> <span class="dv">7</span></span></code></pre></div>
<p>There’s a type for <code>work</code>, too:
<code>Show a =&gt; a -&gt; Int</code></p>
<p>The language compiler infers that too. That means: the input is
<code>a</code> and, by the way, it has a constraint that there’s an
instance of the class <code>Show</code> for that <code>a</code>, and the
output is <code>Int</code>.</p>
<p>We can do it again. Let’s move the arithmetic to its own
function:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>thing <span class="ot">=</span> <span class="ch">&#39;a&#39;</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>example <span class="ot">=</span> work thing</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>work x <span class="ot">=</span> arith (<span class="fu">length</span> (<span class="fu">show</span> x))</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>arith n <span class="ot">=</span> n <span class="op">*</span> <span class="dv">2</span> <span class="op">+</span> <span class="dv">7</span></span></code></pre></div>
<p>There’s a type for <code>arith</code>, too:
<code>Num a =&gt; a -&gt; a</code></p>
<p>The language compiler infers that too. As above, this means: input
and output is a type <code>a</code> that is an instance of
<code>Num</code> (numbers).</p>
<p>What’s going on here? The type system is saying: I don’t know which
instance to use for this function, so I’m going to make it someone
else’s problem and throw a constraint on the type. Job done.</p>
<p>This is what I’m calling “movement”. I can move my code freely and
there is still a type for the code and the compiler will accept it.</p>
<h2 id="type-directed-name-resolution">Type-directed name
resolution</h2>
<p>If we suppose that instead of type-classes we had type-directed name
resolution, such as seen in Idris, or C++ (function overloading), we run
into a problem at the first step. Consider an imaginary Haskell where
operator overloading is achieved via this mechanism instead of
type-classes:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ot">n ::</span> <span class="dt">Int</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>n <span class="ot">=</span> <span class="dv">1</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>example <span class="ot">=</span> n <span class="op">+</span> <span class="dv">5</span></span></code></pre></div>
<p>If we imagine that <code>+</code> is one of many functions called
<code>+</code>: one for <code>Int</code>, one for <code>Float</code>,
etc. and then the compiler picks which one you intended based on the
type, then it can see <code>n</code> is an <code>Int</code> and then
pick the right <code>+</code> which has type
<code>Int -&gt; Int -&gt; Int</code>.</p>
<p>However, if we try to abstract this:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ot">n ::</span> <span class="dt">Int</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>n <span class="ot">=</span> <span class="dv">1</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>example <span class="ot">=</span> oops n</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>oops x <span class="ot">=</span> x <span class="op">+</span> <span class="dv">5</span></span></code></pre></div>
<p>What is the type for <code>oops</code>? We can’t give one, because we
don’t know which <code>+</code> is intended. We don’t know what the type
of <code>x</code> will be. So this is a compile error. At this point
we’ve interrupted the programmer with an awkward problem.</p>
<p>This is a very leaky abstraction. I can’t even move code.</p>
<h2 id="exercise">Exercise</h2>
<p>Here’s an exercise. Try this in your statically-typed language of
choice. If you can use overloading of some kind in an expression, and
then abstract the generic part of it into its own function, then your
language’s overloading satisfies the movement principle.</p>
<h2 id="summary">Summary</h2>
<p>There are many factors that go into making a language let you move
code easily. One is making everything an expression, rather than
distinguishing between statements and expressions, for example. Another
is to avoid things like move semantics and ownership as seen in Rust,
which puts a lot of friction on moving code.<a href="#fn1"
class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></p>
<p>I think type-classes are overlooked in contributing to this quality
in a language. They enable generic programming, but in a way that
preserves the movement principle.</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>In Rust, the designers wanted this
property.<a href="#fnref1" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2021-04-10 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sat, 10 Apr 2021 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[What's wrong with ImplicitParams]]></title><link>https://chrisdone.com/posts/whats-wrong-with-implicitparams</link><guid>https://chrisdone.com/posts/whats-wrong-with-implicitparams</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>What’s wrong with ImplicitParams</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>What’s wrong with ImplicitParams</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Implicit parameters, enabled by the <code>ImplicitParams</code>
extension in GHC, often come up in Haskell discussions,<a href="#fn1"
class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a>
with the statement that they’re so convenient, yet nobody<a href="#fn2"
class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a>
seems to use them. Why is that?</p>
<p>The problem is incoherence. Type class resolution works in a very
binary way: either it finds one, singular instance with one behavior and
we compile, or it finds none at all and we don’t compile. It’s never<a
href="#fn3" class="footnote-ref" id="fnref3"
role="doc-noteref"><sup>3</sup></a> the case that changing our code will
<em>change</em> a resolved instance. I can change my import list, or
update my type-signatures.</p>
<p>Incoherence breaks this guarantee. Implicit parameters rely on
incoherence to work, because they piggyback on the type-class machinery
with magical instances that appear as needed.</p>
<p>Let’s see an example of how this leads to surprising results. The two
declarations below produce different results.</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> <span class="kw">let</span> <span class="op">?</span>myparam <span class="ot">=</span> <span class="dv">123</span> <span class="kw">in</span> terror</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>(<span class="dv">123</span>,<span class="dv">123</span>)</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> <span class="kw">let</span> <span class="op">?</span>myparam <span class="ot">=</span> <span class="dv">123</span> <span class="kw">in</span> horror</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>(<span class="dv">123</span>,<span class="dv">456</span>)</span></code></pre></div>
<p>Check out the code and find the reason why.</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE ImplicitParams #-}</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="ot">horror ::</span> (<span class="op">?</span><span class="ot">myparam ::</span> <span class="dt">Int</span>) <span class="ot">=&gt;</span> (<span class="dt">Int</span>, <span class="dt">Int</span>)</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>horror <span class="ot">=</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">let</span><span class="ot"> result ::</span> (<span class="op">?</span><span class="ot">myparam ::</span> <span class="dt">Int</span>) <span class="ot">=&gt;</span> <span class="dt">Int</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>      result <span class="ot">=</span> <span class="op">?</span>myparam</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>   <span class="kw">in</span> ( result</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>      , <span class="kw">let</span> <span class="op">?</span>myparam <span class="ot">=</span> <span class="dv">456</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>         <span class="kw">in</span> result)</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a><span class="ot">terror ::</span> (<span class="op">?</span><span class="ot">myparam ::</span> <span class="dt">Int</span>) <span class="ot">=&gt;</span> (<span class="dt">Int</span>, <span class="dt">Int</span>)</span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>terror <span class="ot">=</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">let</span><span class="ot"> result ::</span> <span class="dt">Int</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>      result <span class="ot">=</span> <span class="op">?</span>myparam</span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>   <span class="kw">in</span> ( result</span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>      , <span class="kw">let</span> <span class="op">?</span>myparam <span class="ot">=</span> <span class="dv">456</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>         <span class="kw">in</span> result)</span></code></pre></div>
<p>You found it; it’s that we added a type signature to
<code>result</code>. That changed the behavior! If you find this
surprising, it’s because you’re used to coherence. In normal Haskell, an
inferred type and an explicit type don’t produce different code.</p>
<p>Here’s another, more insidious, way to evoke the problem:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE ImplicitParams, NoMonomorphismRestriction #-}</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="ot">terror ::</span> (<span class="op">?</span><span class="ot">myparam ::</span> <span class="dt">Int</span>) <span class="ot">=&gt;</span> (<span class="dt">Int</span>, <span class="dt">Int</span>)</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>terror <span class="ot">=</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">let</span> result <span class="ot">=</span> <span class="op">?</span>myparam</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>   <span class="kw">in</span> ( result</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>      , <span class="kw">let</span> <span class="op">?</span>myparam <span class="ot">=</span> <span class="dv">456</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>         <span class="kw">in</span> result)</span></code></pre></div>
<p>Try removing <code>NoMonomorphismRestriction</code>. The output is
different depending on whether this extension is on or not. <strong>Be
afraid, be very afraid.</strong></p>
<p>If this constraint was <code>Show</code>, I wouldn’t be able to
reproduce this difference, because there’s only one
<code>Show Int</code> instance.</p>
<p>Implicit parameters break fundamental expectations about one of
Haskell’s most basic features: its type inference. For me, this is
reason enough to avoid it.</p>
<hr />
<p>Thanks Andrew Martin for insightful discussion on this topic a few
years ago.</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Such as this blog post <a
href="https://hugopeters.me/posts/10/">Who still uses ReaderT</a> by
Hugo Peters.<a href="#fnref1" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p>People do use them, see e.g. <a
href="https://old.reddit.com/r/haskell/comments/m8o88a/who_still_uses_readert/grkh17q/">Ed
Kmett</a>, with caveats.<a href="#fnref2" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn3" role="doc-endnote"><p>Orphan instances change this
guarantee, which is why they’re maligned.<a href="#fnref3"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2021-03-20 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sat, 20 Mar 2021 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[How exactly ExceptT differs to EarlyDo]]></title><link>https://chrisdone.com/posts/exceptt-vs-early-do</link><guid>https://chrisdone.com/posts/exceptt-vs-early-do</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>How exactly ExceptT differs to EarlyDo</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>How exactly ExceptT differs to EarlyDo</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>After publishing my <a
href="https://github.com/inflex-io/early">early</a> GHC plugin, I saw a
lot of response from people saying “Why not <code>ExceptT</code>?”,
despite having outlined it in the README of the project. After reading
some sincere responses failing to see why I bothered with this at all,
it seems I haven’t explained myself well.</p>
<p>I’m happy for people to just disagree because they have different
values, but I want to make sure we’re talking about the same
trade-offs.</p>
<p>I think people need to see real code to see why I think this is a
substantial improvement. You’ll have to use your imagination generously
to raise the contrived to the “real world”.</p>
<p>(I’m calling this plugin <code>EarlyDo</code> so I can talk
specifically about the syntax extension.)</p>
<h1 id="setup">Setup</h1>
<p>Here is a module of three functions (but use your imagination to make
a couple dozen), where the IO actions return
<code>Either failure a</code>. The proposal I have been repeatedly given
is to use <code>ExceptT</code>. I’m typically using RIO, so I define a
fake one, and then use a real one later.</p>
<h1 id="basic-exceptt">Basic ExceptT</h1>
<p>To do concurrency or exception handling or any with-like thing, you
need the equivalent of <code>MonadUnliftIO</code> to capture the current
context, and then re-run the monad further in the new thread. Here we do
it manually to demonstrate what’s happening.</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Concurrent.Async</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Monad.Trans.Except</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Monad.Trans.Reader</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Monad.Trans</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">RIO</span> r a <span class="ot">=</span> <span class="dt">ReaderT</span> r <span class="dt">IO</span> a</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="ot">foo ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">RIO</span> () (<span class="dt">Either</span> () ())</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>foo i <span class="ot">=</span> runExceptT <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>  _ <span class="ot">&lt;-</span> <span class="dt">ExceptT</span> <span class="op">$</span> bar (i <span class="op">+</span> <span class="dv">1</span>)</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>  <span class="dt">ExceptT</span> <span class="op">$</span> zot (i <span class="op">+</span> <span class="dv">2</span>)</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a><span class="ot">bar ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">RIO</span> () (<span class="dt">Either</span> () ((), ()))</span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>bar i <span class="ot">=</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>  runExceptT <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>    <span class="dt">ExceptT</span> <span class="op">$</span> zot <span class="dv">0</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>    r <span class="ot">&lt;-</span> <span class="dt">ExceptT</span> <span class="op">$</span> <span class="fu">fmap</span> <span class="dt">Right</span> ask</span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>    (x, y) <span class="ot">&lt;-</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>      <span class="dt">ExceptT</span> <span class="op">$</span> lift <span class="op">$</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>      <span class="fu">fmap</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>        (\(x, y) <span class="ot">-&gt;</span> (,) <span class="op">&lt;$&gt;</span> x <span class="op">&lt;*&gt;</span> y)</span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>        (concurrently</span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>         (<span class="fu">flip</span> runReaderT r <span class="op">$</span> foo (i <span class="op">+</span> <span class="dv">1</span>))</span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>         (<span class="fu">flip</span> runReaderT r <span class="op">$</span> zot (i <span class="op">+</span> <span class="dv">2</span>)))</span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a>    <span class="fu">pure</span> (x, y)</span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a><span class="ot">zot ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">RIO</span> () (<span class="dt">Either</span> () ())</span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a>zot i <span class="ot">=</span> runExceptT <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a>  _ <span class="ot">&lt;-</span> <span class="dt">ExceptT</span> <span class="op">$</span> bar (i <span class="op">+</span> <span class="dv">1</span>)</span>
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a>  <span class="dt">ExceptT</span> <span class="op">$</span> zot (i <span class="op">+</span> <span class="dv">2</span>)</span></code></pre></div>
<p>(Why am I not using <code>ExceptT () (RIO ()) ..</code> in my type
signatures? Continue reading to the end.)</p>
<h1 id="using-monadunliftio">Using MonadUnliftIO</h1>
<p>Here’s a version using <code>MonadUnliftIO</code>. Not that the work
of unlifting has been done for me.</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span>           <span class="dt">Control.Monad.Trans.Except</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span>           <span class="dt">RIO</span> (<span class="dt">RIO</span>)</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span>           <span class="dt">UnliftIO</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="ot">foo ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">RIO</span> () (<span class="dt">Either</span> () ())</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>foo i <span class="ot">=</span> runExceptT <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>  _ <span class="ot">&lt;-</span> <span class="dt">ExceptT</span> <span class="op">$</span> bar (i <span class="op">+</span> <span class="dv">1</span>)</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>  <span class="dt">ExceptT</span> <span class="op">$</span> zot (i <span class="op">+</span> <span class="dv">2</span>)</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a><span class="ot">bar ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">RIO</span> () (<span class="dt">Either</span> () ((), ()))</span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>bar i <span class="ot">=</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>  runExceptT <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>    <span class="dt">ExceptT</span> <span class="op">$</span> zot <span class="dv">0</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>    (x, y) <span class="ot">&lt;-</span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>      <span class="dt">ExceptT</span> <span class="op">$</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>      <span class="fu">fmap</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a>        (\(x, y) <span class="ot">-&gt;</span> (,) <span class="op">&lt;$&gt;</span> x <span class="op">&lt;*&gt;</span> y)</span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a>        (concurrently</span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a>         (foo (i <span class="op">+</span> <span class="dv">1</span>))</span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a>         (zot (i <span class="op">+</span> <span class="dv">2</span>)))</span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a>    <span class="fu">pure</span> (x, y)</span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a><span class="ot">zot ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">RIO</span> () (<span class="dt">Either</span> () ())</span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a>zot i <span class="ot">=</span> runExceptT <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a>  _ <span class="ot">&lt;-</span> <span class="dt">ExceptT</span> <span class="op">$</span> bar (i <span class="op">+</span> <span class="dv">1</span>)</span>
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a>  <span class="dt">ExceptT</span> <span class="op">$</span> zot (i <span class="op">+</span> <span class="dv">2</span>)</span></code></pre></div>
<h1 id="evaluating-cost-and-ergonomics">Evaluating cost and
ergonomics</h1>
<p>What remains is the <code>runExceptT</code> and <code>ExceptT</code>
calls which cannot be eliminated. Here we are unsatisfied, because all
the functions in our module are using this “pattern”. A pattern is what
we call repeating yourself because your language can’t abstract it for
you. We pay an <code>O(1)</code> cost per definition, and an
<code>O(n)</code> cost for calls per definition.</p>
<p>Additionally, any <code>traverse</code> call that is just
<code>MonadIO m =&gt; ..</code> in the middle of the function, or
logging function, will also run in <code>ExceptT</code>, causing a
performance penalty that we didn’t want. If we want to avoid that
penalty, we must use <code>lift</code>. But I haven’t benchmarked this.
You are welcome to do so.</p>
<p>You pay to short-circuit and you pay to do normal actions in the base
monad, and if you’re not careful you <em>may</em> accidentally pay
extra.</p>
<p>Given that pretty much all of my apps have monads that look something
like this, this seemed worth improving.<a href="#fn1"
class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></p>
<h1 id="earlydo">EarlyDo</h1>
<p>With <code>EarlyDo</code>, we have:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# OPTIONS -F -pgmF=early #-}</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Early</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">RIO</span> (<span class="dt">RIO</span>)</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">UnliftIO</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="ot">foo ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">RIO</span> () (<span class="dt">Either</span> () ())</span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>foo i <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a> _ <span class="ot">&lt;-</span> bar (i <span class="op">+</span> <span class="dv">1</span>)<span class="op">?</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a> zot (i <span class="op">+</span> <span class="dv">2</span>)</span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a><span class="ot">bar ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">RIO</span> () (<span class="dt">Either</span> () ((), ()))</span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>bar i <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>  zot <span class="dv">0</span><span class="op">?</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>  (x, y) <span class="ot">&lt;-</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>    <span class="fu">fmap</span> (\(x, y) <span class="ot">-&gt;</span> (,) <span class="op">&lt;$&gt;</span> x <span class="op">&lt;*&gt;</span> y) (concurrently (foo (i <span class="op">+</span> <span class="dv">1</span>)) (zot (i <span class="op">+</span> <span class="dv">2</span>)))<span class="op">?</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>  <span class="fu">pure</span> (<span class="dt">Right</span> (x, y))</span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a><span class="ot">zot ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">RIO</span> () (<span class="dt">Either</span> () ())</span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true" tabindex="-1"></a>zot i <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true" tabindex="-1"></a>  _ <span class="ot">&lt;-</span> bar (i <span class="op">+</span> <span class="dv">1</span>)<span class="op">?</span></span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true" tabindex="-1"></a>  zot (i <span class="op">+</span> <span class="dv">2</span>)</span></code></pre></div>
<p>A single character that appears in a not-normally-valid syntax
position signals short-circuiting. Any base monad action like
<code>mapRIO</code> (runs in <code>RIO r</code>) can be used without
lifting or unlifting. I have to explicitly produce <code>Right</code> in
<code>bar</code>, which is a cost, but not in
<code>zot</code>/<code>foo</code>.</p>
<h1 id="using-our-own-monad-type">Using our own monad type</h1>
<p>Finally, we can use our own wrapper monad:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# OPTIONS -F -pgmF=early #-}</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE GeneralizedNewtypeDeriving #-}</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Early</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">RIO</span> (<span class="dt">RIO</span>)</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">UnliftIO</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">AppEnv</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">App</span> a <span class="ot">=</span> <span class="dt">App</span> {<span class="ot"> runApp ::</span> <span class="dt">RIO</span> <span class="dt">AppEnv</span> a} <span class="kw">deriving</span> (<span class="dt">Functor</span>, <span class="dt">Applicative</span>, <span class="dt">Monad</span>, <span class="dt">MonadIO</span>)</span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">MonadUnliftIO</span> <span class="dt">App</span> <span class="kw">where</span> withRunInIO <span class="ot">=</span> wrappedWithRunInIO <span class="dt">App</span> runApp</span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a><span class="ot">foo ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">App</span> (<span class="dt">Either</span> () ())</span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>foo i <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>  _ <span class="ot">&lt;-</span> bar (i <span class="op">+</span> <span class="dv">1</span>)<span class="op">?</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>  zot (i <span class="op">+</span> <span class="dv">2</span>)</span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a><span class="ot">bar ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">App</span> (<span class="dt">Either</span> () ((), ()))</span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a>bar i <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a>  zot <span class="dv">0</span><span class="op">?</span></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a>  (x, y) <span class="ot">&lt;-</span></span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true" tabindex="-1"></a>    <span class="fu">fmap</span> (\(x, y) <span class="ot">-&gt;</span> (,) <span class="op">&lt;$&gt;</span> x <span class="op">&lt;*&gt;</span> y) (concurrently (foo (i <span class="op">+</span> <span class="dv">1</span>)) (zot (i <span class="op">+</span> <span class="dv">2</span>)))<span class="op">?</span></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true" tabindex="-1"></a>  <span class="fu">pure</span> (<span class="dt">Right</span> (x, y))</span>
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-23"><a href="#cb4-23" aria-hidden="true" tabindex="-1"></a><span class="ot">zot ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">App</span> (<span class="dt">Either</span> () ())</span>
<span id="cb4-24"><a href="#cb4-24" aria-hidden="true" tabindex="-1"></a>zot i <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb4-25"><a href="#cb4-25" aria-hidden="true" tabindex="-1"></a>  _ <span class="ot">&lt;-</span> bar (i <span class="op">+</span> <span class="dv">1</span>)<span class="op">?</span></span>
<span id="cb4-26"><a href="#cb4-26" aria-hidden="true" tabindex="-1"></a>  zot (i <span class="op">+</span> <span class="dv">2</span>)</span></code></pre></div>
<p>The <code>App</code> monad has the full power of all the previously
mentioned things.</p>
<p>But not with <code>ExceptT</code>. I <strong>cannot put
<code>ExceptT</code> in this monad stack and retain the
<code>MonadUnliftIO</code> instance.</strong> It has no valid
instance!</p>
<h1 id="but-you-should-still-use-exceptt-because-i-like-it">But you
should still use ExceptT because I like it</h1>
<p>Could the mechanics of this syntax use <code>ExceptT</code>
underneath? Sure, but then the whole do block would be under
<code>ExceptT</code>, and I’d have to lift the rest of the do notation
too (even if it’s not necessary, incurring extra cost for no reason).
Even if I could tell which statements should be <code>ExceptT</code>’d
or <code>lift</code>’d, it would be overkill.</p>
<p>At this level, it doesn’t matter much. All you need the syntax to
produce is a case expression. The use of an <code>Early</code> class is
unneccessary, it just makes it easy to use either <code>Maybe</code> or
<code>Either</code> with the same syntax.</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>If your answer is “just define really
short names for <code>runExceptT</code> and <code>ExceptT</code> and
<code>lift</code>”, perhaps you could go back to using
<code>&gt;&gt;=</code> and <code>&gt;&gt;</code> instead of
<code>do</code>, and <a
href="https://www.microsoft.com/en-us/research/wp-content/uploads/2016/08/desugaring-haskell-haskell16.pdf?from=http%3A%2F%2Fresearch.microsoft.com%2Fen-us%2Fum%2Fpeople%2Fsimonpj%2Fpapers%2Flist-comp%2Fapplicativedo.pdf"><code>ApplicativeDo</code></a>,
and <a
href="https://ocharles.org.uk/posts/2014-12-09-recursive-do.html"><code>RecursiveDo</code></a>,
and <a
href="https://ocharles.org.uk/guest-posts/2014-12-21-arrows.html"><code>Arrows</code></a>,
and report your experience.</p>
<p>I’ve never once used <code>Arrow</code> and I’ve used
<code>RecursiveDo</code> as a novelty, but <code>mfix</code> was
sufficient in the end. <code>ApplicativeDo</code> is a brittle
extension, but that doesn’t stop me from using it.<a href="#fnref1"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2021-01-05 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Tue, 05 Jan 2021 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Haskell doesn't have macros]]></title><link>https://chrisdone.com/posts/haskell-doesnt-have-macros</link><guid>https://chrisdone.com/posts/haskell-doesnt-have-macros</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Haskell doesn’t have macros</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Haskell doesn’t have macros</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>I wanted to underscore a specific point about Haskell’s
metaprogramming capabilities. It doesn’t have a macro system, the kind
that Lispers love. It has metaprogramming, yes. But not the kind that’s
useful in the same way.</p>
<h2 id="what-macros-are">What macros are</h2>
<p>In Lisp, macros are:</p>
<ol type="1">
<li>Syntactically light-weight.</li>
<li>Don’t require writing a parser to deal with the language’s native
syntax.</li>
<li>They work on trees of lexical tokens of the language; <em>not</em>
abstract syntax trees. At best, they are incomplete ASTs.</li>
</ol>
<p>Macros are functions that take in this tree of tokens, either atomic
lexical tokens, or lists denoted by balanced parentheses, and do some
transforms, and return the same as output.</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode lisp"><code class="sourceCode commonlisp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>foo</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;bar&quot;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="dv">123</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>(foo <span class="st">&quot;bar&quot;</span> (<span class="dv">123</span>) <span class="kw">nil</span> (blob x))</span></code></pre></div>
<h2 id="quoting-in-lisp-vs-haskell">Quoting in Lisp vs Haskell</h2>
<p>In Haskell, we have GHC’s Template Haskell. What that provides
is:</p>
<ol type="1">
<li>Splices: <code>$(foo)</code> – this syntax means: run the code
<code>foo</code>, in the <code>Q</code> monad, at compile time, and it
should produce a valid Haskell abstract syntax tree.</li>
<li>Quotation: <code>[|bar|]</code> – this means: produce an action in
the <code>Q</code> monad which will produce the abstract syntax tree for
the code <code>bar</code>.</li>
<li>Quasiquotation: <code>[zot|anything|]</code> – this means: the
<code>zot</code> is a parser that will parse the string contents
<code>anything</code> and produce an abstract syntax tree in the
<code>Q</code> monad.</li>
</ol>
<p>This code is ran at compile-time. That’s different to Lisp.</p>
<p>In Lisp, e.g. Common Lisp, we have:</p>
<ol type="1">
<li>Splices: <code>,foo</code> – run the code to produce a tree.</li>
<li>Quotation: <code>'bar</code> or <code>'(bar abc)</code> – quote the
code, that’s all.</li>
<li>Quasiquotation: <code>`bar</code> or <code>`(bar ,foo)</code> – this
is like a regular quotation, but I can place <code>,</code> anywhere to
mean “run this code”.</li>
</ol>
<p>The code runs at <strong>runtime</strong> at this point, not
compile-time yet.<a href="#fn1" class="footnote-ref" id="fnref1"
role="doc-noteref"><sup>1</sup></a></p>
<h2 id="macros">Macros</h2>
<p>To have macros run at compile-time, Common Lisp specifically has
<code>defmacro</code> to define a macro. Here’s an example of the famous
<em>anaphoric if</em>. It’s a short-hand for let-binding followed by an
immediate if, testing that the value is “true-ish” (non-nil), and makes
whatever it is available as <code>it</code> in the if:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode lisp"><code class="sourceCode commonlisp"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>(<span class="kw">defmacro</span><span class="fu"> aif </span>(test-form then-form else-form)</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  `(<span class="kw">let</span> ((it ,test-form))</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    (<span class="kw">if</span> it ,then-form ,else-form)))</span></code></pre></div>
<p>You use it like this:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode lisp"><code class="sourceCode commonlisp"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>(aif (calculate-something) (use it) (do-something-else))</span></code></pre></div>
<p>Here’s how we implement the same thing in Template Haskell:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>aif testForm thenForm elseForm <span class="ot">=</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>  [<span class="op">|</span> <span class="kw">let</span> it <span class="ot">=</span> <span class="op">$</span>testForm</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>     <span class="kw">in</span> <span class="kw">if</span> it</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>     <span class="kw">then</span> <span class="op">$</span>thenForm</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>     <span class="kw">else</span> <span class="op">$</span>elseForm</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">|</span>]</span></code></pre></div>
<p>So far so good, apart from the fact no one would write this macro in
Haskell.<a href="#fn2" class="footnote-ref" id="fnref2"
role="doc-noteref"><sup>2</sup></a> Here’s how we use it:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="op">$</span>(aif [<span class="op">|</span>calculate something<span class="op">|</span>] [<span class="op">|</span>use it<span class="op">|</span>] [<span class="op">|</span>something other<span class="op">|</span>])</span></code></pre></div>
<p>Oh no! I have to manually quote every argument myself! The quotation
syntax isn’t even short, I have to write <code>[| .. |]</code> around
everything. No one will use your macros if they are like that.</p>
<h2 id="quasiquotes-dont-solve-the-problem">Quasiquotes don’t solve the
problem</h2>
<p>Haskell has what it calls “quasiquotes” which are like Lisp’s reader
macros: You can parse an arbitrary string and produce an AST for the
compiler. They’re actually great for embedding other languages into
Haskell like JSON, YAML, HTML, etc.</p>
<p>Maybe that could make writing this easy? Perhaps something like:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>[aif|calculate something; use it; something other|]</span></code></pre></div>
<p>On the surface this looks like we’re there. But we’re not, because
remember that Haskell’s metaprogramming requires you to produce an AST.
The type <code>Exp</code> forms the abstract syntax tree and looks like
this:</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Exp</span> <span class="ot">=</span> <span class="dt">VarE</span> <span class="dt">Name</span> <span class="op">|</span> <span class="dt">ConE</span> <span class="dt">Name</span> <span class="op">|</span> <span class="dt">LitE</span> <span class="dt">Lit</span> <span class="op">|</span> <span class="dt">AppE</span> <span class="dt">Exp</span> <span class="dt">Exp</span> <span class="op">|</span> <span class="dt">AppTypeE</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Exp</span> <span class="dt">Type</span> <span class="op">|</span> <span class="op">...</span></span></code></pre></div>
<p>So you can’t go from the string above into the compiler without
converting to an AST. <strong>You need a parse step</strong>.</p>
<p>Fine, let’s just import GHC’s own parser to produce the AST. Surely
that’s possible? Sadly, not. GHC’s own API parser has a completely
different tree type to the one in Template Haskell.<a href="#fn3"
class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a>
This is where we get stuck.</p>
<p>Implementing such a translation might be the way to salvage
quasi-quote syntax into a macro system. It might be a little slow,
though. It’d need long-term maintenance.</p>
<p>Quasiquotes in GHC optimise a different use-case to macros: they let
you deal with <em>foreign</em> languages. Macros let you add slight
enhancements to your <em>existing</em> language.</p>
<h2 id="a-quick-fix">A quick fix</h2>
<p>A quick fix to at least let us get at the parse tree would be to have
some special syntax, e.g. to make something up completely<a href="#fn4"
class="footnote-ref" id="fnref4"
role="doc-noteref"><sup>4</sup></a>:</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>aif<span class="op">!</span>(<span class="kw">if</span> calculate something <span class="kw">then</span> use it <span class="kw">else</span> something other)</span></code></pre></div>
<p>Could produce:</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="op">$</span>(aif [<span class="op">|</span> <span class="kw">if</span> calculate something <span class="kw">then</span> use it <span class="kw">else</span> something other <span class="op">|</span>])</span></code></pre></div>
<p>The limitation here is that the input to the macro has to parse
correctly into an AST. You can’t have the branches of the
<code>if</code> separately from the <code>if</code> itself.</p>
<p>The surface syntax of Lisp (token trees), used by the macro system,
is a superset of the core syntax of Lisp (let/setf/cond/progn, etc.).
Unfortunately, the surface syntax of Haskell (used by the
metaprogramming) is exactly the core syntax:</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> <span class="op">:</span>t <span class="op">$</span>(lamE [varP (mkName <span class="st">&quot;x&quot;</span>)] (varE (mkName <span class="st">&quot;x&quot;</span>)))</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>interactive<span class="op">&gt;:</span><span class="dv">1</span><span class="op">:</span><span class="dv">3</span><span class="op">-</span><span class="dv">46</span><span class="op">:</span> <span class="dt">Splicing</span> expression lamE [varP (mkName <span class="st">&quot;x&quot;</span>)] (varE (mkName <span class="st">&quot;x&quot;</span>))</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="op">======&gt;</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>\ x <span class="ot">-&gt;</span> x</span></code></pre></div>
<p>This is how you have to construct the AST in Haskell: it has to be of
the right schema immediately, there’s no way to produce a “loose tree of
tokens” that TH will consume for you.</p>
<p>Additionally, quotation demands correct syntax too:
<code>[| let |]</code> is a syntax error. What if I wanted to define my
own variation on let? Too bad.</p>
<p>This would encourage strange warping and re-using of existing syntax
to achieve what you want. I don’t think this is a good idea on the
whole.</p>
<p>Therefore, we either have to fit our macros into existing syntax (as
above), or parse strings (quasiquotes). We need the middle ground that
Lisp offers.</p>
<h2 id="an-ideal-design">An ideal design</h2>
<p>Going back to the original definition of macros, we had:</p>
<ol type="1">
<li>Syntactically light-weight.</li>
<li>Don’t require writing a parser to deal with the language’s native
syntax.</li>
<li>They work on trees of lexical tokens of the language; <em>not</em>
abstract syntax trees.</li>
</ol>
<p>Let’s explore this in Haskell. If we had this, it might look
like:</p>
<div class="sourceCode" id="cb11"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>aif<span class="op">!</span>(calculate something; use it; something other)</span></code></pre></div>
<p>This is light-weight. It doesn’t require a parser. We could receive
the lexical tokens as:</p>
<div class="sourceCode" id="cb12"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>calculate  something  ;  use  it  ;  something  other</span></code></pre></div>
<p>The only special addendum would be that bracketing syntax be balanced
into a tree, so: <code>() {} []</code>.<a href="#fn5"
class="footnote-ref" id="fnref5" role="doc-noteref"><sup>5</sup></a>
Just like in Lisp. Finally, the Template Haskell API would provide a
trivial way to go from a token tree to an abstract syntax tree:
<code>[if,x,then,y,else,z]</code> into <code>CondE ...</code></p>
<h2 id="motivating-examples">Motivating examples</h2>
<p>So the following constructs would be fine:</p>
<div class="sourceCode" id="cb13"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a>nat<span class="op">!</span><span class="dv">1</span>      <span class="co">-- natural number.</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>ne<span class="op">!</span>[<span class="dv">1</span>,<span class="dv">2</span>,<span class="dv">3</span>] <span class="co">-- non-empty list.</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>sha1<span class="op">!</span>cf23df2207d99a74fbe169e3eba035e633b65d94 <span class="co">-- compile-time validated sha1</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>email<span class="op">!</span><span class="st">&quot;chrisdone@gmail.com&quot;</span> <span class="co">-- compile-time validated email</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>set<span class="op">!</span>{<span class="dv">1</span> <span class="dv">2</span> <span class="dv">3</span> c <span class="dv">4</span>}</span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>vec<span class="op">!</span>[ <span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span> ] <span class="co">-- vector type</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a><span class="fu">map</span><span class="op">!</span>{ x<span class="op">:</span> <span class="dv">1</span>, y<span class="op">:</span> <span class="dv">2</span>, z<span class="op">:</span> <span class="dv">3</span> } <span class="co">-- easier-to-read compile-time constructed map</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>ado<span class="op">!</span>(x <span class="ot">&lt;-</span> y</span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>     y <span class="ot">&lt;-</span> z</span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>     x)  <span class="co">-- applicative or qualified do could have been macros</span></span></code></pre></div>
<p>(If you don’t find those examples enticing there’s no hope for
you.)</p>
<p>As it happens, Rust’s macros work just like this. Lisp’s do. Haskell
could potentially have this. It depends whether the community wants it,
and/or whether someone is willing to implement a patch for GHC and lobby
for it. But it seemed worth pointing out.</p>
<hr />
<p>Thanks <a href="https://www.jonis.lv/">Jānis ǅeriņš</a> and <a
href="http://lisperator.net/">Mihai Bazon</a> for reviewing this
post.</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>They’re also syntactic sugar for
<code>QUOTE</code>, <code>UNQUOTE</code>, and <code>QUASIQUOTE</code>.
The latter can be implemented with macros.<a href="#fnref1"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p>No one would write this because
Haskell doesn’t have “true-ish-ness” or implicit null, so this would
simply produce a type error. But we’re going with a very typical
example.<a href="#fnref2" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn3" role="doc-endnote"><p>Feel like writing that translation?
Haskell’s surface syntax is big; be my guest. See Nikita Volkov’s famous
<a href="http://nikita-volkov.github.io/record/">records library
post</a> for an example of where this bites:</p>
<blockquote>
<p>Unfortunately since the introduced syntax is not supported by
“haskell-src-exts” and since neither does that library expose a parser
API, Haskell syntax parsing needs to be reimplemented in the “record”
library. This is not a trivial task, so currently the quasi-quoters do
not support all of the Haskell syntax. All the basic stuff is supported
however: variables, literals, tuple and list syntax. Don’t worry though,
if you’ll try to use something unsupported, you’ll get notified during
compilation.</p>
</blockquote>
<a href="#fnref3" class="footnote-back" role="doc-backlink">↩︎</a></li>
<li id="fn4" role="doc-endnote"><p>Actually, this is very similar to
Rust syntax.<a href="#fnref4" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn5" role="doc-endnote"><p>An open question would be whether you
would include whitespace-aligned lines as “these are a list of trees”,
to support Haskell’s indentation-sensitive syntax. Personally, I never
liked that part of Haskell. But it’s a real consideration, it’s how
people code in reality. Infix operators are another consideration: you
may want to resolve their precedence, or not. If you want <code>*</code>
in prefix/postfix position, then balancing shouldn’t get in your way.<a
href="#fnref5" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2020-12-29 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Tue, 29 Dec 2020 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Is it Try.do that is dangerous?]]></title><link>https://chrisdone.com/posts/is-try-do-dangerous</link><guid>https://chrisdone.com/posts/is-try-do-dangerous</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Is it Try.do that is dangerous?</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Is it Try.do that is dangerous?</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>I wrote the post <a href="https://chrisdone.com/posts/try-do/">Try.do
for recoverable errors in Haskell</a> and someone has written <a
href="https://github.com/effectfully/sketches/blob/d45c3ec127e8789ab1af657f911c1a2a070d3780/try-do-is-dangerous/README.md">a
nice response post</a> proposing that this pattern is actually
dangerous. While reading it I wrote up some of my own notes to share in
reply.</p>
<p>I’d like to preface with the fact that I’m grateful for discussion
and criticism of this approach. I’d like to use this approach, but if
someone finds genuine issues with it, then I’ll naturally have to look
elsewhere.</p>
<h2 id="loss-of-code-re-use">Loss of code re-use</h2>
<p>The first point made, and I think this is a solid point, is that you
can’t re-use handy monadic functions like <code>traverse</code> or
<code>forever</code> with this syntax. That’s a downer.</p>
<p>However, I think it also follows naturally. If <code>ExceptT</code>
were easily a clean <code>MonadUnliftIO</code> instance, then we would
have a clean interpretation of how such functions would behave under all
the circumstances that unliftio is applicable in, most importantly
threading and when IO appears in negative position (<code>withX</code>).
As it happens, we don’t.</p>
<p>This also applies to free monads, by the way. When you run the monad,
you still have to decide on an interpretation, figure out how things
will interact, and the idea of doing so does not bring me
confidence.</p>
<p>Indeed, I may want to decide on a case-by-case basis whether
<code>traverse</code> should optimistically run <em>all</em> actions (<a
href="https://hackage.haskell.org/package/unliftio-0.2.13.1/docs/UnliftIO-Async.html#v:pooledMapConcurrentlyN">even
concurrently</a>; which I’m doing in my compiler), only at the end
checking all results, or whether it should fail hard on the
<em>first</em> failing action. Happily, the
<code>pooledMapConcurrentlyN</code> function doesn’t have to know or
care about how I do error handling.</p>
<p>In conclusion, I don’t see this as a complete obvious loss, and in
some way it’s also a gain. I think there might be some interesting ideas
to explore in this area.</p>
<h2 id="lifting-hides-results">Lifting hides results</h2>
<p>The second point, in my reading, was that with this syntax, a
programmer will get into the habit of lifting all actions that aren’t
returning <code>Either E A</code>. The downside being that if you use a
function like <code>timeout</code>, like this:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>result <span class="ot">&lt;-</span> timeout (<span class="ot">someAction ::</span> <span class="dt">IO</span> (<span class="dt">Either</span> <span class="dt">E</span> <span class="dt">A</span>))</span></code></pre></div>
<p>Then you’ll hit a type error,</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>• <span class="dt">Couldn&#39;t</span> match <span class="kw">type</span><span class="op">:</span> <span class="dt">Maybe</span> (<span class="dt">Either</span> <span class="dt">ErrorType</span> <span class="dt">Int</span>)</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>                 with<span class="op">:</span> <span class="dt">Either</span> e0 b0</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>• <span class="dt">In</span> a stmt <span class="kw">of</span> a qualified &#39;do&#39; block<span class="op">:</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    result <span class="ot">&lt;-</span> timeout <span class="dv">1000</span> action1</span></code></pre></div>
<p>So, being in a rush, they ignore the code and just add an
<code>fmap pure</code> call to fix the error:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>result <span class="ot">&lt;-</span> <span class="fu">fmap</span> <span class="fu">pure</span> (timeout <span class="dv">1000</span> action1)</span></code></pre></div>
<p>Now we’ve lost the error, it didn’t short-circuit where it should
have! Actually, <strong>we haven’t lose the error</strong>. In fact, we
<em>haven’t finished writing the code</em> at this point. Assuming we
have compiler warnings on, we’ll be <strong>told that
<code>result</code> is unused</strong>.</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>Main.hs<span class="op">:</span><span class="dv">10</span><span class="op">:</span><span class="dv">7</span><span class="op">:</span> warning<span class="op">:</span> [<span class="op">-</span><span class="dt">Wunused</span><span class="op">-</span>matches]</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Defined</span> but <span class="fu">not</span> used<span class="op">:</span> ‘result’</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>   <span class="op">|</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="dv">10</span> <span class="op">|</span>       result <span class="ot">&lt;-</span> <span class="fu">fmap</span> <span class="fu">pure</span> (timeout <span class="dv">1000</span> action1)</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>   <span class="op">|</span>       <span class="op">^^^^^^</span></span></code></pre></div>
<p>Furthermore, when we decide to use it, we’ll see that its type is</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Maybe</span> (<span class="dt">Either</span> <span class="dt">ErrorType</span> <span class="dt">Int</span>)</span></code></pre></div>
<p>The error is still here, we have to <em>do something</em> with it.
You can’t use it without having to deal with the error in some way. I
think if the compiler tells you something and you ignore it, that’s your
responsibility. It can’t save you from yourself.</p>
<p>This is the first instance of a running theme in the post that I’m
replying to, which is that code that doesn’t use results is
dangerous.</p>
<h2 id="the-try-function">The <code>try</code> function</h2>
<p>The next case considered was <code>try</code>, which has this
type:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="ot">try ::</span> <span class="dt">Exception</span> e <span class="ot">=&gt;</span> <span class="dt">IO</span> a <span class="ot">-&gt;</span> <span class="dt">IO</span> (<span class="dt">Either</span> e a)</span></code></pre></div>
<p>And what would happen if you wrote:</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>result <span class="ot">&lt;-</span> try (<span class="ot">someAction ::</span> <span class="dt">IO</span> (<span class="dt">Either</span> <span class="dt">E</span> <span class="dt">A</span>))</span></code></pre></div>
<p>So that the type would be:</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>result <span class="ot">&lt;-</span> try (<span class="ot">someAction ::</span> <span class="dt">IO</span> (<span class="dt">Either</span> <span class="dt">E</span> <span class="dt">A</span>))<span class="ot"> ::</span> <span class="dt">IO</span> (<span class="dt">Either</span> <span class="dt">E</span> (<span class="dt">Either</span> <span class="dt">E</span> <span class="dt">A</span>))</span></code></pre></div>
<p>The author claims that you won’t get a type error if you do something
with the result. Let’s study it:</p>
<ol type="1">
<li><code>try</code> will catch exceptions thrown by the GHC exception
mechanism.</li>
<li>It will catch only those exceptions that are an instance of
<code>Exception</code>.</li>
<li>It will be reported back to the user in the <code>Left</code> case
of the either.</li>
</ol>
<p>In this example:</p>
<ul>
<li>This assumes that one would make their failure result type
<code>E</code> an instance of <code>Exception</code>. <strong>I don’t
think there would be a good reason to do that.</strong> But let’s
continue with this assumption.</li>
<li>If, further, you actually use the <code>throw</code> call from
<code>base</code> to throw your result type (<strong>again, why would
you?</strong>), then <code>try</code> will catch it. So it wasn’t
lost.</li>
<li>If the function simply returns the failure type, then you have
it.</li>
<li>Finally, my point above about the <code>result</code> variable
stands here; it has to be used somewhere.</li>
</ul>
<p>But I believe that this example is contrived. The whole point of the
<code>Try.do</code> system is to avoid using the <code>base</code>
exception system for our business logic. Why, then, would we implement
an instance of <code>Exception</code> and then willingly
<code>throw</code> our failure type? Finally, the code doesn’t lose any
errors. In fact, the double <code>Either</code> would be enough to
indicate to a programmer that something is off here.</p>
<h2 id="names-are-not-type-safety">Names are not type safety</h2>
<p>As an aside, an easy to avoid confusion here is to simply use a type
dedicated to this. Let’s call it <code>Failure</code>:</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Failure</span> err ok <span class="ot">=</span> <span class="dt">Failed</span> err <span class="op">|</span> <span class="dt">Ok</span> ok</span></code></pre></div>
<p>Now, it’s not possible to be confused about <code>Either</code> as
some random data and <code>Failure</code> which only ever is produced by
a failure. Many have argued that <code>Either</code> itself is a form of
<a
href="https://existentialtype.wordpress.com/2011/03/15/boolean-blindness/">boolean
blindness</a>. I used <code>Either</code> in my post as an aid to
demonstrate a point; there’s no compelling reason otherwise to use
it.</p>
<p>The author, citing Alexis King, would have us believe that <a
href="https://lexi-lambda.github.io/blog/2020/11/01/names-are-not-type-safety/">names
are not type safety</a>. <strong>I disagree; all types are type
safety.</strong> The attempt to put type techniques into “safe” and
“unsafe” categories only serves to eliminate nuance.</p>
<p>Additionally, the author believes that syntax is not type safety. I
think syntax is the main driving force behind type safety, or so I feel,
having written the type generation stage of various compilers.</p>
<h2 id="finally-pun-intended">Finally (pun intended)</h2>
<p>The last point the author brings up seems to be more of a criticism
of any <code>IO</code> action returning <code>Either</code>, than the
special syntax I proposed in my post.</p>
<p>In base there are two functions which are notable in one crucial
aspect, <strong>their discarding of values</strong>:</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="ot">finally ::</span> <span class="dt">MonadUnliftIO</span> m <span class="ot">=&gt;</span> m a <span class="ot">-&gt;</span> m b <span class="ot">-&gt;</span> m a</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="ot">bracket ::</span> <span class="dt">MonadUnliftIO</span> m <span class="ot">=&gt;</span> m a <span class="ot">-&gt;</span> (a <span class="ot">-&gt;</span> m b) <span class="ot">-&gt;</span> (a <span class="ot">-&gt;</span> m c) <span class="ot">-&gt;</span> m c</span></code></pre></div>
<p><code>finally</code> discards <code>b</code>, and
<code>bracket</code> discards <code>b</code>.</p>
<p>The author writes that for,</p>
<div class="sourceCode" id="cb11"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>someAction1 <span class="ot">`finally`</span> someAction2</span></code></pre></div>
<p>would necessarily discard the result of <code>someAction2</code>. I
think this is a good observation. <strong>Your result will be discarded,
never to be seen again.</strong></p>
<p>This does bring up a wider point, however: the type of bracket and
friends is a problem. Why don’t they use <code>()</code>? These
functions can swallow results all the time, regardless of whether you’re
using <code>Try.do</code> or writing normal Haskell. In Scala, Kotlin
and Ceylon, <code>bracket</code> uses <code>void</code> or
<code>unit</code>.</p>
<p>I’m glad the author brought this up, because we don’t currently have
any tooling to find and catch these mistakes. Essentially,
<code>bracket</code>/<code>finally</code> are risky functions to use due
to this.<a href="#fn1" class="footnote-ref" id="fnref1"
role="doc-noteref"><sup>1</sup></a> This is what prompted the title of
my reply – is it <code>Try.do</code> that’s dangerous, or is it
<code>bracket</code>/<code>finally</code>?</p>
<p>Is it a criticism of <code>Try.do</code>? I’m doubtful at the
moment.</p>
<h2 id="concluding">Concluding</h2>
<p>I don’t think there’s any reason to call this technique “dangerous”.
I think that the examples in the post were slightly contrived (such as
the dubious suggestion that you would implement <code>Exception</code>
for your result type, or not using the result of an action that GHC
would warn you about), and in the last point it seemed to be arguing
against <code>base</code> rather than my proposed technique, to which I
can only agree.</p>
<p>I’m unsure about the tone in the penultimate paragraph<a href="#fn2"
class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a>,
but overall I liked the criticism, it got me thinking. I do think
there’s a wider discussion to be had about “use”, and perhaps my slow
absorption of Rust thinking has me wishing there was less of a
complacent attitude to throwing away results in Haskell’s base
libraries. It’ll raise my alarms more readily when reviewing/auditing
code.</p>
<p>It’ll still be a while before I’m even able to take advantage of
<code>QualifiedDo</code>, but I still look forward to pushing the
boundaries of this idea.</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Well, they’re risky anyway. Consider
the case of an exception being raised in the handler or releaser. It’s
complicated.<a href="#fnref1" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p>This language seems tonally
ambiguous, “shallow unsafe trick into a single weak spoiled framework”,
but I’ll assume good faith.<a href="#fnref2" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2020-12-24 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Thu, 24 Dec 2020 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Try.do for recoverable errors in Haskell]]></title><link>https://chrisdone.com/posts/try-do</link><guid>https://chrisdone.com/posts/try-do</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Try.do for recoverable errors in Haskell</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Try.do for recoverable errors in Haskell</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p><strong>UPDATE 2021-01-02</strong>: I have since written <a
href="https://github.com/inflex-io/early">a GHC compiler plugin to
implement an alternative <code>?</code>-based syntax for early
return.</a> I prefer that one than use of <code>Try.do</code>, because
it doesn’t require any type magic or special instances, and the
<code>?</code> is more readable.</p>
<hr />
<p><strong>UPDATE</strong>: I’ve added a follow-up post to this <a
href="/posts/is-try-do-dangerous/">here</a>, where I address some
criticisms of this post.</p>
<hr />
<p>The first half of this post is <a
href="/posts/recoverable-errors-in-haskell">here</a>. Please read that
for context.</p>
<h2 id="qualified-do">Qualified do</h2>
<p>One thing that struck me was that our earlier
<code>Make the IO action return Either</code> approach produced code
that was still perfectly satisfying the unliftio laws. Perhaps, like in
Rust, we need a syntactic solution to the problem.</p>
<p>Enter <a
href="https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/qualified_do.html">QualifiedDo</a>,
which will be available on the 9.0.1 version of GHC. What this would
allow us to do is rebind <code>(&gt;&gt;=)</code> to mean what we’d
like:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">module</span> <span class="dt">Try</span> ((<span class="op">Try.&gt;&gt;=</span>)) <span class="kw">where</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="ot">(&gt;&gt;=) ::</span> <span class="dt">IO</span> (<span class="dt">Either</span> e a) <span class="ot">-&gt;</span> (a <span class="ot">-&gt;</span> <span class="dt">IO</span> (<span class="dt">Either</span> e b)) <span class="ot">-&gt;</span> <span class="dt">IO</span> (<span class="dt">Either</span> e b)</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>(<span class="op">&gt;&gt;=</span>) m f <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>  result <span class="ot">&lt;-</span> m</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">case</span> result <span class="kw">of</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Left</span> e <span class="ot">-&gt;</span> <span class="fu">pure</span> (<span class="dt">Left</span> e)</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Right</span> a <span class="ot">-&gt;</span> f a</span></code></pre></div>
<p>We put this in a module called <code>Try</code> and import it with
<code>QualifiedDo</code> enabled.</p>
<p>Now our code becomes:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>Try.do constraints <span class="ot">&lt;-</span> constrainRenamed renamed</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>       solved <span class="ot">&lt;-</span> solveConstraints constraints</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>       generalised <span class="ot">&lt;-</span> generaliseSolved solved</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>       resolveGeneralised generalised</span></code></pre></div>
<p>where each action’s type is
<code>SomeThing -&gt; IO (Either ErrorType OtherThing)</code>.</p>
<p>Full working example:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE QualifiedDo #-}</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Try</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">ErrorType</span> <span class="ot">=</span> <span class="dt">OhNo</span> <span class="kw">deriving</span> (<span class="dt">Show</span>)</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="ot">action1 ::</span> <span class="dt">IO</span> (<span class="dt">Either</span> <span class="dt">ErrorType</span> <span class="dt">Int</span>)</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>action1 <span class="ot">=</span> <span class="fu">pure</span> (<span class="dt">Right</span> <span class="dv">10</span>)</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="ot">action2 ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> (<span class="dt">Either</span> <span class="dt">ErrorType</span> <span class="dt">Int</span>)</span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>action2 x <span class="ot">=</span> <span class="fu">pure</span> (<span class="dt">Left</span> <span class="dt">OhNo</span>)</span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a><span class="ot">action3 ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> (<span class="dt">Either</span> <span class="dt">ErrorType</span> <span class="dt">Int</span>)</span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>action3 x <span class="ot">=</span> <span class="fu">pure</span> (<span class="dt">Right</span> (x<span class="op">+</span><span class="dv">30</span>))</span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>  result <span class="ot">&lt;-</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>    Try.do</span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>      output <span class="ot">&lt;-</span> action1</span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>      output2 <span class="ot">&lt;-</span> action2 output</span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>      output3 <span class="ot">&lt;-</span> action3 output2</span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>  <span class="fu">print</span> result</span></code></pre></div>
<p>If you want a final return, you need to wrap it up in
<code>Either</code>, as:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>  result <span class="ot">&lt;-</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>    Try.do</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>      output <span class="ot">&lt;-</span> action1</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>      output2 <span class="ot">&lt;-</span> action2 output</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>      output3 <span class="ot">&lt;-</span> action3 output2</span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>      <span class="fu">pure</span> (<span class="dt">Right</span> output3)</span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>  <span class="fu">print</span> result</span></code></pre></div>
<p>Otherwise it won’t match our type:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>Main.hs<span class="op">:</span><span class="dv">16</span><span class="op">:</span><span class="dv">7</span><span class="op">:</span> <span class="fu">error</span><span class="op">:</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    • <span class="dt">Couldn&#39;t</span> match <span class="kw">type</span> ‘<span class="dt">Int</span>’ with ‘<span class="dt">Either</span> <span class="dt">ErrorType</span> b0’</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>      <span class="dt">Expected</span><span class="op">:</span> <span class="dt">IO</span> (<span class="dt">Either</span> <span class="dt">ErrorType</span> b0)</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Actual</span><span class="op">:</span> <span class="dt">IO</span> <span class="dt">Int</span></span></code></pre></div>
<p>People who know a bit of Rust will see this as a familiar pattern;
putting <code>Ok(output3)</code> at the end of your function.</p>
<p>What did we gain? We can have our cake and eat it too. We get a
trivial, syntactically-lightweight, way to string possibly-failing
actions together, while retaining all the benefits of being an
unliftio-able monad.</p>
<p><strong>Verdict</strong>: Best of all worlds.</p>
<h2 id="good-things-come-to-those-who-wait">Good things come to those
who wait</h2>
<p>Unfortunately, it’ll be a while before I’ll be upgrading to this
version of GHC, but I look forward to being able to use this time
saver.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2020-12-21 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Mon, 21 Dec 2020 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Recoverable errors in Haskell]]></title><link>https://chrisdone.com/posts/recoverable-errors-in-haskell</link><guid>https://chrisdone.com/posts/recoverable-errors-in-haskell</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Recoverable errors in Haskell</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Recoverable errors in Haskell</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>In Haskell, I sometimes have IO-based actions that may produce
failures. The IO aspect is usually incidental; because I need logging or
metrics generation.</p>
<p>When not using a free monad or a fancy effect-system–just plain IO–I
like to follow a mental model similar to <a
href="https://doc.rust-lang.org/book/ch09-00-error-handling.html">Rust’s
definition of error handling</a>, which splits them into
<em>recoverable</em> vs <em>unrecoverable</em> errors.</p>
<p>In Rust, when a function can fail with a recoverable error, it
returns a <code>Result</code>, like:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode rust"><code class="sourceCode rust"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Result</span><span class="op">&lt;</span>OutputType<span class="op">,</span> ErrorType<span class="op">&gt;</span></span></code></pre></div>
<p>which the caller can pattern-match on. Let’s compare recoverable
errors in Haskell.</p>
<h2 id="have-the-io-action-throw-a-runtime-exception">Have the IO action
throw a runtime exception</h2>
<p>Our code might look like:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">do</span> constraints <span class="ot">&lt;-</span> constrainRenamed renamed</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>   solved <span class="ot">&lt;-</span> solveConstraints constraints</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>   generalised <span class="ot">&lt;-</span> generaliseSolved solved</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>   resolveGeneralised generalised</span></code></pre></div>
<p>And each of these steps may throw an exception. We leave it up to
code above in the call chain to remember to catch them.</p>
<p>The trouble with exceptions is that they’re not mentioned in the type
system. They’re also handled not at the call site, when for recoverable
errors, that is usually the most straight-forward place to handle
them.</p>
<p>It’s simply very easy–and it happens all the time–that you either
throw the wrong exception type in the wrong place, or you forget to
catch exceptions at the right place.</p>
<p><strong>Verdict</strong>: Too dangerous.</p>
<h2 id="make-the-io-action-return-either">Make the IO action return
Either</h2>
<p>A more direct approach, which is a bit like Rust, is to simply have
the function return <code>Either ErrorType OutputType</code> and then
pattern match on the result to find out whether everything went
fine.</p>
<p>Now our code looks like this:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">do</span> constraints <span class="ot">&lt;-</span> constrainRenamed renamed</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>   <span class="kw">case</span> constraints <span class="kw">of</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>     <span class="dt">Left</span> err <span class="ot">-&gt;</span> <span class="fu">return</span> (<span class="dt">Left</span> err)</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>     <span class="dt">Right</span> constraints&#39; <span class="ot">-&gt;</span> <span class="kw">do</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>       solved <span class="ot">&lt;-</span> solveConstraints constraints</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>       <span class="kw">case</span> solved <span class="kw">of</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>         <span class="dt">Left</span> err <span class="ot">-&gt;</span> <span class="fu">return</span> (<span class="dt">Left</span> err)</span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>         <span class="dt">Right</span> solved&#39; <span class="ot">-&gt;</span> <span class="kw">do</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>           generalised <span class="ot">&lt;-</span> generaliseSolved solved&#39;</span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>           <span class="kw">case</span> generalised <span class="kw">of</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>             <span class="dt">Left</span> err <span class="ot">-&gt;</span> <span class="fu">return</span> (<span class="dt">Left</span> err)</span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>             <span class="dt">Right</span> generalised&#39; <span class="ot">-&gt;</span> <span class="kw">do</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>              resolveGeneralised generalised&#39;</span></code></pre></div>
<p>This is tedious to write, there’s all that repetition on the
<code>Left</code> case. Reading it, you also can’t immediately tell
whether there’s any extra logic going on here.</p>
<p><strong>Verdict</strong>: Too much code.</p>
<h2 id="wrap-your-io-code-up-in-exceptt">Wrap your IO code up in
<code>ExceptT</code></h2>
<p>One way to solve this issue is to wrap up these actions in the
<code>ExceptT</code> monad transformer. We have to make each of the
actions now live in the <code>ExceptT</code> monad, so</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="dt">IO</span> (<span class="dt">Either</span> <span class="dt">ErrorType</span> <span class="dt">OutputType</span>)</span></code></pre></div>
<p>becomes</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="dt">ExceptT</span> <span class="dt">ErrorType</span> <span class="dt">IO</span> <span class="dt">OutputType</span></span></code></pre></div>
<p>And our code goal is clean again:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>runExceptT</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>  (<span class="kw">do</span> constraints <span class="ot">&lt;-</span> constrainRenamed renamed</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>      solved <span class="ot">&lt;-</span> solveConstraints constraints</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>      generalised <span class="ot">&lt;-</span> generaliseSolved solved</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>      resolveGeneralised generalised)</span></code></pre></div>
<p>The <code>runExceptT</code> produces an
<code>IO (Either ErrorType OutputType)</code>.</p>
<p>However, <code>ExceptT</code> <a
href="https://github.com/fpco/unliftio/tree/master/unliftio#limitations">cannot
be an instance of <code>MonadUnliftIO</code></a> – because it
necessarily requires multiple exit points. See <a
href="https://github.com/fpco/unliftio/issues/68">this discussion</a>
which should give you an idea of how hairy and unpredictable this can
be.</p>
<p><strong>This is a big deal.</strong></p>
<p>Essentially, if a monad is unliftio-able, then:</p>
<ol type="1">
<li>The regular exception system will work as normal. This is important,
because you do want regular exceptions to be thrown upwards.</li>
<li>Concurrent programming works as usual: you can use
<code>async</code> with <a
href="https://hackage.haskell.org/package/unliftio-0.2.13.1/docs/UnliftIO-Async.html"><code>UnliftIO.Async</code></a>
and get predictable results.</li>
<li>Resource clean-up is also straight-forward.</li>
</ol>
<p>So, <code>ExceptT</code> has to be thrown out too, sadly.</p>
<p><strong>Verdict</strong>: Not compatible.</p>
<h2 id="solutions">Solutions</h2>
<p>I previously explored in <a
href="https://chrisdone.com/posts/try-do/">another post</a> about
<code>Try.do</code>, which I’ve decided against in favor of…</p>
<p>I have since written <a href="https://github.com/inflex-io/early">a
GHC compiler plugin to implement an alternative <code>?</code>-based
syntax for early return.</a> I prefer that one than use of
<code>Try.do</code>, because it doesn’t require any type magic or
special instances, and the <code>?</code> is more readable.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2020-12-21 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Mon, 21 Dec 2020 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Use import aliases to easily access fields]]></title><link>https://chrisdone.com/posts/import-aliases-field-names</link><guid>https://chrisdone.com/posts/import-aliases-field-names</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Use import aliases to easily access fields</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Use import aliases to easily access fields</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>This post demonstrates using imports as a quick and easy way to
disambiguate record field names. You can still put all your types in one
module.</p>
<p>No fancy type classes or machinery needed.</p>
<p>Define all your types in one module, using
<code>DuplicateRecordFields</code> to avoid GHC complaining about
conflicting field names:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE DuplicateRecordFields  #-}</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">module</span> <span class="dt">Types</span> <span class="kw">where</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Prelude</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Person</span> <span class="ot">=</span> <span class="dt">Person</span> {<span class="ot"> name ::</span> <span class="dt">String</span>,<span class="ot"> age ::</span> <span class="dt">Int</span> } <span class="kw">deriving</span> <span class="dt">Show</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Company</span> <span class="ot">=</span> <span class="dt">Company</span> {<span class="ot"> name ::</span> <span class="dt">String</span>,<span class="ot"> age ::</span> <span class="dt">Int</span> } <span class="kw">deriving</span> <span class="dt">Show</span></span></code></pre></div>
<p>Now in another module, use import aliases to get at specific types
(<code>Person</code> and <code>Company</code>):</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE DuplicateRecordFields  #-}</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">module</span> <span class="dt">Use</span> <span class="kw">where</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Prelude</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Types</span> <span class="kw">as</span> <span class="dt">Person</span> (<span class="dt">Person</span>(..))</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Types</span> <span class="kw">as</span> <span class="dt">Company</span> (<span class="dt">Company</span>(..))</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Types</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a><span class="ot">main ::</span> <span class="dt">IO</span> ()</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">let</span> <span class="co">-- Freely use Person/Company constructors, and field names unqualified:</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>      mary <span class="ot">=</span> <span class="dt">Person</span> {name <span class="ot">=</span> <span class="st">&quot;Mary&quot;</span>, age <span class="ot">=</span> <span class="dv">23</span>}</span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>      james <span class="ot">=</span> <span class="dt">Person</span> {name <span class="ot">=</span> <span class="st">&quot;James&quot;</span>, age <span class="ot">=</span> <span class="dv">22</span>}</span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>      company <span class="ot">=</span> <span class="dt">Company</span> {name<span class="ot">=</span><span class="st">&quot;Fish Limited&quot;</span>,age<span class="ot">=</span><span class="dv">150</span>}</span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>   <span class="kw">in</span> <span class="kw">do</span> <span class="co">-- Pattern matching convenience:</span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>         <span class="kw">case</span> mary <span class="kw">of</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>           <span class="dt">Person</span>{name} <span class="ot">-&gt;</span> <span class="fu">print</span> name</span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a>         <span class="kw">case</span> company <span class="kw">of</span></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a>           <span class="dt">Company</span>{name} <span class="ot">-&gt;</span> <span class="fu">print</span> name</span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a>         <span class="co">-- Easily transfer data between record types because the field names are the same.</span></span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a>         <span class="kw">let</span> transferred <span class="ot">=</span> <span class="dt">Company</span> {<span class="op">..</span>} <span class="kw">where</span> <span class="dt">Person</span> {<span class="op">..</span>} <span class="ot">=</span> mary</span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a>         <span class="co">-- Accessing:</span></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a>         <span class="fu">print</span> (Person.name mary)</span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a>         <span class="fu">print</span> (Person.name james)</span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a>         <span class="fu">print</span> (<span class="fu">map</span> Person.name [mary,james])</span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a>         <span class="fu">print</span> (Company.name company)</span>
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a>         <span class="fu">print</span> (Company.name transferred)</span>
<span id="cb2-27"><a href="#cb2-27" aria-hidden="true" tabindex="-1"></a>         <span class="co">-- Updating:</span></span>
<span id="cb2-28"><a href="#cb2-28" aria-hidden="true" tabindex="-1"></a>         <span class="fu">print</span> (mary { Person.name <span class="ot">=</span> <span class="st">&quot;Maria&quot;</span>})</span></code></pre></div>
<p>Daniel Díaz Carrete commented:</p>
<blockquote>
<p>While it doesn’t free you from having to prepend the qualified name
when using the selectors, it feels conceptually “better” to define it
once at the import list, instead of doing it at each field
declaration.</p>
</blockquote>
<p>Which I agree with!</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2020-12-15 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Tue, 15 Dec 2020 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[The language of spreadsheets is bad]]></title><link>https://chrisdone.com/posts/language-of-spreadsheets-is-bad</link><guid>https://chrisdone.com/posts/language-of-spreadsheets-is-bad</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>The language of spreadsheets is bad</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>The language of spreadsheets is bad</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>The user interface in a spreadsheet is modal. There are two
modes:</p>
<ul>
<li>The first mode is <strong>code</strong> (also known as: formula):
<code>=SUM(A1:A5)</code></li>
<li>The second mode is the <strong>result</strong> of running that code:
<code>234</code></li>
</ul>
<p>You type in some equation, some mathematics, some conditions, and
then you hit return, and then you see the results.</p>
<h2 id="declarative-programming-is-a-good-fit">Declarative programming
is a good fit</h2>
<p>The programming language that you write your code in is a declarative
programming language. We call programming languages declarative when you
say what you want (declarative) more than instructing the computer how
to go about achieving it (imperative). When languages are declarative,
it gives the system more freedom to make choices about how to go about
computing results.</p>
<p>The code in spreadsheets is this kind of language. It has to be. When
you change code in one cell, all the other cells are updated. If the
language was imperative, that would mean it could change things. That’s
bad when cells are re-run all the time during your course of work. It’d
be chaos to keep track of what you changed.</p>
<p>That’s why the language must be declarative, to give the system
freedom to run formulae whenever it needs to without worrying about side
effects. On VisiCalc, the first spreadsheet software from 1979, Ted
Nelson said:</p>
<p>“VISICALC represented a new idea of a way to use a computer and a new
way of thinking about the world. Where conventional programming was
thought of as a sequence of steps, this new thing was no longer
sequential in effect: When you made a change in one place, all other
things changed instantly and automatically.”</p>
<h2 id="thats-where-it-ends">That’s where it ends</h2>
<p>However, it’s quite a limited programming language. It was initially
designed to handle a small subset of problems that you might encounter
in finance. It has been extended with plenty of functions like
trigonometric functions and things like that, but without any particular
rigour or academic insight or critical eye.</p>
<p>It’s very convenient for simple problems, dealing with simple
numbers, text and dates. However, any programmer can tell you
immediately that there are limitations to this language. And indeed any
Excel or Google Sheets user can tell you that they have hit the limits
of this language often.</p>
<h2 id="the-solutions-arent-solutions">The solutions aren’t
solutions</h2>
<p>When you hit the limits of the spreadsheets expression language,
there are two approaches:</p>
<ul>
<li>The first is to try to remodel your problem to avoid the limitation,
this is really just a hack/kludge.</li>
<li>The other is to simply abandon this language and use either Visual
Basic or JavaScript, or Python, or some other general purpose
programming language that has the power to express what you really
wanted to express in the first place. This is typically called
“scripting”.</li>
</ul>
<p>The first approach is not a solution.</p>
<p>For the second, there are two solid problems with this approach:</p>
<ul>
<li>The first problem is that you are no longer using the original
language and therefore you have to keep two languages in sync and in
your head.</li>
<li>You have to work with two completely different programming
paradigms, because all of the mainstream scripting languages are
imperative.</li>
</ul>
<p>You have lost the declarative nature of what makes spreadsheets
great. You also have to learn a new language.</p>
<p>If you were a normal spreadsheet user, with a full plate of work, the
chances of actually learning Visual Basic or Python on your own time are
very slim.</p>
<p>So, probably, you’ll have to ask a “programmer” to solve your problem
for you, which is really annoying. A wise person once said: in
computing, there is nothing worse than a computer telling you that you
cannot express a thought.</p>
<h2 id="wizard-politics">Wizard politics</h2>
<p>This creates a funny class system of “muggles and wizards”, to borrow
a Harry Potter term, wherein the millions of users of spreadsheets are
the muggles that make do with rudimentary tools, and the wizards are a
privileged class with all the power. Modern offerings like AirTable
continue this narrative: in the community forums, I have read this
comment by a community leader:</p>
<blockquote>
<p>I don’t recommend attempting this using a formula field. Look into a
scripting solution—either in the Scripting app, or in a “Run script”
action in an automation—where you can tap into the built-in sorting
features of the JavaScript language.</p>
</blockquote>
<p>It also makes bad sense from a business perspective; I paid for a
tool for all my employees, and now my employees are asking for
developers to do something that the tool should be able to do already.
My employees are wasted even though they are perfectly good at their
domain and are willing.</p>
<p>We are also faced with a secondary problem, which is the problem of
choice. You have to choose where to put your logic, either in the
spreadsheet or in the scripting language. Now you have two problems.</p>
<h2 id="lets-call-a-spade-a-spade">Let’s call a spade a spade</h2>
<p>The elephant in the room is simply that the expression language in
spreadsheets is insufficient, not up to the task, not up to snuff,
including for people who aren’t programmers or engineers. Hybridisation
does not work well to paper over this issue either.</p>
<p>This is also omitting other criticisms, like a lack of first-class
functions, which would make awkward abominations like
<code>VLOOKUP</code> and friends unnecessary.</p>
<p>We also know that this language simply does not scale. People write
god-awful messes of <code>IF(IF(..))</code> expressions that fill a
whole screen in one cell. Formulae are duplicated across ranges and then
accidentally modified only in some of them. It’s the wild west.</p>
<h2 id="there-is-already-a-better-language">There is already a better
language</h2>
<p>The good news is that for 35 years there has been in development
so-called <em>pure functional programming languages</em>, which are
declarative languages which have the power of general purpose languages
like Visual Basic, yet retain the declarative purity that we enjoy in
spreadsheets.</p>
<p>The most popular incarnation of this is called Haskell. It has a
static type system which prevents some issues. It has a well-developed,
comprehensive set of functions for expressing common problems like
loops, filters, reductions, etc.</p>
<p>Unlike your Visual Basics, your Pythons, your JavaScripts, Haskell
knows how to express normal every day programming problems in a
functional declarative way, and that is what makes it a perfect
candidate replacement language for spreadsheets.</p>
<p>Haskell also has something to say about dealing with time (think:
<code>=NOW()</code>), streams (think reading data from external
systems), events (think button clicks) and the rest in a pure language.
Spreadsheet systems side-step the whole issue (and miss a huge
opportunity), opting to simply call these “volatile” cells that may
change in a variety of ad hoc cases, but we’ll see more about that in
another future article.</p>
<h2 id="conclusion">Conclusion</h2>
<p>In conclusion, there’s no point trying to maintain a hybrid approach
of using a very restricted language combined with an imperative
language, when you could go straight to the obvious solution and use a
real, functional, powerful language from the beginning, which has been
tried and tested for 35 years, and is easily up to the task of
expressing spreadsheet problems. There is also an optimising compiler
that can compile it to machine code to run very quickly.</p>
<p>You can educate people in a tool to do simple arithmetic and filters
very easily, I’ve done it. But the key addition is that you can level up
in the same language to do more complex things. There’s a progression
path.</p>
<p>Our Inflex language is built from the ground up based on Haskell
(with lessons from PureScript, Unison and OCaml). It’s designed to be
run in a reactive document, to deal with numbers, records, lists,
tables, etc. and in the future, streams. At the time of writing, we’re
in an invite-only beta, but we’ll be documenting more of that language
over time.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2020-11-13 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Fri, 13 Nov 2020 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[What’s wrong with the grid?]]></title><link>https://chrisdone.com/posts/whats-wrong-with-the-grid</link><guid>https://chrisdone.com/posts/whats-wrong-with-the-grid</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>What’s wrong with the grid?</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>What’s wrong with the grid?</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>The grid system in spreadsheets is very simple. It’s also very
powerful, and it’s powerful because it’s simple. As a user you can
immediately start entering data without even thinking about it. And
then, in an ad hoc fashion, you can add logic and conditions as you
think of them.</p>
<h2 id="lack-of-boundaries-cause-bugs">Lack of boundaries cause
bugs</h2>
<p>This fast and loose paradigm is also the downfall of spreadsheets,
because the user is encouraged to do a form of programming, without
encouraging them to do any kind of discipline. Spreadsheets quickly get
out of hand. The boundaries are arbitrary, and usually are only visual,
which means it’s very difficult to write good code based on this.</p>
<p>For example, there is the famous case of a large spreadsheet used in
an economics paper, called <a
href="https://en.wikipedia.org/wiki/Growth_in_a_Time_of_Debt#Methodological_flaws">Growth
in a time of Debt</a>, and there was a miscalculation because a few rows
at the end of a list of items were not taken into account, as, per usual
in a spreadsheet, the user specified them in a range. It has been
criticised anywhere from a gross oversight to disastrous.</p>
<h2 id="proper-data-structures-are-simpler">Proper data structures are
simpler</h2>
<p>However, in normal programming, we don’t have just one data
structure. The grid is just one data structure, a matrix of practically
infinite width and height. You can access its elements by coordinates.
But in programming––normal programming––we have, for example, lists. If
a proper list data structure were were used for the list of elements in
the above example, there wouldn’t have been this bug, because you don’t
have to specify how many elements of a list you want to work on. We just
say “apply this function to all elements of the list.”</p>
<p>Data structures like lists and matrices can all be approximated in a
spreadsheet by a grid, badly. However, anything more than this becomes
awkward very quickly.</p>
<p>For example, a simple record consisting of a name and an age in a
spreadsheet must be modelled by using a cell for the label of the name
and label of the age, and then the value for each thing. This is a hack,
using superficial visual embellishments to reflect what is actually
data.</p>
<p>In normal programming languages, this is called a record. There’s no
need for any kind of strange and brittle hacking and tricks to make this
work as you have to do in a spreadsheet. The basic spreadsheet, as-is,
is very accessible to the normal person who just wants to do every day
calculations about their business. But the ideas of a record, list, tree
or graph are also intuitive for normal people because they actually
model the kind of data that their domain is dealing with. Sadly,
knowledge workers using spreadsheets are deprived of these tools.</p>
<h2 id="data-modelling-is-poor">Data modelling is poor</h2>
<p>Therefore we find spreadsheets very lacking, in fact, when we try to
model even every day pedestrian problems. Consider for example trying to
model a family tree, or the hierarchical structure of the US government,
or a taxonomy of a species.</p>
<p>Trees are three data structures, perfectly normal, well understood,
pliable, things that you can express in a programming language and
manipulate using code in a very logical manner. You can count how many
items are in the tree, you can restrict the tree to a certain branch,
perform a transformation on each node in the tree, or transpose the tree
and flip it upside down!</p>
<p>Another example is a graph. For example, the Coronavirus can be
modelled by its spread using a graph the graph consists of a set of
people in the connections between those people. You can easily write
code to count how many connections a given node has to it; that’s a
normal graph operation. Or count how many transitive node are connected
to it in one direction, in other words; you can measure the influences
of one person within a community.</p>
<p>Aside from using code to manipulate said data structures, your user
interface should allow you to click a node and edit the text, maybe
write some code in there, like any other type of cell.</p>
<p>Both of those things are impossible, practically, to describe, talk
about, express, manipulate, or visualise, in a traditional grid-based
spreadsheet!</p>
<p>So, we’ve established two things so far. The first is that the grid
system lacks boundaries between different data structures, which can
lead to bugs. Second is that there are actually very normal, every day,
useful data structures which we should, in a reasonable system, be able
to express, but which the grid system is unable to express.</p>
<p>Additionally, we have seen that these data structures actually have
very well understood and rich and useful operations which work only if
you have that kind of data structure.</p>
<p>But a spreadsheet simply has one single data structure: the grid.
And, the only elements that you can put in that data structure are
numbers, strings and dates. In other words, atomic values. But that’s
not real life. There’s no reason that I should not be able to have a
list of lists. Or a tree of records. Or a list of records (aka a
“table”). I should, hypothetically, be able to arbitrarily nest data
structures as it fits my problem.</p>
<h2 id="correctness-checks">Correctness checks</h2>
<p>Turning to a different topic, when you have different data
structures, you can start to add checks that help you avoid making other
types of mistakes. If your system knows the shape of data, it can have
expectations about how you use it.</p>
<p>You can add a type system to the system. The purpose of a type system
is to make sure that you are combining your different operations
together in a way that makes sense. Not putting a square peg in around
hole. For example, you can calculate the sum of an list, of a graph, of
a tree. However, you cannot concatenate a graph to an list. What would
that even mean?</p>
<h2 id="conclusion">Conclusion</h2>
<p>In conclusion, we’ve looked at reasons why a traditional spreadsheet
grid system is lacking in several key areas of expression, correctness,
and even convenience, in a way that is actually important for normal
knowledge work and not just for programmers.</p>
<p>If you look through various competitors to the established
spreadsheet vendors, you’ll see a lot of “reinvent spreadsheets”
language. But it’s always the same thing: we have a grid system with
coordinates and an underwhelming untyped expression language. But they
added JavaScript or Python to it, or added a “low-code” app generator on
top of the spreadsheet, or some special views.</p>
<p>We’re working on <a href="https://inflex.io/">a system called
Inflex</a> that really does rethink the spreadsheet fundamentally from
the ground up. And the first thing to be thrown out is the grid, the
coordinate system and replace them with real data structures and a type
system.</p>
<p>We keep what’s <em>good</em> about spreadsheets: the reactivity and
“edit-in-place” user experience.</p>
<p>In our next post we’ll be discussing the fundamental problems with
the expression/formula languages used in spreadsheet software, and how
we are fixing it.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2020-11-12 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Thu, 12 Nov 2020 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Ghosts of Departed Proofs Convenience]]></title><link>https://chrisdone.com/posts/ghost-of-departed-proofs-conveniences</link><guid>https://chrisdone.com/posts/ghost-of-departed-proofs-conveniences</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Ghosts of Departed Proofs Convenience</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Ghosts of Departed Proofs Convenience</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Following on from <a href="https://kataskeue.com/gdp.pdf"><em>Ghosts
of Departed Proofs</em></a> with a <code>Named</code> type as defined in
<a
href="https://ocharles.org.uk/blog/posts/2019-08-09-who-authorized-these-ghosts.html">Olliver
Charles’s post on the same topic</a>, we can add a usability improvement
by defining a <code>SomeNamed</code> existential in order to wrap up the
new type introduced for the <code>n</code> in <code>Name n a</code>, and
then a pattern synonym to conveniently unwrap that constructor.</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- | Our main engine for naming a value, then we can prove properties</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="co">--   about a named value.</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE ExistentialQuantification #-}</span> <span class="co">-- Used for SomeNamed.</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE PatternSynonyms #-}</span> <span class="co">-- Used for the Name pattern.</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE ViewPatterns #-}</span> <span class="co">-- Used for the Name pattern.</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE RankNTypes #-}</span> <span class="co">-- Used for withName.</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="kw">module</span> <span class="dt">Named</span> ( <span class="dt">Named</span>, <span class="kw">pattern</span> <span class="dt">Name</span>, forgetName</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>             , withName, someNamed, <span class="dt">SomeNamed</span>(<span class="op">..</span>) ) <span class="kw">where</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a><span class="co">-- | Give a generated type-level name to any value.</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">Named</span> n a <span class="ot">=</span> <span class="dt">Named_</span> {<span class="ot"> forgetName ::</span> a }</span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a><span class="ot">withName ::</span> a <span class="ot">-&gt;</span> (<span class="kw">forall</span> name<span class="op">.</span> <span class="dt">Named</span> name a <span class="ot">-&gt;</span> r) <span class="ot">-&gt;</span> r</span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>withName x f <span class="ot">=</span> f (<span class="dt">Named_</span> x)</span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a><span class="co">-- | A convenient way to name something and access the name later.</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">SomeNamed</span> a <span class="ot">=</span> <span class="kw">forall</span> n<span class="op">.</span> <span class="dt">SomeNamed</span> (<span class="dt">Named</span> n a)</span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a><span class="co">-- | Wrap a value up with a non-exposed name.</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a><span class="ot">someNamed ::</span> a <span class="ot">-&gt;</span> <span class="dt">SomeNamed</span> a</span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>someNamed x <span class="ot">=</span> <span class="dt">SomeNamed</span> (<span class="dt">Named_</span> x)</span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a><span class="co">-- | A convenient way to quickly name a value as a pattern.</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a><span class="kw">pattern</span> <span class="dt">Name</span> t <span class="ot">&lt;-</span> (someNamed <span class="ot">-&gt;</span> <span class="dt">SomeNamed</span> t)</span></code></pre></div>
<p>With this, we can write</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">case</span> x <span class="kw">of</span> <span class="dt">Name</span> x&#39; <span class="ot">-&gt;</span> <span class="op">...</span></span></code></pre></div>
<p>And now we have a named version of <code>x</code>! This scales to any
number of tuples or pattern matches. See below for a real example.</p>
<h2 id="some-proof-generators">Some proof generators</h2>
<p>For the sake of example in the next section, I introduce a couple
trivial modules for checking non-zeroness of a number, and a function
that makes use of such proof to perform division.</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- | A trivial proof of nonzero for a given named thing.</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="co">--</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="co">-- Note that only this module can produce an IsNonzero value. Hence</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="co">-- you can only get a proof of nonzero via checkNonzero.</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="kw">module</span> <span class="dt">Nonzero</span> ( <span class="dt">IsNonzero</span>, checkNonzero ) <span class="kw">where</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Named</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">IsNonzero</span> name <span class="ot">=</span> <span class="dt">IsNonzero</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a><span class="ot">checkNonzero ::</span> (<span class="dt">Num</span> i, <span class="dt">Eq</span> i) <span class="ot">=&gt;</span> <span class="dt">Named</span> name i <span class="ot">-&gt;</span> <span class="dt">Maybe</span> (<span class="dt">IsNonzero</span> name)</span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>checkNonzero named</span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>  <span class="op">|</span> forgetName named <span class="op">/=</span> <span class="dv">0</span> <span class="ot">=</span> <span class="dt">Just</span> <span class="dt">IsNonzero</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>  <span class="op">|</span> <span class="fu">otherwise</span> <span class="ot">=</span> <span class="dt">Nothing</span></span></code></pre></div>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- | A simple API that requires proof of nonzero.</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="co">--</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="co">-- An obvious example: division requires a nonzero denominator.</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="kw">module</span> <span class="dt">Div</span> (divide) <span class="kw">where</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Named</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Nonzero</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a><span class="ot">divide ::</span> <span class="dt">Fractional</span> i <span class="ot">=&gt;</span> <span class="dt">IsNonzero</span> y <span class="ot">-&gt;</span> <span class="dt">Named</span> x i <span class="ot">-&gt;</span> <span class="dt">Named</span> y i <span class="ot">-&gt;</span> i</span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>divide _ x y <span class="ot">=</span> (forgetName x <span class="op">/</span> forgetName y)</span></code></pre></div>
<h2 id="example-use">Example use</h2>
<p>Here’s a simple program that parses two numbers, checks that the
latter is non-zero, and then does a division by that non-zero number.
Trivial, but it helps demonstrate the syntax without untidiness.</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Div</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Nonzero</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Text.Read</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Named</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>  numeratorString <span class="ot">&lt;-</span> <span class="fu">getLine</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>  denominatorString <span class="ot">&lt;-</span> <span class="fu">getLine</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">case</span> (,) <span class="op">&lt;$&gt;</span> readMaybe numeratorString</span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>           <span class="op">&lt;*&gt;</span> readMaybe<span class="ot"> denominatorString ::</span> <span class="dt">Maybe</span> (<span class="dt">Double</span>, <span class="dt">Double</span>) <span class="kw">of</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Nothing</span> <span class="ot">-&gt;</span> <span class="fu">error</span> <span class="st">&quot;Both must be valid numbers.&quot;</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Just</span> (<span class="dt">Name</span> numeratorNum, <span class="dt">Name</span> denominatorNum) <span class="ot">-&gt;</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a>      <span class="kw">case</span> checkNonzero denominatorNum <span class="kw">of</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Nothing</span> <span class="ot">-&gt;</span> <span class="fu">error</span> <span class="st">&quot;Denominator must be non-zero.&quot;</span></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Just</span> denominatorNonZero <span class="ot">-&gt;</span></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a>          <span class="kw">let</span> result <span class="ot">=</span> divide denominatorNonZero numeratorNum denominatorNum</span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a>          <span class="kw">in</span> <span class="fu">putStrLn</span> (<span class="st">&quot;Result: &quot;</span> <span class="op">++</span> <span class="fu">show</span> result)</span></code></pre></div>
<p>One nice addition is that we can <em>use monad syntax</em> to name
them very conveniently!</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>main2 <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>  numeratorString <span class="ot">&lt;-</span> <span class="fu">getLine</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>  denominatorString <span class="ot">&lt;-</span> <span class="fu">getLine</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">let</span> maybeResult <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Name</span> numeratorNum   <span class="ot">&lt;-</span> readMaybe numeratorString</span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Name</span> denominatorNum <span class="ot">&lt;-</span> readMaybe denominatorString</span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>        denominatorNonZero  <span class="ot">&lt;-</span> checkNonzero denominatorNum</span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>        <span class="fu">pure</span> (divide denominatorNonZero numeratorNum denominatorNum)</span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>  <span class="fu">maybe</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>    (<span class="fu">error</span> <span class="st">&quot;Something wasn&#39;t right and we don&#39;t care why.&quot;</span>)</span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>    <span class="fu">print</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a>    maybeResult</span></code></pre></div>
<p>With an <code>Either E</code> return type, we could return or throw
an exception, if we wanted to.</p>
<h2 id="proof-is-in-the-pudding-examples-that-do-not-compile">Proof is
in the pudding: Examples that do not compile</h2>
<p>Here are some example variations of <code>Main</code> which fail to
compile, demonstrating that this technique is helping the program be
more correct:</p>
<p>This version of main fails to compile simply because I haven’t named
the <code>numeratorInt</code>.</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Div</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Nonzero</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Text.Read</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Named</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>  numeratorString <span class="ot">&lt;-</span> <span class="fu">getLine</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>  denominatorString <span class="ot">&lt;-</span> <span class="fu">getLine</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">case</span> (,) <span class="op">&lt;$&gt;</span> readMaybe numeratorString</span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>           <span class="op">&lt;*&gt;</span> readMaybe<span class="ot"> denominatorString ::</span> <span class="dt">Maybe</span> (<span class="dt">Double</span>, <span class="dt">Double</span>) <span class="kw">of</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Nothing</span> <span class="ot">-&gt;</span> <span class="fu">error</span> <span class="st">&quot;Both must be valid numbers.&quot;</span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Just</span> (numeratorInt, <span class="dt">Name</span> denominatorInt) <span class="ot">-&gt;</span></span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a>      <span class="kw">case</span> checkNonzero denominatorInt <span class="kw">of</span></span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Nothing</span> <span class="ot">-&gt;</span> <span class="fu">error</span> <span class="st">&quot;Denominator must be non-zero.&quot;</span></span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Just</span> denominatorNonZero <span class="ot">-&gt;</span></span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true" tabindex="-1"></a>          <span class="kw">let</span> result <span class="ot">=</span> divide denominatorNonZero numeratorInt denominatorInt</span>
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true" tabindex="-1"></a>          <span class="kw">in</span> <span class="fu">putStrLn</span> (<span class="st">&quot;Result: &quot;</span> <span class="op">++</span> <span class="fu">show</span> result)</span></code></pre></div>
<p>Yields the error:</p>
<pre><code>Couldn&#39;t match expected type ‘Named x0 Double’ with actual type ‘Double’</code></pre>
<p>Here is a version where I got the arguments to divide the wrong way
round:</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Div</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Nonzero</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Text.Read</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Named</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>  numeratorString <span class="ot">&lt;-</span> <span class="fu">getLine</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>  denominatorString <span class="ot">&lt;-</span> <span class="fu">getLine</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">case</span> (,) <span class="op">&lt;$&gt;</span> readMaybe numeratorString</span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>           <span class="op">&lt;*&gt;</span> readMaybe<span class="ot"> denominatorString ::</span> <span class="dt">Maybe</span> (<span class="dt">Double</span>, <span class="dt">Double</span>) <span class="kw">of</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Nothing</span> <span class="ot">-&gt;</span> <span class="fu">error</span> <span class="st">&quot;Both must be valid numbers.&quot;</span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Just</span> (<span class="dt">Name</span> numeratorInt, <span class="dt">Name</span> denominatorInt) <span class="ot">-&gt;</span></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a>      <span class="kw">case</span> checkNonzero denominatorInt <span class="kw">of</span></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Nothing</span> <span class="ot">-&gt;</span> <span class="fu">error</span> <span class="st">&quot;Denominator must be non-zero.&quot;</span></span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Just</span> denominatorNonZero <span class="ot">-&gt;</span></span>
<span id="cb9-16"><a href="#cb9-16" aria-hidden="true" tabindex="-1"></a>          <span class="kw">let</span> result <span class="ot">=</span> divide denominatorNonZero  denominatorInt numeratorInt</span>
<span id="cb9-17"><a href="#cb9-17" aria-hidden="true" tabindex="-1"></a>          <span class="kw">in</span> <span class="fu">putStrLn</span> (<span class="st">&quot;Result: &quot;</span> <span class="op">++</span> <span class="fu">show</span> result)</span></code></pre></div>
<p>Yields the error:</p>
<pre><code>• Couldn&#39;t match type ‘n’ with ‘n1’</code></pre>
<p>The <code>denominatorNonZero</code> proof refers to
<code>denominatorInt</code> by a generate name type (<code>n1</code>),
and <code>numeratorInt</code>’s name (<code>n</code>) is different.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2019-12-07 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sat, 07 Dec 2019 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Defaulting fields in a record]]></title><link>https://chrisdone.com/posts/defaulting-fields-in-a-record</link><guid>https://chrisdone.com/posts/defaulting-fields-in-a-record</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Defaulting fields in a record</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Defaulting fields in a record</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Do you have 20+ fields of configuration for your kitchen sink API?
This approach might be for you.</p>
<p>An approach to specifying many (required) fields, where some are
defaulted. What you get:</p>
<ol type="1">
<li>The ability to specify what the defaults are in a single place.</li>
<li>That set of defaults is decoupled from the function that uses the
record (separating concerns).</li>
<li>The ability to choose different sets of defaults easily (e.g. “dev”
mode vs “production” mode).</li>
<li>Type-safety; you can’t specify defaults for required fields as an
API provider.</li>
<li>Overriding: you can provide values instead of using the default
trivially.</li>
<li>Light-weight syntax.</li>
<li>Failing to provide a required field as an API end-user results in a
type error.</li>
</ol>
<p>A field which has no sensible default value (such as one enabling a
new feature like <code>TLSSettings</code>) can still be
<code>Maybe a</code>.</p>
<p>Your consumer of this API:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- | Usage of API.</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">module</span> <span class="dt">Main</span> <span class="kw">where</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">DBAPI</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="co">-- Omitting either username or password triggers a type error.</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> connect connSpecDefaults {username <span class="ot">=</span> <span class="st">&quot;test&quot;</span>, password <span class="ot">=</span> <span class="st">&quot;mypw&quot;</span>}</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="co">-- To override defaults, just specify the field e.g. port:</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>main2 <span class="ot">=</span> connect connSpecDefaults {username <span class="ot">=</span> <span class="st">&quot;test&quot;</span>, password <span class="ot">=</span> <span class="st">&quot;mypw&quot;</span>, port <span class="ot">=</span> <span class="dv">1234</span>}</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a><span class="co">-- Thanks Aleksey Khudyakov (@pineapple_zombi) for pointing out that plain record</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a><span class="co">-- update has the same typing rules as RecordWildCards.</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a><span class="co">--</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a><span class="co">-- Old version was: ConnSpec{username=&quot;..&quot;,password=&quot;..&quot;,..} where</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a><span class="co">-- ConnSpec{..} = connSpecDefaults</span></span></code></pre></div>
<p>Definition of an API, in this case the example is a database:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE DataKinds #-}</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="co">-- | My database API.</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="kw">module</span> <span class="dt">DBAPI</span> <span class="kw">where</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Defaults</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">ConnSpec</span> p <span class="ot">=</span> <span class="dt">ConnSpec</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>  {<span class="ot"> username ::</span> <span class="op">!</span>(<span class="dt">Required</span> p <span class="dt">String</span>)</span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>  ,<span class="ot"> password ::</span> <span class="op">!</span>(<span class="dt">Required</span> p <span class="dt">String</span>)</span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>  ,<span class="ot"> port ::</span> <span class="op">!</span><span class="dt">Int</span> <span class="co">-- Optional and therefore requires a default.</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>  ,<span class="ot"> host ::</span> <span class="op">!</span><span class="dt">String</span> <span class="co">-- Optional and therefore requires a default.</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>  }</span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a><span class="ot">connSpecDefaults ::</span> <span class="dt">ConnSpec</span> <span class="dt">Defaults</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a>connSpecDefaults <span class="ot">=</span> <span class="dt">ConnSpec</span> {</span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Required fields are ()</span></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a>  username <span class="ot">=</span> (), password <span class="ot">=</span> (),</span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Defaulted fields need defaults specified</span></span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a>  port <span class="ot">=</span> <span class="dv">5432</span>, host <span class="ot">=</span> <span class="st">&quot;localhost&quot;</span></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a>  }</span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a><span class="co">-- Example func.</span></span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a><span class="ot">connect ::</span> <span class="dt">ConnSpec</span> <span class="dt">Complete</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</span>
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a>connect _ <span class="ot">=</span> <span class="fu">pure</span> ()</span></code></pre></div>
<p>Basic defaults module to support this approach:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE TypeFamilies #-}</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE DataKinds #-}</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE KindSignatures #-}</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="co">-- | Providing defaults for fields in a record.</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="kw">module</span> <span class="dt">Data.Defaults</span> <span class="kw">where</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a><span class="co">-- | Purpose of a data type.</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Purpose</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>  <span class="ot">=</span> <span class="dt">Defaults</span> <span class="co">-- For specifying defaults.</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>  <span class="op">|</span> <span class="dt">Complete</span> <span class="co">-- For making a complete record.</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a><span class="co">-- | Required fields are not usable from a defaults spec.</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="kw">family</span> <span class="dt">Required</span> (<span class="ot">p ::</span> <span class="dt">Purpose</span>) a <span class="kw">where</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Required</span> <span class="dt">&#39;Defaults</span> a  <span class="ot">=</span> () <span class="co">-- When we&#39;re defining defaults, required fields are ().</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Required</span> <span class="dt">&#39;Complete</span> a <span class="ot">=</span> a</span></code></pre></div>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2019-12-07 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sat, 07 Dec 2019 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Statically Checked Overloaded Strings]]></title><link>https://chrisdone.com/posts/statically-checked-overloaded-strings</link><guid>https://chrisdone.com/posts/statically-checked-overloaded-strings</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Statically Checked Overloaded Strings</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Statically Checked Overloaded Strings</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>This page demonstrates a trick I came up with which is defining
<code>IsString</code> for <code>Q (TExp a)</code>, where <code>a</code>
is <code>lift</code>-able. It allows you to write <code>$$("...")</code>
and have the string parsed at compile-time.</p>
<p>This offers a light-weight way to enforce compile-time constraints.
It’s basically <code>OverloadedStrings</code> with static checks.</p>
<p>This trick works already in old GHC versions.</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE TemplateHaskell, OverloadedStrings #-}</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Network.URI</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Path</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">PATHTH</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">SHA256TH</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">URITH</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="ot">uri ::</span> <span class="dt">URI</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>uri <span class="ot">=</span> <span class="op">$$</span>(<span class="st">&quot;https://releases.hashicorp.com/vault/1.2.2/vault_1.2.2_linux_amd64.zip&quot;</span>)</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a><span class="ot">sha256 ::</span> <span class="dt">SHA256</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>sha256 <span class="ot">=</span> <span class="op">$$</span>(<span class="st">&quot;7725b35d9ca8be3668abe63481f0731ca4730509419b4eb29fa0b0baa4798458&quot;</span>)</span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a><span class="ot">home ::</span> <span class="dt">Path</span> <span class="dt">Abs</span> <span class="dt">Dir</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>home <span class="ot">=</span> <span class="op">$$</span>(<span class="st">&quot;/home/chris&quot;</span>)</span></code></pre></div>
<p>Scroll down to see the modules <code>PATHTH</code>,
<code>SHA256TH</code> and <code>URITH</code>.</p>
<h2 id="versus-quasiquotes">Versus QuasiQuotes</h2>
<p>This is more light-weight and overloaded than, e.g.</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>[quasiquote|...|]</span></code></pre></div>
<p>which requires stating the name of the quoter you want (sometimes
you’d rather not), requires the <code>QuasiQuotes</code> extension, and
leaves syntax highlighters not sure how to highlight your content
properly.</p>
<h2 id="a-step-to-make-this-syntax-even-lighter">A step to make this
syntax even lighter</h2>
<p>It’d be nice to relax GHC’s parser a little to support
<code>$$"..."</code> to mean the same thing. This wouldn’t conflict with
any existing syntax that I am aware of, or of any existing plans or
proposals.</p>
<h2 id="pathth">PATHTH</h2>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE FlexibleInstances #-}</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="kw">module</span> <span class="dt">PATHTH</span> <span class="kw">where</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.String</span> (<span class="dt">IsString</span>(..))</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Language.Haskell.TH.Syntax</span> (<span class="dt">Q</span>, <span class="dt">TExp</span>(..), lift)</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Path</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">IsString</span> (<span class="dt">Q</span> (<span class="dt">TExp</span> (<span class="dt">Path</span> <span class="dt">Rel</span> <span class="dt">Dir</span>))) <span class="kw">where</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>  fromString <span class="ot">=</span> <span class="fu">fmap</span> <span class="dt">TExp</span> <span class="op">.</span> mkRelDir</span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">IsString</span> (<span class="dt">Q</span> (<span class="dt">TExp</span> (<span class="dt">Path</span> <span class="dt">Abs</span> <span class="dt">Dir</span>))) <span class="kw">where</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>  fromString <span class="ot">=</span> <span class="fu">fmap</span> <span class="dt">TExp</span> <span class="op">.</span> mkAbsDir</span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">IsString</span> (<span class="dt">Q</span> (<span class="dt">TExp</span> (<span class="dt">Path</span> <span class="dt">Rel</span> <span class="dt">File</span>))) <span class="kw">where</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>  fromString <span class="ot">=</span> <span class="fu">fmap</span> <span class="dt">TExp</span> <span class="op">.</span> mkRelFile</span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">IsString</span> (<span class="dt">Q</span> (<span class="dt">TExp</span> (<span class="dt">Path</span> <span class="dt">Abs</span> <span class="dt">File</span>))) <span class="kw">where</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>  fromString <span class="ot">=</span> <span class="fu">fmap</span> <span class="dt">TExp</span> <span class="op">.</span> mkAbsFile</span></code></pre></div>
<h2 id="sha256th">SHA256TH</h2>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE DeriveLift, FlexibleInstances, TemplateHaskell #-}</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="kw">module</span> <span class="dt">SHA256TH</span> <span class="kw">where</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span>           <span class="dt">Data.ByteString</span> (<span class="dt">ByteString</span>)</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.ByteString</span> <span class="kw">as</span> <span class="dt">S</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.ByteString.Base16</span> <span class="kw">as</span> <span class="dt">Hex</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span>           <span class="dt">Data.String</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span>           <span class="dt">Instances.TH.Lift</span> ()</span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span>           <span class="dt">Language.Haskell.TH.Syntax</span> (<span class="dt">Q</span>, <span class="dt">TExp</span>(..), <span class="dt">Lift</span>(..))</span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">SHA256</span> <span class="ot">=</span> <span class="dt">SHA256</span> <span class="dt">ByteString</span> <span class="kw">deriving</span> (<span class="dt">Eq</span>, <span class="dt">Ord</span>, <span class="dt">Lift</span>)</span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">IsString</span> (<span class="dt">Q</span> (<span class="dt">TExp</span> <span class="dt">SHA256</span>)) <span class="kw">where</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>  fromString i <span class="ot">=</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">if</span> <span class="fu">length</span> i <span class="op">==</span> <span class="dv">64</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>      <span class="kw">then</span> <span class="kw">case</span> Hex.decode (fromString i) <span class="kw">of</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>             (result, wrong)</span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a>               <span class="op">|</span> S.null wrong <span class="ot">-&gt;</span> <span class="fu">fmap</span> <span class="dt">TExp</span> (lift (<span class="dt">SHA256</span> result))</span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a>             _ <span class="ot">-&gt;</span> <span class="fu">fail</span> <span class="st">&quot;Invalid SHA256 format.&quot;</span></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a>      <span class="kw">else</span> <span class="fu">fail</span> <span class="st">&quot;Incorrect length for SHA256.&quot;</span></span></code></pre></div>
<h2 id="urith">URITH</h2>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE NamedFieldPuns, FlexibleInstances, TemplateHaskell #-}</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="kw">module</span> <span class="dt">URITH</span> <span class="kw">where</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.String</span> (<span class="dt">IsString</span>(..))</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Language.Haskell.TH.Syntax</span> (<span class="dt">Q</span>, <span class="dt">TExp</span>(..), lift)</span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Network.URI</span> (<span class="dt">URI</span>(..), parseURI, <span class="dt">URIAuth</span>(..))</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">IsString</span> (<span class="dt">Q</span> (<span class="dt">TExp</span> <span class="dt">URI</span>)) <span class="kw">where</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>  fromString i <span class="ot">=</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">case</span> parseURI i <span class="kw">of</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>      <span class="dt">Nothing</span> <span class="ot">-&gt;</span> <span class="fu">fail</span> (<span class="st">&quot;Invalid URI: &quot;</span> <span class="op">++</span> <span class="fu">show</span> i)</span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>      <span class="dt">Just</span> uri <span class="ot">-&gt;</span> liftURI uri</span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a><span class="ot">liftURI ::</span> <span class="dt">URI</span> <span class="ot">-&gt;</span> <span class="dt">Q</span> (<span class="dt">TExp</span> <span class="dt">URI</span>)</span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>liftURI <span class="dt">URI</span> {uriScheme, uriAuthority, uriPath, uriQuery, uriFragment} <span class="ot">=</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a>  <span class="fu">fmap</span> <span class="dt">TExp</span> [<span class="op">|</span><span class="dt">URI</span> {uriScheme, uriAuthority <span class="ot">=</span> <span class="op">$</span>(mauthority), uriPath, uriQuery, uriFragment}<span class="op">|</span>]</span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a>  <span class="kw">where</span></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a>    mauthority <span class="ot">=</span> <span class="fu">maybe</span> [<span class="op">|</span><span class="dt">Nothing</span><span class="op">|</span>] liftAuthority uriAuthority</span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a>    liftAuthority <span class="dt">URIAuth</span> {uriUserInfo, uriRegName, uriPort} <span class="ot">=</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a>      [<span class="op">|</span><span class="dt">Just</span> (<span class="dt">URIAuth</span> {uriUserInfo, uriRegName, uriPort})<span class="op">|</span>]</span></code></pre></div>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2019-11-13 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Wed, 13 Nov 2019 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Static Smart Constructors with Double Splices]]></title><link>https://chrisdone.com/posts/static-smart-constructors</link><guid>https://chrisdone.com/posts/static-smart-constructors</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Static Smart Constructors with Double Splices</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Static Smart Constructors with Double Splices</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>I plan on using this technique in at least one library, and so
thought it would be worth giving a name and a page dedicated to it, so
it can be linked to, instead of explained all over again.</p>
<hr />
<p>Sometimes you’re making a DSL and you need a way to make a smart
constructor that is static. You want to validate a value at compile-time
(possibly because the validation logic is harder to do in the
type-system or not ergonomic enough), and also return the run-time
value, without having to <code>lift</code> the whole structure from
TH-land to real-land. Perhaps your data type is a funky GADT with
functions in it, and therefore has no <code>Lift</code> instance
anyway!</p>
<p>One pattern to achieve the desired result is using a double
splice.</p>
<p>Here’s a really trivial example with strings:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> <span class="op">:</span>t <span class="op">$$</span>(<span class="op">$$</span>(notNull [<span class="op">||</span> thename <span class="op">||</span>]))</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="op">$$</span>(<span class="op">$$</span>(notNull [<span class="op">||</span> thename <span class="op">||</span>]))<span class="ot"> ::</span> <span class="dt">NonEmptyString</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> <span class="op">$$</span>(<span class="op">$$</span>(notNull [<span class="op">||</span> thename <span class="op">||</span>]))</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;Hello!&quot;</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> <span class="op">:</span>t <span class="op">$$</span>(<span class="op">$$</span>(notNull [<span class="op">||</span> thename_empty <span class="op">||</span>]))</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>interactive<span class="op">&gt;:</span><span class="dv">1</span><span class="op">:</span><span class="dv">4</span><span class="op">:</span> <span class="fu">error</span><span class="op">:</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>    • <span class="dt">Exception</span> when trying to run compile<span class="op">-</span>time code<span class="op">:</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>        <span class="dt">String</span> is <span class="fu">not</span> empty<span class="op">.</span></span></code></pre></div>
<p>Note that the <code>notNull</code> validator is well-typed (which is
commonly lacking in Template-Haskell, but here works well):</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> <span class="op">:</span>t notNull</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="ot">notNull ::</span> <span class="dt">Q</span> (<span class="dt">TExp</span> <span class="dt">String</span>) <span class="ot">-&gt;</span> <span class="dt">Q</span> (<span class="dt">TExp</span> (<span class="dt">Q</span> (<span class="dt">TExp</span> <span class="dt">NonEmptyString</span>)))</span></code></pre></div>
<p>The above uses typed splices <code>$$( ... )</code> and typed quotes
<code>[|| ... ||]</code>. However, you can implement the same technique
with regular <code>$(..)</code> and <code>[| .. |]</code> if typed
splices are too long for you.<a href="#fn1" class="footnote-ref"
id="fnref1" role="doc-noteref"><sup>1</sup></a></p>
<p>Here is the implementation:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE TemplateHaskell #-}</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Language.Haskell.TH</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Language.Haskell.TH.Instances</span> ()</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Language.Haskell.TH.Syntax</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Language.Haskell.TH.Lift</span> ()</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="co">-- Here is a simple validator.</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a><span class="ot">valueFine ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Bool</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>valueFine <span class="ot">=</span> <span class="fu">not</span> <span class="op">.</span> <span class="fu">null</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a><span class="co">-- The static smart constructor with the nested expressions returned.</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a><span class="ot">notNull ::</span> <span class="dt">Q</span> (<span class="dt">TExp</span> <span class="dt">String</span>) <span class="ot">-&gt;</span> <span class="dt">Q</span> (<span class="dt">TExp</span> (<span class="dt">Q</span> (<span class="dt">TExp</span> <span class="dt">NonEmptyString</span>)))</span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>notNull q <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>  <span class="dt">TExp</span> expr <span class="ot">&lt;-</span> q</span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a>  <span class="kw">let</span> name <span class="ot">=</span> <span class="dt">&#39;NonEmptyString</span></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a>  [<span class="op">||</span> <span class="kw">if</span> valueFine <span class="op">$$</span>(q)</span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true" tabindex="-1"></a>      <span class="kw">then</span> <span class="dt">TExp</span> <span class="op">&lt;$&gt;</span> (appE (conE name) (<span class="fu">pure</span> expr))</span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true" tabindex="-1"></a>      <span class="kw">else</span> <span class="fu">error</span> <span class="st">&quot;String is not empty.&quot;</span> <span class="op">||</span>]</span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true" tabindex="-1"></a><span class="co">-- A smart constructor.</span></span>
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">NonEmptyString</span> <span class="ot">=</span> <span class="dt">NonEmptyString</span> <span class="dt">String</span></span>
<span id="cb3-25"><a href="#cb3-25" aria-hidden="true" tabindex="-1"></a> <span class="kw">deriving</span> (<span class="dt">Show</span>)</span>
<span id="cb3-26"><a href="#cb3-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-27"><a href="#cb3-27" aria-hidden="true" tabindex="-1"></a><span class="co">-- Some example values.</span></span>
<span id="cb3-28"><a href="#cb3-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-29"><a href="#cb3-29" aria-hidden="true" tabindex="-1"></a><span class="ot">thename ::</span> [<span class="dt">Char</span>]</span>
<span id="cb3-30"><a href="#cb3-30" aria-hidden="true" tabindex="-1"></a>thename <span class="ot">=</span> <span class="st">&quot;Hello!&quot;</span></span>
<span id="cb3-31"><a href="#cb3-31" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-32"><a href="#cb3-32" aria-hidden="true" tabindex="-1"></a><span class="ot">thename_empty ::</span> [<span class="dt">Char</span>]</span>
<span id="cb3-33"><a href="#cb3-33" aria-hidden="true" tabindex="-1"></a>thename_empty <span class="ot">=</span> <span class="st">&quot;&quot;</span></span></code></pre></div>
<p>Thanks to <a href="https://mgsloan.com/">Michael Sloan</a> for the
idea to have an expression return another expression.</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>In my case, the length doesn’t matter
too much, just the correctness properties, because it’ll be used once or
twice per codebase to validate a much larger DSL AST.<a href="#fnref1"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2019-08-22 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Thu, 22 Aug 2019 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Client-side web programming in Haskell: A retrospective]]></title><link>https://chrisdone.com/posts/clientside-programming-haskell</link><guid>https://chrisdone.com/posts/clientside-programming-haskell</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Client-side web programming in Haskell: A
retrospective</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Client-side web programming in Haskell: A retrospective</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>At the beginning of this decade (2010), a few of us Haskellers were
exploring how best to do client-side web programming. We didn’t want to
write JavaScript. There’s a surprising number of techniques we tried to
avoid doing so. There was work coming from academia and industry. Here’s
a history of my own experience in this problem space.</p>
<p>In 2008, Joel Bjornson and Niklas Broberg published <a
href="http://hackage.haskell.org/package/HJScript-0.4">HJScript</a>,
which was a Haskell EDSL for writing JavaScript. It had the ability to
express typed JS via a GADT. I used it in 2010 on a project to make
limited DOM manipulations. I wrote <a
href="https://github.com/benarmston/hpaste/blob/master/src/HJScript/Objects/JQuery/Extra.hs">a
wrapper around jquery</a>, for example. It was nice to write in Haskell,
but it was also mental overhead to write in two languages at once (it
still had JavaScript’s semantics). In the end I went back to using plain
JavaScript.</p>
<p>Around 2010, Adam Chlipala announces <a
href="http://impredicative.com/ur/">Ur</a>, a radical web dev language
with row types, which compiles to both native object code and
JavaScript, fairly transparently, embedding both HTML and SQL syntax
into the language. I am both impressed by the simplicity of the code and
correctness, and horrified by some of the code involving
metaprogramming. The row types documentation frankly scares me away.
After trying out some examples, I don’t return to it.<a href="#fn1"
class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> To
this day I am still interested in this architecture.</p>
<p>Some time in 2011, <a href="http://opalang.org/">Opa</a> appears, but
apparently nobody wants to learn yet another server-side language. I
don’t know anyone who has used this in production.</p>
<p>In August 2011, I was <a
href="https://chrisdone.com/posts/ghcjs/">experimenting with GHCJS</a>,
notes which later I copied over to the Haskell Wiki under the name <a
href="http://www.haskell.org/haskellwiki/The_JavaScript_Problem">The
JavaScript Problem</a>. At the time, I encountered bugs and runtime
difficulties with some simple GHCJS experiments. From there I mostly
abandoned it as a choice, underwhelmed.</p>
<p>In December 2011, I came up with <a
href="https://chrisdone.com/posts/ji-haskell-web/">ji</a>, a means of
controlling a web page from a Haskell web service, which later was
renamed to <a
href="http://hackage.haskell.org/package/threepenny-gui">threepenny-gui</a>
and is now maintained by Heinrich Apfelmus to this day. It turned out to
be extremely powerful; I wrote an IRC-like app in which people could
chat on a web page in a page of code. However, in the end it wasn’t to
be for mainstream web dev; a good point that Michael Snoyman made was
that it had a high server-side cost, and did not scale to multiple
servers. In the end, threepenny-gui is a great library to consider for
cross-platform desktop programs (such as with Electron).</p>
<p>In January 2012, I <a
href="https://web.archive.org/web/20120623212312/https://chrisdone.com/posts/2012-01-06-uhc-javascript.html">experimented
with UHC</a>. My experience was similar to GHCJS. I tried some basic
experiments, but the heavy runtime that came along with it wasn’t
attractive to me. It felt like I would spend half my time maintaining
<em>it</em> aside from the applications I might’ve written with it.</p>
<p>In March 2012, <a
href="https://www.reddit.com/r/haskell/comments/rkyoa/my_thesis_is_finally_complete_elm_concurrent_frp/">Evan
Czaplicki announced that his thesis on Elm</a> was complete. The
emphasis on FRP drew me (and probably others, at the time) away from it,
as FRP was seen as green, experimental and impractical. Indeed, in 2016,
Evan wrote <a href="https://elm-lang.org/news/farewell-to-frp">A
Farewell to FRP</a>. Elm used to be all about FRP, and then it wasn’t.
“I might argue that Elm was <em>never</em> about FRP,” writes Evan. I
imagine this contributed to Elm’s growing success. Today, Elm is not my
choice because it lacks type-classes.</p>
<p>In April 2012, Michael Snoyman was doing some very interesting
explorations into <a
href="https://www.yesodweb.com/blog/2012/04/client-side">writing
high-level Haskell code that would produce limited JavaScript</a>
transparently to produce dynamic page changes (and <a
href="https://www.yesodweb.com/blog/2012/04/yesod-js-todo">here</a>). To
this day I am still interested in exploring this path.</p>
<p>In May 2012, Anton Ekblad announces his <a
href="https://www.reddit.com/r/haskell/comments/tw997/haste_haskell_to_javascript_compiler/">Haste
compiler</a>, a Haskell-to-JavaScript compiler like GHCJS which also
goes via GHC Core, but doesn’t try as hard to implement the GHC runtime
in the browser. It’s the driver for <a
href="https://ekblad.cc/pubs/thesis.pdf">his PhD thesis</a>
<em>Functional EDSLs for Web Applications</em>. We never really give it
a try on a real project.</p>
<p>In September 2012, I <a
href="https://chrisdone.com/posts/fay/">authored the Fay compiler</a>,
which was a Haskell subset compiler. I was inspired by Elm and Roy. The
idea was to re-use the GHC compiler for type-checking, and separately do
codegen with haskell-src-exts without type information. As a result, it
didn’t support type-classes, and didn’t compile basically any of
Hackage. But it was useful enough and simple enough to get use in the
community and at FP Complete, where we used it for the web-based IDE,
which had about 15k lines of Fay code in it.</p>
<p>To add some additional context, at the time, I wrote:</p>
<blockquote>
<p>My approach to the problem, as with everyone else, has long been:
well, we can’t do anything about it, let’s just wait for Google to
complete their native client project and hope that it breaks the
market.</p>
</blockquote>
<p>In March 2013, Andrew Gill and Jan Bracker published their <a
href="https://github.com/ku-fpg/sunroof-compiler">sunroof</a> project,
which was a HJScript on steroids, and which actually seemed compelling
to some people at the time. I’m not sure anybody ever used it in
production. I think this was the last ember of effort in JavaScript DSLs
in Haskell, and it flickered out.</p>
<p>In October 2013, Phil Freeman <a
href="https://www.reddit.com/r/haskell/comments/1pkzd0/show_reddit_my_weekend_project_purescript/">announced
PureScript</a>, a strict, pure, Haskell-like language with
row-polymorphism that compiled to JS with no runtime. I think it was
seen as an interesting concept, but it wasn’t until a few years later
that PureScript came back on my radar as a practical language.</p>
<p>Around late 2014, at FP Complete, we were ready to try GHCJS again.
Luite Stegeman had been working hard on it and bringing it to life. In
August of 2014, Simon Meier released <a
href="https://github.com/meiersi/blaze-react">blaze-react</a>, which was
a GHCJS-based React.js binding with an Elm-style of processing events as
a sum type. This re-ignited interest, at least from my perspective.
Although we were doubtful that the Elm architecture scaled. Fay is
officially out of the picture.</p>
<p>In April 2015, we whipped up a similar package called <a
href="https://github.com/fpco/ghcjs-react">ghcjs-react</a>, which
implemented React without the Om-style handling of state via a
lens/cursor (Redux appeared around the same time, doing a similar
thing). I wrote the experimental <a
href="https://github.com/fpco/stackage-view#introduction">stackage-view</a>
tool based on this library; which we thought would be a good litmus test
both of GHCJS and our react bindings. It was awkward, but when it
worked, it worked well.</p>
<p>I will note that, we’re slow on the up-take. React.js was released in
May 2013, and we twigged onto it as a good way to write UIs around 2015.
Partly in thanks to the Clojure library <a
href="https://github.com/omcljs/om">Om</a>.</p>
<p>Also in April 2015, Ryan Trinkle <a
href="https://www.reddit.com/r/haskell/comments/31rat9/reflex_practical_functional_reactive_programming/">presented
his new library Reflex</a>, with a very compelling talk. I wrote at the
time:</p>
<blockquote>
<p>The video is quite comprehensible, it may be the first FRP demo I’ve
seen that isn’t mired in nomenclature I don’t understand, builds up from
small components but doesn’t bore me with unrealistic counters or
sliders, and has some real world products written in it. 10/10 talk,
count me interested.</p>
</blockquote>
<p>In Jan 2016, some of the FP Complete team started learning Reflex and
using it on a large client pilot project. Experience reports can be
summed up as: mind-bending but eye-opening in the same way learning
Haskell was. Awkward to express some things, but also unquestionably
composable and re-usable. Groans and grumbles about GHCJS being heavy,
slow and brittle.</p>
<p>In Jan 2015, Slam Data start their <a
href="https://github.com/slamdata/purescript-halogen">Halogen
library</a> for PureScript.</p>
<p>During 2015 and 2016, Tim Dysinger is a growing advocate for
PureScript at FP Complete internal discussions.</p>
<p>In October 2016, I’m using PureScript with React.js bindings to make
internal demo UIs for FP Complete. I’m enjoying it a lot. We have an
engineering meeting about PureScript vs other technologies.</p>
<p>December 2016, Michael Snoyman comments on Slack:</p>
<blockquote>
<p>PureScript seems like it’s doing everything right.</p>
</blockquote>
<p>April 2017, Michael Snoyman <a
href="https://github.com/snoyberg/purescript-halogen-onetimepad">writes
a PureScript + Halogen version</a> of his one-time-pad toy app. At the
time, I’m not interested in Halogen. It looks complicated, and I’m still
enjoying React.</p>
<p>August 2018, it has been decided that we will use PureScript to build
a UI for a cryptocurrency client at FP Complete. I’m happy about that. I
decide to give Halogen a try. After initial pain, I end up loving
it.</p>
<p>November 2018, we briefly discuss whether Rust+WASM is a new possible
contender. We’ll have to wait for WASM to become supported on all
browsers, especially mobile.</p>
<p>December 2018, we have a dev meeting on the state of frontend
development. Our meeting notes are long and detailed, the brief summary:
we don’t feel comfortable with GHCJS, Reflex is great but also costly
(double novelty budget), Halogen is a better architecture than Elm.
PureScript and Halogen come out as the best possible choice. Other
things considered: ClojureScript, TypeScript, Rust, <a
href="https://reasonml.github.io/">ReasonML</a>, Elm, <a
href="https://ocsigen.org/js_of_ocaml/3.1.0/manual/overview">OCaml</a>.</p>
<p>As of 2019, I was personally still using PureScript with Halogen.</p>
<p>In 2023 have pushed for our team at Artificial Labs to start trying
<a href="https://htmx.org/">Htmx</a> combined with Haskell. So far, the
experience is good: we like writing Haskell. There are some downsides to
Htmx, however: inheritence is a bad idea, request queues have bad
defaults and are hard to manage, and htmx intuitions (such as related to
request queues) don’t play well with morphdom. I’ve written a full post
about it <a
href="https://chrisdone.com/posts/htmx-critique/">here.</a></p>
<p>As of 2024, I still think that <a
href="https://chrisdone.com/posts/halogen-is-better-than-react/">Halogen
is better than React at everything</a>, and that Halogen is the best way
to write an SPA that I have experienced, but I haven’t used it since
2022.</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>In retrospect, if it was marketed in
the same way Elm was, and less “academic”, it may have taken off. But it
could just be that it arrived before anyone was ready to try alternative
languages. Or perhaps its syntax could have matched Haskell.
Comparatively, PureScript has row types too.<a href="#fnref1"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2019-07-25 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Thu, 25 Jul 2019 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[German Naming Convention]]></title><link>https://chrisdone.com/posts/german-naming-convention</link><guid>https://chrisdone.com/posts/german-naming-convention</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>German Naming Convention</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>German Naming Convention</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<h2 id="introduction">Introduction</h2>
<p>As a software consultant, mostly contributing code to other company’s
codebases, and doing code review, I’ve seen about thirty separate
codebases over the past half dozen years, and there’s one thing that
could make my life much easier: better naming convention.</p>
<p>Jump to <a href="#german-naming-convention">German Naming
Convention</a> to skip straight to it.</p>
<h2 id="expect-the-violent-psychopath">Expect the Violent
Psychopath</h2>
<p>You’re trying to tell a story with your code. Your code should tell
that story clearly, not cryptically, for an audience besides yourself. A
good yardstick for deciding what kind of audience you are writing for is
to imagine someone who has a familiarity with your domain but not your
program’s take on the domain. I think programmers forget that, as they
are authors, they have readers.</p>
<p>A famous and regularly quoted piece of advice, from the mailing list
<code>comp.lang.c</code> in 1991, John F. Woods wrote:</p>
<blockquote>
<p>Always code as if the guy who ends up maintaining your code will be a
violent psychopath who knows where you live. Code for readability.</p>
</blockquote>
<p>It’s hard to put it better than that.</p>
<h2 id="naming-tropes">Naming Tropes</h2>
<p>There are some common naming conventions which are departures from
plain English, usually in the interest of brevity:</p>
<ol type="1">
<li>Abbreviations: when words are abbreviated such as <code>fct</code>
for “function”, <code>dfn</code> for “definition”, <code>ctx</code> for
“context.”</li>
<li>It’s All Greek To Me: using simply <code>a</code>, <code>x</code>,
etc. as in mathematics.</li>
<li>“Hungarian” notation: any prefix or suffix notation in which a
single letter is used to refer to a <em>type</em> or <em>property</em>
of the variable, as in sigils like <code>$foo</code> (“scalar foo”),
<code>lpszFoo</code> (“long pointer string zero-terminated”), or
<code>fooL</code> (list of foo).</li>
<li>Acronyms: using initial letters to refer to concepts:
<code>throwVE</code> (“throw validation error”).</li>
</ol>
<p>Most of these are unnecessary<a href="#fn1" class="footnote-ref"
id="fnref1" role="doc-noteref"><sup>1</sup></a> and/or harmful.</p>
<h2 id="its-all-greek-to-me">It’s All Greek To Me</h2>
<p>A word on this convention. Single letter naming comes from
mathematical tradition; it means “there isn’t a good noun for this
because it’s general”. A person of X height. In some cases, this is
actually reasonable. Consider:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>identity x <span class="ot">=</span> x</span></code></pre></div>
<p>The <code>identity</code> function isn’t enhanced by calling its
parameter <code>thing</code>; it literally doesn’t matter what it is,
especially in some typed languages<a href="#fn2" class="footnote-ref"
id="fnref2" role="doc-noteref"><sup>2</sup></a>. In fact, one could
argue that it’s harmful to try to using a meaningful English name.</p>
<p>However, anywhere that your variables have some meaning, by using
“Greek convention”, you’re throwing away information that could help
someone to digest your code better. You’re not trying to fit your code
on a napkin.</p>
<h2 id="german-naming-convention">German Naming Convention</h2>
<p>This is what I consider good naming convention. I discovered this
convention while working with a German colleague, who, I’d always joked,
uses long variable names, and almost never abbreviates anything.
However, the more I read his code, the more I realised I was able to
read the story he was trying to tell, and appreciated it a lot: Using as
many words as necessary to clearly name something.
<em>Everything</em>.</p>
<p>I called this “German” naming convention as a reference to the fact
that the German language is known for its compound words, which can
become comically long and specific at times. Some examples include,
<em>Betäubungsmittelverschreibungsverordnung</em> (“regulation requiring
a prescription for an anaesthetic”),
<em>Rechtsschutzversicherungsgesellschaften</em> (““legal protection
insurance companies”), and the 1999 German “Word of the Year”:
<em>Rindfleischetikettierungsüberwachungsaufgabenübertragungsgesetz</em>
(“beef labelling regulation and delegation of supervision law”).</p>
<p>Don’t write <code>fopen</code> when you can write
<code>openFile</code>. Write <code>throwValidationError</code> and not
<code>throwVE</code>. Call that name <code>function</code> and not
<code>fct</code>. That’s German naming convention. Do this and your
readers will appreciate it.</p>
<h2 id="isomorphic-naming">Isomorphic Naming</h2>
<p>This convention complements German naming convention completely.</p>
<p><em>Isomorphic naming</em> is to say that the name of the variable is
the same form<a href="#fn3" class="footnote-ref" id="fnref3"
role="doc-noteref"><sup>3</sup></a> of the name of the type. A simple
heuristic, in other words: <strong>just use the name of the
type.</strong></p>
<p>Here’s a real sample where better naming convention would make this
easier to read without being a cryptographer:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>updateColExp</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="ot">  ::</span> <span class="dt">QualifiedTable</span> <span class="ot">-&gt;</span> <span class="dt">RenameField</span> <span class="ot">-&gt;</span> <span class="dt">ColExp</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> <span class="dt">ColExp</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>updateColExp qt rf (<span class="dt">ColExp</span> fld val) <span class="ot">=</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">ColExp</span> updatedFld <span class="op">&lt;$&gt;</span> updatedVal</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">...</span></span></code></pre></div>
<p>Look at this naming convention. This may be appropriate if you’re in
some kind of code golfing competition, but I can’t even pronounce these
names. Applying the type-based naming heuristic, we get:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>updateColumnExpression</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="ot">  ::</span> <span class="dt">QualifiedTable</span> <span class="ot">-&gt;</span> <span class="dt">RenameField</span> <span class="ot">-&gt;</span> <span class="dt">ColumnExpression</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> <span class="dt">ColumnExpression</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>updateColumnExpression qualifiedTable renameField (<span class="dt">ColumnExpression</span> field value) <span class="ot">=</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">ColumnExpression</span> updatedField <span class="op">&lt;$&gt;</span> updatedValue</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">...</span></span></code></pre></div>
<p>Look, it’s readable, plain English! Isn’t this a huge improvement?
Any maintainer reading this code can read each variable and know what it
is. I can even pronounce the names out loud.</p>
<p>Note that this convention only works well when your <em>types</em>
are well-named too, by German naming convention.</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Especially for e.g. Haskell, C#,
Rust, TypeScript or Java. I give more legroom to unityped languages like
Python, Perl, JavaScript, etc. because your editor typically can’t tell
you the type of a name, and there typically isn’t a lexical indication
of the type anywhere nearby, like a type signature.<a href="#fnref1"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p><a
href="https://www.well-typed.com/blog/2015/05/parametricity/">Parametricity</a>
ensures that this really does not matter in a formal theory sense.<a
href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn3" role="doc-endnote"><p>From iso- “equal, identical” +
-morphic, from Greek morphē “form, shape,” See the Etymology Online
entry for <a
href="https://www.etymonline.com/word/isomorphic">isomorphic</a>.<a
href="#fnref3" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2019-06-07 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Fri, 07 Jun 2019 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Dynamically typed Haskell]]></title><link>https://chrisdone.com/posts/dynamically-typed-haskell</link><guid>https://chrisdone.com/posts/dynamically-typed-haskell</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Dynamically typed Haskell</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Dynamically typed Haskell</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>For a while I’ve been intending to make a package that provides a
dynamic type and a trivial means to read/write that type to/from
CSV/JSON and web requests. I thought that this would be enough to
provide a convenient package for doing exploratory work against unknown
data.</p>
<p>In Haskell, typically we would model all the types of the data that
we want to work with ahead of time. That’s inconvenient if you want to
just quickly look through a JSON or CSV file and do some quick
calculation: that’s where you would reach for Python. Even type
providers<a href="#fn1" class="footnote-ref" id="fnref1"
role="doc-noteref"><sup>1</sup></a> don’t provide that level of
convenience.</p>
<p>I thought, well, it’s pretty easy to define a <code>Dynamic</code>
type which is an instance of a bunch of classes like <code>Num</code>,
<code>FromCSV</code> and <code>FromJSON</code>, etc. with which one
could program like they do in a dynamically typed language.<a
href="#fn2" class="footnote-ref" id="fnref2"
role="doc-noteref"><sup>2</sup></a> But I had other things to work
on.</p>
<p>April 1st came around the corner, so I decided that would be a good
time to publish such a package then, that way any detractors could be
dismissed by “April fools!” <a
href="https://github.com/chrisdone/dynamic">Here is the package</a> in
all its glory. I have actually already used it several times to play
with some public APIs. It’s nice to be able to use regular Haskell once
I want to actually write some logic. I can see myself using this fairly
often.</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Such as <a
href="https://docs.microsoft.com/en-us/dotnet/fsharp/tutorials/type-providers/">those
in F#</a>: An F# type provider is a component that provides types,
properties, and methods for use in your program.<a href="#fnref1"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p>Oddly, no one seems to have done
this. There are plenty of “dynamic type” packages in Haskell, but their
authors couldn’t resist making it well-typed in some way.<a
href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2019-04-06 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sat, 06 Apr 2019 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Web engines in Haskell]]></title><link>https://chrisdone.com/posts/web-engines</link><guid>https://chrisdone.com/posts/web-engines</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Web engines in Haskell</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Web engines in Haskell</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<h2 id="vado">Vado</h2>
<p><a href="https://github.com/chrisdone/vado">Vado</a> is a Haskell web
browser I wrote in two evenings that is the culmination of:</p>
<ul>
<li>Wanting to demonstrate some good Haskell libraries.</li>
<li>That a cross-platform sdl2 package in Haskell is quite usable and
works on Linux, OS X and Windows.</li>
<li>That a simple web browser like something from the 90s was pretty
straight-forward to implement.</li>
</ul>
<p>In that I think the project is a success. The code isn’t anything
special, and it’s not beautiful, or efficient.</p>
<p>Quoting the page:</p>
<blockquote>
<p>This is a demonstration program that is able to load a web page up
and render it like in the early 90’s. It supports laying out text,
different font sizes for headings, inline and block elements,
hyperlinks, bold and italics. It supports mouse-wheel scrolling,
too.</p>
</blockquote>
<blockquote>
<p>I wrote this in a couple evenings, because it seemed straight-forward
to do so given the libraries available today. That’s a good sign for
Haskell. Also, there’s an inarticulate gut feeling I have that tells me
maybe it’s worth celebrating these days in which the web is still
viewable in its simplest, earliest form.</p>
</blockquote>
<h2 id="fudgets">Fudgets</h2>
<p>Meanwhile, I found that in 1994 there was <a
href="http://www.cse.chalmers.se/~hallgren/wwwbrowser.html">a Haskell
web browser by the Fudgets folk.</a></p>
<p>Quoting from the page in case it goes offline one day:</p>
<blockquote>
<p>WWWBrowser is a prototype WWW Browser implemented in the functional
programming language Haskell using the Fudget Library. WWWBrowser was
mostly implemented in 1994, when NCSA Mosaic was the dominant web
browser, and some updates have been made in 1997 and 1998.</p>
<p>WWWBrowser is also described in the chapter WWWBrowser – a WWW client
in the Fudgets Thesis.</p>
<ul>
<li>It supports forms.</li>
<li>It supports inlined images, like [:-)]. The GIF, PNG, JPEG, PNM and
XBM formats are recognized. PNM and GIF images are processed with
Haskell code. For the other formats, conversions are done with external
programs (from the PBMPLUS package). Dithering (or just color remapping)
is done by the WWWBrowser itself. (Unfortunately this gets a bit slow
for large images.) (See The Graphics File Format Page (2D specs) for
info on these and other image file formats.)</li>
<li>Inlined images are fetched in parallel. This means that pages
containing many small inlined images, such as IconBAZAAR, load faster in
WWWBrowser (in spite of the slow image processing) than in browsers,
like NCSA Mosaic (the dominating browser at the time when WWWBrowser was
developed), that fetch one image at a time.</li>
<li>It understands most of the protocols used for information retrieval
in WWW: http, ftp, nntp (news), gopher and telnet. It can also read
files and directories in the local file system. When talking to nntp and
ftp servers, it uses the same connection for several transfers rather
than connecting/disconnecting for every document retrieved.</li>
<li>It can connect to the Internet directly or through a proxy.</li>
</ul>
</blockquote>
<p>Hard to believe there was a pretty viable looking browser back then,
and in Haskell! It’s very impressive! The Fudgets work really is still
amazing and interesting to this day. I’ve started and will continue to
read through their documentation and ideas.</p>
<h2 id="reflecting-on-browsers">Reflecting on browsers</h2>
<p>You might think (or not think) that a cross-platform browser in 600
lines is pretty good. But this exercise also helps illuminate to me the
gulf that exists between what we had in the 90s, and what people expect
today. Vado doesn’t do anything that you would expect from a modern web
browser. Here are just some things that I can think of:</p>
<ul>
<li>Support cookies</li>
<li>Loading images</li>
<li>Caching of assets</li>
<li>History forward/back navigation</li>
<li>Handle the plethora of custom form inputs (dates, integers, sliders,
dropdowns, multiselects, basic text, textarea, buttons, etc.)</li>
<li>Parse and handle even old CSS 2, nevermind modern CSS 3 (and custom
fonts)</li>
<li>Parse and handle plain old JavaScript, not to mention more modern
JS</li>
<li>Provide the large surface area of API for JavaScript, including but
not limited to
<ul>
<li>The basic DOM API with all its events (keyboards, timers, mouse,
form inputs)</li>
<li>Drawing APIs (canvas)</li>
<li>Network APIs (AJAX, websockets)</li>
<li>Cookies and web storage</li>
<li>Window APIs (navigation, refreshing, etc.), alerts, prompts</li>
<li>Audio, video elements, web workers, …</li>
</ul></li>
<li>The whole UI around managing your history, addresses, bookmarks,
cookies, etc. that they’re expected to have.</li>
</ul>
<p>Also to do all of these things efficiently, securely, and in a way
that matches (quirks and all) with the way other engines are expected to
render. And then if you want anyone to continue using it, you have to
keep on keeping up with the web, aside from the high maintenance costs
of a basic web browser.</p>
<h2 id="approaching-a-mono-culture">Approaching a mono culture</h2>
<p>At present we have an unfortunate state of affairs, we used to have
these rendering engines:</p>
<ul>
<li>Blink (Chromium)</li>
<li>KHTML (Konqueror)</li>
<li>WebKit (Safari)</li>
<li>Trident (IE)</li>
<li>EdgeHTML (Edge)</li>
<li>Presto (Opera)</li>
<li>Gecko (Firefox)</li>
</ul>
<p>Unfortunately, they’ve been collapsed down to:</p>
<ul>
<li>Blink (Chromium, Opera, Edge) – controlled by Google</li>
<li>KHTML (Konqueror) – controlled by KDE</li>
<li>WebKit (Safari) – controlled by Apple</li>
<li>Gecko (Firefox) – controlled by Mozilla</li>
</ul>
<p>I hope this trend doesn’t continue. Google are already attempting to
destroy email as we know it, using their power afforded by GMail.
Mozilla are pretty bent on keeping the web diverse and competitive. I’m
not sure whether Apple will follow Microsoft’s and Opera’s lead and move
to Blink for Safari.</p>
<p>We’ll see.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2019-04-05 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Fri, 05 Apr 2019 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Lazy list length]]></title><link>https://chrisdone.com/posts/lazy-list-length</link><guid>https://chrisdone.com/posts/lazy-list-length</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Lazy list length</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Lazy list length</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>To get the length of a list like</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="fu">length</span> [<span class="dv">1</span><span class="op">..</span><span class="dv">10</span>] <span class="op">==</span> <span class="dv">10</span></span></code></pre></div>
<p>You have to walk the whole list to check that it’s indeed of length
<code>10</code>.</p>
<p>Another way is to define a natural number in peano arithmetic
style:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Nat</span> <span class="ot">=</span> <span class="dt">Zero</span> <span class="op">|</span> <span class="dt">Add1</span> <span class="dt">Nat</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  deriivng (<span class="dt">Ord</span>, <span class="dt">Eq</span>)</span></code></pre></div>
<p>So</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- 0 = Zero</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="co">-- 1 = Add1 Zero</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="co">-- 2 = Add1 (Add1 Zero)</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="co">-- 3 = Add1 (Add1 (Add1 Zero))</span></span></code></pre></div>
<p>We define a trivial instance of <code>Num</code> for it:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Num</span> <span class="dt">Nat</span> <span class="kw">where</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Zero</span> <span class="op">+</span> y <span class="ot">=</span> y</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Add1</span> x <span class="op">+</span> y <span class="ot">=</span> x <span class="op">+</span> (<span class="dt">Add1</span> y)</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>  <span class="fu">fromInteger</span> <span class="dv">0</span> <span class="ot">=</span> <span class="dt">Zero</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>  <span class="fu">fromInteger</span> n <span class="ot">=</span> <span class="dt">Add1</span> (<span class="fu">fromInteger</span> (n <span class="op">-</span> <span class="dv">1</span>))</span></code></pre></div>
<p>Now we can use <code>genericLength</code> on a list like this.
Equal-sized lists:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> genericLength [<span class="dv">1</span><span class="op">..</span><span class="dv">3</span>] <span class="op">==</span> (genericLength [<span class="dv">1</span><span class="op">..</span><span class="dv">3</span>]<span class="ot"> ::</span> <span class="dt">Nat</span>)</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="dt">True</span></span></code></pre></div>
<p>With infinite lists:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> genericLength [<span class="dv">1</span><span class="op">..</span><span class="dv">3</span>] <span class="op">&lt;</span> (genericLength [<span class="dv">1</span><span class="op">..</span>]<span class="ot"> ::</span> <span class="dt">Nat</span>)</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="dt">True</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> genericLength [<span class="dv">1</span><span class="op">..</span><span class="dv">3</span>] <span class="op">==</span> (genericLength [<span class="dv">1</span><span class="op">..</span>]<span class="ot"> ::</span> <span class="dt">Nat</span>)</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="dt">False</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> genericLength [<span class="dv">1</span><span class="op">..</span><span class="dv">3</span>] <span class="op">&gt;</span> (genericLength [<span class="dv">1</span><span class="op">..</span>]<span class="ot"> ::</span> <span class="dt">Nat</span>)</span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a><span class="dt">False</span></span></code></pre></div>
<p>We didn’t have to walk the whole list to compare its length with a
finite number. That’s pretty cool.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2018-08-23 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Thu, 23 Aug 2018 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Type inequality operator]]></title><link>https://chrisdone.com/posts/type-inequality-operator</link><guid>https://chrisdone.com/posts/type-inequality-operator</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Type inequality operator</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Type inequality operator</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Here’s a fun trick. If you want to define a function that accepts
everything but one type, you can make a type family like this. If the
two types unify, we produce the type <code>'False</code> of kind
<code>Bool</code>.</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="kw">family</span> a <span class="op">/~</span> b <span class="kw">where</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  a <span class="op">/~</span> a <span class="ot">=</span> <span class="dt">&#39;False</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  _ <span class="op">/~</span> _ <span class="ot">=</span> <span class="dt">&#39;True</span></span></code></pre></div>
<p>You can use it like this:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ot">foo ::</span> (<span class="dt">Integral</span> i, i <span class="op">/~</span> <span class="dt">Word8</span> <span class="op">~</span> <span class="dt">&#39;True</span>) <span class="ot">=&gt;</span> i <span class="ot">-&gt;</span> ()</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>foo <span class="ot">=</span> <span class="fu">undefined</span></span></code></pre></div>
<p>The argument can be any type <code>i</code> that doesn’t unify with
<code>Word8</code>. So this type-checks:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>bar <span class="ot">=</span> foo (<span class="fu">undefined</span><span class="ot"> ::</span>  <span class="dt">Int</span>)</span></code></pre></div>
<p>But this doesn’t:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>bad <span class="ot">=</span> foo (<span class="fu">undefined</span><span class="ot"> ::</span> <span class="dt">Word8</span>)</span></code></pre></div>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Couldn&#39;t</span> match <span class="kw">type</span> ‘<span class="dt">&#39;False</span>’ with ‘<span class="dt">&#39;True</span>’<span class="op">.</span></span></code></pre></div>
<p>Not that I have a use for this. It was just discussed at work.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2018-06-19 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Tue, 19 Jun 2018 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Fast Haskell: Competing with C at parsing XML]]></title><link>https://chrisdone.com/posts/fast-haskell-c-parsing-xml</link><guid>https://chrisdone.com/posts/fast-haskell-c-parsing-xml</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Fast Haskell: Competing with C at parsing XML</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Fast Haskell: Competing with C at parsing XML</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>In this post we’re going to look at parsing XML in Haskell, how it
compares with an efficient C parser, and steps you can take in Haskell
to build a fast library from the ground up. We’re going to get fairly
detailed and get our hands dirty.</p>
<!-- establish context -->
<h2 id="a-new-kid-on-the-block">A new kid on the block</h2>
<p>A few weeks ago Neil Mitchell posted <a
href="http://neilmitchell.blogspot.co.uk/2016/12/new-xml-parser-hexml.html">a
blog post</a> about a new XML library that he’d written. The parser is
written in C, and the API is written in Haskell which uses the C
library. He writes that it’s very fast:</p>
<blockquote>
<p>Hexml has been designed for speed. In the very limited benchmarks
I’ve done it is typically just over 2x faster at parsing than Pugixml,
where Pugixml is the gold standard for fast XML DOM parsers. In my uses
it has turned XML parsing from a bottleneck to an irrelevance, so it
works for me.</p>
</blockquote>
<p>In order to achieve that speed, he cheats by not performing
operations he doesn’t care about:</p>
<blockquote>
<p>To gain that speed, Hexml cheats. Primarily it doesn’t do entity
expansion, so <code>&amp;amp;</code> remains as <code>&amp;amp;</code>
in the output. It also doesn’t handle <code>CData</code> sections (but
that’s because I’m lazy) and comment locations are not remembered. It
also doesn’t deal with most of the XML standard, ignoring the
<code>DOCTYPE</code> stuff. [..] I only work on UTF8, which for the bits
of UTF8 I care about, is the same as ASCII - I don’t need to do any
character decoding.</p>
</blockquote>
<p>Cheating is fine when you describe in detail how you cheat. That’s
just changing the rules of the game!</p>
<!-- why this is of interest to me -->
<h2 id="but-c-has-problems">But C has problems</h2>
<p>This post caught my attention because it seemed to me a pity to use
C. Whether you use Haskell, Python, or whatever, there are a few
problems with dropping down to C from your high-level language:</p>
<ul>
<li>The program is more likely to segfault. I’ll take an exception over
a segfault any day!</li>
<li>The program opens itself up to possible exploitation due to lack of
memory safety.</li>
<li>If people want to extend your software, they have to use C, and not
your high-level language.</li>
<li>Portability (i.e. Windows) is a pain in the arse with C.</li>
</ul>
<p>Sure enough, it wasn’t long before <a
href="https://www.reddit.com/r/haskell/comments/5i2mg1/new_xml_parser_hexml/db5os2h/">Austin
Seipp posted a rundown of bugs in the C code</a>:</p>
<blockquote>
<p>At the moment, sorry to say – I wouldn’t use this library to parse
any arbitrary XML, since it could be considered hostile, and get me
owned. Using American Fuzzy Lop, just after a few minutes, I’ve already
found around ~30 unique crashes.</p>
</blockquote>
<p>But C is really fast right? Like 100s of times faster than Haskell!
It’s worth the risk.</p>
<h2 id="but-but-c-is-fast">But-but C is fast!</h2>
<p>Let’s benchmark it. We’re going to parse a 4KB, a 31KB and a 211KB
XML file.</p>
<p>Using the <a href="http://www.serpentine.com/criterion/">Criterion
benchmarking package</a>, we can compare Hexml against the pretty old
Haskell <code>xml</code> package…</p>
<p>[image deleted due to region politics]</p>
<pre><code>File   hexml    xml
4KB    6.26 μs  1.94 ms (1940 μs)
31KB   9.41 μs  13.6 ms (13600 μs)
211KB  260  μs  25.9 ms (25900 μs)</code></pre>
<p>Ouch! Those numbers don’t look good. The xml package is 100-300x
times slower.</p>
<p>Okay, I’m being unfair. The xml package isn’t known for speed. Its
package description is simply <code>A simple XML library.</code> Let’s
compare with the hexpat package. That one has this in its
description:</p>
<blockquote>
<p>The design goals are speed, speed, speed, interface simplicity and
modularity.</p>
</blockquote>
<p>So that’s probably more representing the best in Haskell XML parsers.
It’s also based on the C expat library, which is supposed to be
fast.</p>
<p>[image deleted due to region politics]</p>
<pre><code>File   hexml     hexpat
4KB    6.395 μs  320.3 μs
31KB   9.474 μs  378.3 μs
211KB  256.2 μs  25.68 ms</code></pre>
<p>That’s a bit better. We’re now between 40-100x slower than Hexml. I’d
prefer 10x slower, but it’s a more reasonable outcome. The hexpat
package handles: keeping location information, reasonable parse errors,
the complete XML standard. Hexml doesn’t do any of that.</p>
<p>Let’s set us a challenge. Can we match or beat the Hexml package in
plain old Haskell? This is an itch that got under my skin. I emailed
Neil and he was fine with it:</p>
<blockquote>
<p>I don’t think it’s unfair or attacky to use Hexml as the baseline -
I’d welcome it!</p>
</blockquote>
<p>I’ll walk you through my approach. I called my library <a
href="https://github.com/chrisdone/xeno">Xeno</a> (for obvious
reasons).</p>
<h2 id="start-with-the-simplest-thing-possible">Start with the simplest
thing possible</h2>
<p>…and make sure it’s fast. Here’s the first thing I wrote, to see how
fast it was to walk across a file compared with Hexml.</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">module</span> <span class="dt">Xeno</span> (parse) <span class="kw">where</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span>           <span class="dt">Data.ByteString</span> (<span class="dt">ByteString</span>)</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.ByteString</span> <span class="kw">as</span> <span class="dt">S</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span>           <span class="dt">Data.Word</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="co">-- | Parse an XML document.</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="ot">parse ::</span> <span class="dt">ByteString</span> <span class="ot">-&gt;</span> ()</span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>parse str <span class="ot">=</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>  parseTags <span class="dv">0</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">where</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>    parseTags <span class="fu">index</span> <span class="ot">=</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>      <span class="kw">case</span> elemIndexFrom <span class="dv">60</span> str <span class="fu">index</span> <span class="kw">of</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Nothing</span> <span class="ot">-&gt;</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>          ()</span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Just</span> fromLt <span class="ot">-&gt;</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>          <span class="kw">case</span> elemIndexFrom <span class="dv">62</span> str fromLt <span class="kw">of</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a>            <span class="dt">Nothing</span> <span class="ot">-&gt;</span> ()</span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a>            <span class="dt">Just</span> fromGt <span class="ot">-&gt;</span> <span class="kw">do</span></span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true" tabindex="-1"></a>              parseTags (fromGt <span class="op">+</span> <span class="dv">1</span>)</span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true" tabindex="-1"></a><span class="co">-- | Get index of an element starting from offset.</span></span>
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true" tabindex="-1"></a><span class="ot">elemIndexFrom ::</span> <span class="dt">Word8</span> <span class="ot">-&gt;</span> <span class="dt">ByteString</span> <span class="ot">-&gt;</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Maybe</span> <span class="dt">Int</span></span>
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true" tabindex="-1"></a>elemIndexFrom c str offset <span class="ot">=</span> <span class="fu">fmap</span> (<span class="op">+</span> offset) (S.elemIndex c (S.drop offset str))</span>
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# INLINE elemIndexFrom #-}</span></span></code></pre></div>
<p>The numbers 60 and 62 are <code>&lt;</code> and <code>&gt;</code>. In
XML the only characters that matter are <code>&lt;</code> and
<code>&gt;</code> (if you don’t care about entities). <code>&lt;</code>
and <code>&gt;</code> can’t appear inside speech marks (attributes).
They are the only important things to search for. Results:</p>
<pre><code>File   hexml     xeno
4KB    6.395 μs  2.630 μs
42KB   37.55 μs  7.814 μs</code></pre>
<p>So the baseline performance of walking across the file in jumps is
quite fast! Why is it fast? Let’s look at that for a minute:</p>
<ul>
<li>The <code>ByteString</code> data type is a safe wrapper around a
vector of bytes. It’s underneath equivalent to <code>char*</code> in
C.</li>
<li>With that in mind, <a
href="http://hackage.haskell.org/package/bytestring-0.10.8.1/docs/Data-ByteString.html#v:elemIndex">the
<code>S.elemIndex</code> function</a> is implemented using the standard
C function <code>memchr(3)</code>. As we all know, <code>memchr</code>
jumps across your file in large word boundaries or even using SIMD
operations, meaning it’s bloody fast. But the <code>elemIndex</code>
function itself is safe.</li>
</ul>
<p>So we’re effectively doing a <code>for(..) { s=memchr(s,..) }</code>
loop over the file.</p>
<h2 id="keep-an-eye-on-the-allocations">Keep an eye on the
allocations</h2>
<p>Using the <a href="https://github.com/fpco/weigh#readme">weigh
package</a> for memory allocation tracking, we can also look at
allocations of our code right now:</p>
<pre><code>Case         Bytes  GCs  Check
4kb parse    1,168    0  OK
42kb parse   1,560    0  OK
52kb parse   1,168    0  OK
182kb parse  1,168    0  OK</code></pre>
<p>We see that it’s constant. Okay, it varies by a few bytes, but it
doesn’t increase linearly or anything. That’s good! One thing that stood
out to me, is that didn’t we pay for allocation of the
<code>Maybe</code> values. For a 1000x <code>&lt;</code> and
<code>&gt;</code> characters, we should have 1000 allocations of
<code>Just</code>/<code>Nothing</code>. Let’s go down that rabbit hole
for a second.</p>
<h2 id="looking-at-the-core">Looking at the Core</h2>
<p>Well, if you compile the source like this</p>
<pre><code>stack ghc -- -O2 -ddump-simpl Xeno.hs</code></pre>
<p>You’ll see a dump of the real <a
href="http://stackoverflow.com/questions/6121146/reading-ghc-core">Core</a>
code that is generated after the Haskell code is desugared, and before
it’s compiled to machine code. At this stage you can already see
optimizations based on inlining, common-sub-expression elimination,
deforestation, and other things.</p>
<p>The output is rather large. Core is verbose, and fast code tends to
be longer. <a
href="https://gist.github.com/chrisdone/7aea4748c6fd0f1854d341b5676a4a97">Here
is the output</a>, but you don’t have to understand it. Just note that
there’s no mention of Maybe, Just or Nothing in there. It skips that
altogether. See <a
href="https://gist.github.com/chrisdone/7aea4748c6fd0f1854d341b5676a4a97#file-1core-hs-L38-L48">here
specifically</a>. There is a call to <code>memchr</code>, then there is
an <code>eqAddr</code> comparison with <code>NULL</code>, to see whether
the <code>memchr</code> is done or not. But we’re <a
href="https://gist.github.com/chrisdone/7aea4748c6fd0f1854d341b5676a4a97#file-1core-hs-L146">still
doing safety checks</a> so that the resulting code is safe.</p>
<h2 id="inlining-counts">Inlining counts</h2>
<p>The curious reader might have noticed that <code>INLINE</code> line
in my first code sample.</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# INLINE elemIndexFrom #-}</span></span></code></pre></div>
<p>Without the INLINE, the whole function is twice as slow and has
linear allocation.</p>
<pre><code>Case        Bytes  GCs  Check
4kb parse   1,472    0  OK
42kb parse  1,160    0  OK
52kb parse  1,160    0  OK

benchmarking 4KB/xeno
time                 2.512 μs   (2.477 μs .. 2.545 μs)
benchmarking 211KB/xeno
time                 129.9 μs   (128.7 μs .. 131.2 μs)
benchmarking 31KB/xeno
time                 1.930 μs   (1.909 μs .. 1.958 μs)</code></pre>
<p>versus:</p>
<pre><code>Case         Bytes  GCs  Check
4kb parse   12,416    0  OK
42kb parse  30,080    0  OK
52kb parse  46,208    0  OK

benchmarking 4KB/xeno
time                 5.258 μs   (5.249 μs .. 5.266 μs)
benchmarking 211KB/xeno
time                 265.9 μs   (262.4 μs .. 271.4 μs)
benchmarking 31KB/xeno
time                 3.212 μs   (3.209 μs .. 3.218 μs)</code></pre>
<p>Always pay attention to things like this. You don’t want to put
INLINE on everything. Sometimes it adds slowdown, most times it makes no
difference. So check with your benchmark suite.</p>
<h2 id="loop-unrolling-manually">Loop unrolling manually</h2>
<p>Some things need to be done manually. I added comment parsing to our
little function:</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>        <span class="dt">Just</span> fromLt <span class="ot">-&gt;</span> checkOpenComment (fromLt <span class="op">+</span> <span class="dv">1</span>)</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>    checkOpenComment <span class="fu">index</span> <span class="ot">=</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>      <span class="kw">if</span> S.isPrefixOf <span class="st">&quot;!--&quot;</span> (S.drop <span class="fu">index</span> str)</span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>         <span class="kw">then</span> findCommentEnd (<span class="fu">index</span> <span class="op">+</span> <span class="dv">3</span>)</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>         <span class="kw">else</span> findLt <span class="fu">index</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>    findCommentEnd <span class="fu">index</span> <span class="ot">=</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>      <span class="kw">case</span> elemIndexFrom commentChar str <span class="fu">index</span> <span class="kw">of</span></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>        <span class="dt">Nothing</span> <span class="ot">-&gt;</span> () <span class="co">-- error!</span></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>        <span class="dt">Just</span> fromDash <span class="ot">-&gt;</span></span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>          <span class="kw">if</span> S.isPrefixOf <span class="st">&quot;-&gt;&quot;</span> (S.drop (fromDash <span class="op">+</span> <span class="dv">1</span>) str)</span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>             <span class="kw">then</span> findGt (fromDash <span class="op">+</span> <span class="dv">2</span>)</span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>             <span class="kw">else</span> findCommentEnd (fromDash <span class="op">+</span> <span class="dv">1</span>)</span></code></pre></div>
<p>And it became 2x slower:</p>
<pre><code>benchmarking 4KB/xeno
time                 2.512 μs   (2.477 μs .. 2.545 μs)</code></pre>
<p>to</p>
<pre><code>benchmarking 4KB/xeno
time                 4.296 μs   (4.240 μs .. 4.348 μs)</code></pre>
<p>So I changed the <code>S.isPrefixOf</code> to be unrolled to
<code>S.index</code> calls, like this:</p>
<div class="sourceCode" id="cb13"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="op">-</span>      <span class="kw">if</span> S.isPrefixOf <span class="st">&quot;!--&quot;</span> (S.drop <span class="fu">index</span> str)</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="op">-</span>         <span class="kw">then</span> findCommentEnd (<span class="fu">index</span> <span class="op">+</span> <span class="dv">3</span>)</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a><span class="op">-</span>         <span class="kw">else</span> findLt <span class="fu">index</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>      <span class="kw">if</span> S.index this <span class="dv">0</span> <span class="op">==</span> bangChar <span class="op">&amp;&amp;</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>         S.index this <span class="dv">1</span> <span class="op">==</span> commentChar <span class="op">&amp;&amp;</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>         S.index this <span class="dv">2</span> <span class="op">==</span> commentChar</span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>        <span class="kw">then</span> findCommentEnd (<span class="fu">index</span> <span class="op">+</span> <span class="dv">3</span>)</span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>        <span class="kw">else</span> findLt <span class="fu">index</span></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>      <span class="kw">where</span></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>        this <span class="ot">=</span> S.drop <span class="fu">index</span> str</span></code></pre></div>
<p>And it dropped back down to our base speed again.</p>
<h2 id="finding-tag-names">Finding tag names</h2>
<p>I implemented finding tag names like this:</p>
<div class="sourceCode" id="cb14"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>    findTagName index0 <span class="ot">=</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>      <span class="kw">case</span> S.findIndex (<span class="fu">not</span> <span class="op">.</span> isTagName) (S.drop <span class="fu">index</span> str) <span class="kw">of</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>        <span class="dt">Nothing</span> <span class="ot">-&gt;</span> <span class="fu">error</span> <span class="st">&quot;Couldn&#39;t find end of tag name.&quot;</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>        <span class="dt">Just</span> ((<span class="op">+</span> <span class="fu">index</span>) <span class="ot">-&gt;</span> spaceOrCloseTag) <span class="ot">-&gt;</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>          <span class="kw">if</span> S.head this <span class="op">==</span> closeTagChar</span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>            <span class="kw">then</span> findGt spaceOrCloseTag</span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>            <span class="kw">else</span> <span class="kw">if</span> S.head this <span class="op">==</span> spaceChar</span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>                   <span class="kw">then</span> findLt spaceOrCloseTag</span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>                   <span class="kw">else</span> <span class="fu">error</span></span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>                          (<span class="st">&quot;Expecting space or closing &#39;&gt;&#39; after tag name, but got: &quot;</span> <span class="op">++</span></span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>                           <span class="fu">show</span> this)</span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>          <span class="kw">where</span> this <span class="ot">=</span> S.drop spaceOrCloseTag str</span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>      <span class="kw">where</span></span>
<span id="cb14-14"><a href="#cb14-14" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>        <span class="fu">index</span> <span class="ot">=</span></span>
<span id="cb14-15"><a href="#cb14-15" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>          <span class="kw">if</span> S.head (S.drop index0 str) <span class="op">==</span> questionChar <span class="op">||</span></span>
<span id="cb14-16"><a href="#cb14-16" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>             S.head (S.drop index0 str) <span class="op">==</span> slashChar</span>
<span id="cb14-17"><a href="#cb14-17" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>            <span class="kw">then</span> index0 <span class="op">+</span> <span class="dv">1</span></span>
<span id="cb14-18"><a href="#cb14-18" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>            <span class="kw">else</span> index0</span></code></pre></div>
<p>And immediately noticed a big slow down. From</p>
<pre><code>Case        Bytes  GCs  Check
4kb parse   1,160    0  OK
42kb parse  1,472    0  OK
52kb parse  1,160    0  OK
Benchmark xeno-memory-bench: FINISH
Benchmark xeno-speed-bench: RUNNING...
benchmarking 4KB/hexml
time                 6.149 μs   (6.125 μs .. 6.183 μs)
benchmarking 4KB/xeno
time                 2.691 μs   (2.665 μs .. 2.712 μs)</code></pre>
<p>to</p>
<pre><code>Case          Bytes  GCs  Check
4kb parse    26,096    0  OK
42kb parse   65,696    0  OK
52kb parse  102,128    0  OK
Benchmark xeno-memory-bench: FINISH
Benchmark xeno-speed-bench: RUNNING...
benchmarking 4KB/hexml
time                 6.225 μs   (6.178 μs .. 6.269 μs)
benchmarking 4KB/xeno
time                 10.34 μs   (10.06 μs .. 10.59 μs)</code></pre>
<p>The first thing that should jump out at you is the allocations.
What’s going on there? I looked in the profiler output, by running
<code>stack bench --profile</code> to see a profile output.</p>
<pre><code>    Wed Jan 11 17:41 2017 Time and Allocation Profiling Report  (Final)

       xeno-speed-bench +RTS -N -p -RTS 4KB/xeno

    total time  =        8.09 secs   (8085 ticks @ 1000 us, 1 processor)
    total alloc = 6,075,628,752 bytes  (excludes profiling overheads)

COST CENTRE            MODULE                             %time %alloc

parse.findTagName      Xeno                                35.8   72.7
getOverhead            Criterion.Monad                     13.6    0.0
parse.checkOpenComment Xeno                                 9.9    0.0
parse.findLT           Xeno                                 8.9    0.0
parse                  Xeno                                 8.4    0.0
&gt;&gt;=                    Data.Vector.Fusion.Util              4.6    7.7
getGCStats             Criterion.Measurement                2.8    0.0
basicUnsafeIndexM      Data.Vector.Primitive                1.6    2.0
fmap                   Data.Vector.Fusion.Stream.Monadic    1.3    2.2
rSquare.p              Statistics.Regression                1.3    1.5
basicUnsafeWrite       Data.Vector.Primitive.Mutable        1.2    1.4
innerProduct.\         Statistics.Matrix.Algorithms         1.0    1.6
qr.\.\                 Statistics.Matrix.Algorithms         0.8    1.2
basicUnsafeSlice       Data.Vector.Primitive.Mutable        0.5    1.1
transpose              Statistics.Matrix                    0.5    1.3</code></pre>
<p>Right at the top, we have <code>findTagName</code>, doing all the
allocations. So I looked at the code, and found that the only possible
thing that could be allocating, is <code>S.drop</code>. This function
skips n elements at the start of a <code>ByteString</code>. It turns out
that <code>S.head (S.drop index0 str)</code> was allocating an
intermediate string, just to get the first character of that string. It
wasn’t <em>copying</em> the whole string, but it was making a new
pointer to it.</p>
<p>So I realised that I could just replace
<code>S.head (S.drop n s)</code> with <code>S.index s n</code>:</p>
<div class="sourceCode" id="cb18"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="op">-</span>          <span class="kw">if</span> S.head this <span class="op">==</span> closeTagChar</span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>          <span class="kw">if</span> S.index str spaceOrCloseTag <span class="op">==</span> closeTagChar</span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>             <span class="kw">then</span> findLT spaceOrCloseTag</span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a><span class="op">-</span>            <span class="kw">else</span> <span class="kw">if</span> S.head this <span class="op">==</span> spaceChar</span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>            <span class="kw">else</span> <span class="kw">if</span> S.index str spaceOrCloseTag <span class="op">==</span> spaceChar</span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">then</span> findGT spaceOrCloseTag</span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">else</span> <span class="fu">error</span> <span class="st">&quot;Expecting space or closing &#39;&gt;&#39; after tag name.&quot;</span></span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a><span class="op">-</span>          <span class="kw">where</span> this <span class="ot">=</span> S.drop spaceOrCloseTag str</span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a>       <span class="kw">where</span></span>
<span id="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a>         <span class="fu">index</span> <span class="ot">=</span></span>
<span id="cb18-11"><a href="#cb18-11" aria-hidden="true" tabindex="-1"></a><span class="op">-</span>          <span class="kw">if</span> S.head (S.drop index0 str) <span class="op">==</span> questionChar <span class="op">||</span></span>
<span id="cb18-12"><a href="#cb18-12" aria-hidden="true" tabindex="-1"></a><span class="op">-</span>             S.head (S.drop index0 str) <span class="op">==</span> slashChar</span>
<span id="cb18-13"><a href="#cb18-13" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>          <span class="kw">if</span> S.index str index0 <span class="op">==</span> questionChar <span class="op">||</span></span>
<span id="cb18-14"><a href="#cb18-14" aria-hidden="true" tabindex="-1"></a><span class="op">+</span>             S.index str index0 <span class="op">==</span> slashChar</span></code></pre></div>
<p>And sure enough, the allocations disappeared:</p>
<pre><code>Case        Bytes  GCs  Check
4kb parse   1,160    0  OK
42kb parse  1,160    0  OK
52kb parse  1,472    0  OK
Benchmark xeno-memory-bench: FINISH
Benchmark xeno-speed-bench: RUNNING...
benchmarking 4KB/hexml
time                 6.190 μs   (6.159 μs .. 6.230 μs)
benchmarking 4KB/xeno
time                 4.215 μs   (4.175 μs .. 4.247 μs)</code></pre>
<p>Down to 4.215 μs. That’s not as fast as our pre-name-parsing 2.691
μs. But we had to pay <em>something</em> for the extra operations per
tag. We’re just not allocating anymore, which is great.</p>
<h2 id="sax-for-free">SAX for free</h2>
<p>Eventually I ended up with a function called <code>process</code>
that parses XML and triggers events in a SAX style:</p>
<div class="sourceCode" id="cb20"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a>process</span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a><span class="ot">  ::</span> <span class="dt">Monad</span> m</span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>  <span class="ot">=&gt;</span> (<span class="dt">ByteString</span> <span class="ot">-&gt;</span> m ())               <span class="co">-- ^ Open tag.</span></span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> (<span class="dt">ByteString</span> <span class="ot">-&gt;</span> <span class="dt">ByteString</span> <span class="ot">-&gt;</span> m ()) <span class="co">-- ^ Tag attribute.</span></span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> (<span class="dt">ByteString</span> <span class="ot">-&gt;</span> m ())               <span class="co">-- ^ End open tag.</span></span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> (<span class="dt">ByteString</span> <span class="ot">-&gt;</span> m ())               <span class="co">-- ^ Text.</span></span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> (<span class="dt">ByteString</span> <span class="ot">-&gt;</span> m ())               <span class="co">-- ^ Close tag.</span></span>
<span id="cb20-8"><a href="#cb20-8" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> <span class="dt">ByteString</span> <span class="ot">-&gt;</span> m ()</span></code></pre></div>
<p>Thanks again to GHC’s optimizations, calling this function purely and
doing nothing is exactly equal to the function before SAX-ization:</p>
<div class="sourceCode" id="cb21"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- | Parse the XML but return no result, process no events.</span></span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a><span class="ot">validate ::</span> <span class="dt">ByteString</span> <span class="ot">-&gt;</span> <span class="dt">Bool</span></span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>validate s <span class="ot">=</span></span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">case</span> spork</span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a>         (runIdentity</span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a>            (process</span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a>               (\_ <span class="ot">-&gt;</span> <span class="fu">pure</span> ())</span>
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a>               (\_ _ <span class="ot">-&gt;</span> <span class="fu">pure</span> ())</span>
<span id="cb21-9"><a href="#cb21-9" aria-hidden="true" tabindex="-1"></a>               (\_ <span class="ot">-&gt;</span> <span class="fu">pure</span> ())</span>
<span id="cb21-10"><a href="#cb21-10" aria-hidden="true" tabindex="-1"></a>               (\_ <span class="ot">-&gt;</span> <span class="fu">pure</span> ())</span>
<span id="cb21-11"><a href="#cb21-11" aria-hidden="true" tabindex="-1"></a>               (\_ <span class="ot">-&gt;</span> <span class="fu">pure</span> ())</span>
<span id="cb21-12"><a href="#cb21-12" aria-hidden="true" tabindex="-1"></a>               s)) <span class="kw">of</span></span>
<span id="cb21-13"><a href="#cb21-13" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Left</span> (<span class="ot">_ ::</span> <span class="dt">XenoException</span>) <span class="ot">-&gt;</span> <span class="dt">False</span></span>
<span id="cb21-14"><a href="#cb21-14" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Right</span> _ <span class="ot">-&gt;</span> <span class="dt">True</span></span></code></pre></div>
<pre><code>Case        Bytes  GCs  Check
4kb parse   1,472    0  OK
42kb parse  1,160    0  OK
52kb parse  1,472    0  OK

benchmarking 4KB/xeno
time                 4.320 μs   (4.282 μs .. 4.361 μs)</code></pre>
<p>This function performs at the same speed as <code>process</code>
before it accepted any callback arguments. This means that the only
overhead to SAX’ing will be the activities that the callback functions
themselves do.</p>
<h2
id="specialization-is-for-insects-and-as-it-happens-optimized-programs">Specialization
is for insects (and, as it happens, optimized programs)</h2>
<p>One point of interest is that adding a <code>SPECIALIZE</code> pragma
for the <code>process</code> function increases speed by roughly 1 μs.
Specialization means that for a given function which is generic
(type-class polymorphic), which means it will accept a dictionary
argument at runtime for the particular instance, instead we will
generate a separate piece of code that is specialized on that exact
instance. Below is the <code>Identity</code> monad’s (i.e. just pure,
does nothing) specialized type for <code>process</code>.</p>
<div class="sourceCode" id="cb23"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# SPECIALISE</span></span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a><span class="ot">    process</span></span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a><span class="ot">      :: (ByteString -&gt; Identity ())</span></span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a><span class="ot">      -&gt; (ByteString -&gt; ByteString -&gt; Identity ())</span></span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a><span class="ot">      -&gt; (ByteString -&gt; Identity ())</span></span>
<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a><span class="ot">      -&gt; (ByteString -&gt; Identity ())</span></span>
<span id="cb23-7"><a href="#cb23-7" aria-hidden="true" tabindex="-1"></a><span class="ot">      -&gt; (ByteString -&gt; Identity ())</span></span>
<span id="cb23-8"><a href="#cb23-8" aria-hidden="true" tabindex="-1"></a><span class="ot">      -&gt; ByteString</span></span>
<span id="cb23-9"><a href="#cb23-9" aria-hidden="true" tabindex="-1"></a><span class="ot">      -&gt; Identity ()</span></span>
<span id="cb23-10"><a href="#cb23-10" aria-hidden="true" tabindex="-1"></a><span class="ot"> #-}</span></span></code></pre></div>
<p>Before</p>
<pre><code>benchmarking 4KB/xeno-sax
time                 5.877 μs   (5.837 μs .. 5.926 μs)
benchmarking 211KB/xeno-sax
time                 285.8 μs   (284.7 μs .. 287.4 μs)</code></pre>
<p>after</p>
<pre><code>benchmarking 4KB/xeno-sax
time                 5.046 μs   (5.036 μs .. 5.056 μs)
benchmarking 211KB/xeno-sax
time                 240.6 μs   (240.0 μs .. 241.5 μs)</code></pre>
<p>In the 4KB case it’s only 800 ns, but as we say in Britain, take care
of the pennies and the pounds will look after themselves. The
240-&gt;285 difference isn’t big in practical terms, but when we’re
playing the speed game, we pay attention to things like that.</p>
<h2 id="where-we-stand-xeno-vs-hexml">Where we stand: Xeno vs Hexml</h2>
<p>Currently the SAX interface in Zeno outperforms Hexml in space and
time. Hurrah! We’re as fast as C!</p>
<pre><code>File   hexml-dom  xeno-sax
4KB    6.134 μs   5.147 μs
31KB   9.299 μs   2.879 μs
211KB  257.3 μs   241.0 μs</code></pre>
<p>It’s also worth noting that Haskell does this all safely. All the
functions I’m using are standard ByteString functions which do bounds
checking and throw an exception if so. We don’t accidentally access
memory that we shouldn’t, and we don’t segfault. The server keeps
running.</p>
<p>If you’re interested, if we switch to unsafe functions
(<code>unsafeTake</code>, <code>unsafeIndex</code> from the
<code>Data.ByteString.Unsafe</code> module), we get a notable speed
increase:</p>
<pre><code>File   hexml-dom  xeno-sax
4KB    6.134 μs   4.344 μs
31KB   9.299 μs   2.570 μs
211KB  257.3 μs   206.9 μs</code></pre>
<p>We don’t need to show off, though. We’ve already made our point.
We’re Haskellers, we like safety. I’ll keep my safe functions.</p>
<h2 id="but-hexml-does-more">But Hexml does more!</h2>
<p>I’d be remiss if I didn’t address the fact that Hexml does more
useful things than we’ve done here. Hexml allocates a DOM for random
access. Oh no! Allocation: Haskell’s worse enemy!</p>
<p>[image deleted due to region politics]</p>
<p>We’ve seen that Haskell allocates a lot normally. Actually, have we
looked at that properly?</p>
<pre><code>Case                   Bytes  GCs  Check
4kb/hexpat-sax       444,176    0  OK
31kb/hexpat-sax      492,576    0  OK
211kb/hexpat-sax  21,112,392   40  OK
4kb/hexpat-dom       519,128    0  OK
31kb/hexpat-dom      575,232    0  OK
211kb/hexpat-dom  23,182,560   44  OK</code></pre>
<p>Alright.</p>
<h2 id="implementing-a-dom-parser-for-xeno">Implementing a DOM parser
for Xeno</h2>
<p>All isn’t lost. Hexml isn’t a dumb parser that’s fast because it’s in
C, it’s also a decent algorithm. Rather than allocating a tree, it
allocates a big flat vector of nodes and attributes, which contain
offsets into the original string. We can do that in Haskell too!</p>
<p>Here’s my design of a data structure contained in a vector. We want
to store just integers in the vector. Integers that point to offsets in
the original string. Here’s what I came up with.</p>
<p>We have three kinds of payloads. Elements, text and attributes:</p>
<div class="sourceCode" id="cb29"><pre
class="sourceCode ruby"><code class="sourceCode ruby"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="dv">1</span><span class="kw">.</span>  <span class="dv">00</span> <span class="co"># Type tag: element</span></span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a><span class="dv">2</span><span class="kw">.</span>  <span class="dv">00</span> <span class="co"># Parent index (within this array)</span></span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a><span class="dv">3</span><span class="kw">.</span>  <span class="bn">01</span> <span class="co"># Start of the tag name in the original string</span></span>
<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a><span class="dv">4</span><span class="kw">.</span>  <span class="bn">01</span> <span class="co"># Length of the tag name</span></span>
<span id="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a><span class="dv">5</span><span class="kw">.</span>  <span class="bn">05</span> <span class="co"># End index of the tag (within this array)</span></span></code></pre></div>
<div class="sourceCode" id="cb30"><pre
class="sourceCode ruby"><code class="sourceCode ruby"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="dv">1</span><span class="kw">.</span>  <span class="bn">02</span> <span class="co"># Type tag: attribute</span></span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a><span class="dv">2</span><span class="kw">.</span>  <span class="bn">01</span> <span class="co"># Start of the key</span></span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a><span class="dv">3</span><span class="kw">.</span>  <span class="bn">05</span> <span class="co"># Length of the key</span></span>
<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a><span class="dv">4</span><span class="kw">.</span>  <span class="bn">06</span> <span class="co"># Start of the value</span></span>
<span id="cb30-5"><a href="#cb30-5" aria-hidden="true" tabindex="-1"></a><span class="dv">5</span><span class="kw">.</span>  <span class="bn">03</span> <span class="co"># Length of the value</span></span></code></pre></div>
<div class="sourceCode" id="cb31"><pre
class="sourceCode ruby"><code class="sourceCode ruby"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a><span class="dv">1</span><span class="kw">.</span>  <span class="bn">01</span> <span class="co"># Type tag: text</span></span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a><span class="dv">2</span><span class="kw">.</span>  <span class="bn">01</span> <span class="co"># Start of the text</span></span>
<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a><span class="dv">3</span><span class="kw">.</span>  <span class="dv">10</span> <span class="co"># Length of the text</span></span></code></pre></div>
<p>That’s all the detail I’m going to go into. You can read <a
href="https://github.com/chrisdone/xeno">the code</a> if you want to
know more. It’s not a highly optimized format. Once we have such a
vector, it’s possible to define a DOM API on top of it which can let you
navigate the tree as usual, which we’ll see later.</p>
<p>We’re going to use our SAX parser–the <code>process</code> function,
and we’re going to implement a function that writes to a big array. This
is a very imperative algorithm. Haskellers don’t like imperative
algorithms much, but Haskell’s fine with them.</p>
<p>The function ends up looking something like this:</p>
<div class="sourceCode" id="cb32"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a>runST</span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a>  (<span class="kw">do</span> nil <span class="ot">&lt;-</span> UMV.new <span class="dv">1000</span></span>
<span id="cb32-3"><a href="#cb32-3" aria-hidden="true" tabindex="-1"></a>      vecRef <span class="ot">&lt;-</span> newSTRef nil</span>
<span id="cb32-4"><a href="#cb32-4" aria-hidden="true" tabindex="-1"></a>      sizeRef <span class="ot">&lt;-</span> <span class="fu">fmap</span> asURef (newRef <span class="dv">0</span>)</span>
<span id="cb32-5"><a href="#cb32-5" aria-hidden="true" tabindex="-1"></a>      parentRef <span class="ot">&lt;-</span> <span class="fu">fmap</span> asURef (newRef <span class="dv">0</span>)</span>
<span id="cb32-6"><a href="#cb32-6" aria-hidden="true" tabindex="-1"></a>      process</span>
<span id="cb32-7"><a href="#cb32-7" aria-hidden="true" tabindex="-1"></a>        (\(<span class="dt">PS</span> _ name_start name_len) <span class="ot">-&gt;</span></span>
<span id="cb32-8"><a href="#cb32-8" aria-hidden="true" tabindex="-1"></a>            <span class="op">&lt;</span>write the open tag elements<span class="op">&gt;</span>)</span>
<span id="cb32-9"><a href="#cb32-9" aria-hidden="true" tabindex="-1"></a>        (\(<span class="dt">PS</span> _ key_start key_len) (<span class="dt">PS</span> _ value_start value_len) <span class="ot">-&gt;</span></span>
<span id="cb32-10"><a href="#cb32-10" aria-hidden="true" tabindex="-1"></a>            <span class="op">&lt;</span>write an attribute into the vector<span class="op">&gt;</span>)</span>
<span id="cb32-11"><a href="#cb32-11" aria-hidden="true" tabindex="-1"></a>        (\_ <span class="ot">-&gt;</span> <span class="op">&lt;</span>ignore<span class="op">&gt;</span>)</span>
<span id="cb32-12"><a href="#cb32-12" aria-hidden="true" tabindex="-1"></a>        (\(<span class="dt">PS</span> _ text_start text_len) <span class="ot">-&gt;</span></span>
<span id="cb32-13"><a href="#cb32-13" aria-hidden="true" tabindex="-1"></a>            <span class="op">&lt;</span>write a text entry into the vector<span class="op">&gt;</span>)</span>
<span id="cb32-14"><a href="#cb32-14" aria-hidden="true" tabindex="-1"></a>        (\_ <span class="ot">-&gt;</span></span>
<span id="cb32-15"><a href="#cb32-15" aria-hidden="true" tabindex="-1"></a>            <span class="op">&lt;</span>set the end position <span class="kw">of</span> the parent<span class="op">&gt;</span></span>
<span id="cb32-16"><a href="#cb32-16" aria-hidden="true" tabindex="-1"></a>            <span class="op">&lt;</span>set the current element to the parent<span class="op">&gt;</span>)</span>
<span id="cb32-17"><a href="#cb32-17" aria-hidden="true" tabindex="-1"></a>        str</span>
<span id="cb32-18"><a href="#cb32-18" aria-hidden="true" tabindex="-1"></a>      wet <span class="ot">&lt;-</span> readSTRef vecRef</span>
<span id="cb32-19"><a href="#cb32-19" aria-hidden="true" tabindex="-1"></a>      arr <span class="ot">&lt;-</span> UV.unsafeFreeze wet</span>
<span id="cb32-20"><a href="#cb32-20" aria-hidden="true" tabindex="-1"></a>      size <span class="ot">&lt;-</span> readRef sizeRef</span>
<span id="cb32-21"><a href="#cb32-21" aria-hidden="true" tabindex="-1"></a>      <span class="fu">return</span> (UV.unsafeSlice <span class="dv">0</span> size arr))</span></code></pre></div>
<p>The function runs in the <code>ST</code> monad which lets us locally
read and write to mutable variables and vectors, while staying pure on
the outside.</p>
<p>I allocate an array of 1000 64-bit Ints (on 64-bit arch), I keep a
variable of the current size, and the current parent (if any). The
current parent variable lets us, upon seeing a </close> tag, assign the
position in the vector of where the parent is closed.</p>
<p>Whenever we get an event and the array is too small, I grow the array
by doubling its size. This strategy is copied from the Hexml
package.</p>
<p>Finally, when we’re done, we get the mutable vector, “freeze” it
(this means making an immutable version of it), and then return that
copy. We use <code>unsafeFreeze</code> to re-use the array without
copying, which includes a promise that we don’t use the mutable vector
afterwards, which we don’t.</p>
<h2 id="the-dom-speed">The DOM speed</h2>
<p>Let’s take a look at the speeds:</p>
<pre><code>File   hexml-dom  xeno-sax  xeno-dom
4KB    6.123 μs   5.038 μs  10.35 μs
31KB   9.417 μs   2.875 μs  5.714 μs
211KB  256.3 μs   240.4 μs  514.2 μs</code></pre>
<p>Not bad! The DOM parser is only &lt;2x slower than Hexml (except in
the 31KB where it’s faster. <em>shrug</em>). Here is where I stopped
optimizing and decided it was good enough. But we can review some of the
decisions made along the way.</p>
<p>In the code we’re using unboxed mutable references for the current
size and parent, the mutable references are provided by the
mutable-containers package. See these two lines here:</p>
<div class="sourceCode" id="cb34"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a>      sizeRef <span class="ot">&lt;-</span> <span class="fu">fmap</span> asURef (newRef <span class="dv">0</span>)</span>
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a>      parentRef <span class="ot">&lt;-</span> <span class="fu">fmap</span> asURef (newRef <span class="dv">0</span>)</span></code></pre></div>
<p>Originally, I had tried <code>STRef</code>’s, which are boxed. Boxed
just means it’s a pointer to an integer instead of an actual integer. An
unboxed Int is a proper machine register. Using an <code>STRef</code>,
we get worse speeds:</p>
<pre><code>File   xeno-dom
4KB    12.18 μs
31KB   6.412 μs
211KB  631.1 μs</code></pre>
<p>Which is a noticeable speed loss.</p>
<p>Another thing to take into consideration is the array type. I’m using
the unboxed mutable vectors from the <code>vector</code> package. When
using atomic types like Int, it can be a leg-up to use unboxed vectors.
If I use the regular boxed vectors from <code>Data.Vector</code>, the
speed regresses to:</p>
<pre><code>File   xeno-dom
4KB    11.95 μs (from 10.35 μs)
31KB   6.430 μs (from 5.714 μs)
211KB  1.402 ms (from 514.2 μs)</code></pre>
<p>Aside from taking a bit more time to do writes, it also allocates
1.5x more stuff:</p>
<pre><code>Case                 Bytes  GCs  Check
4kb/xeno/dom        11,240    0  OK
31kb/xeno/dom       10,232    0  OK
211kb/xeno/dom   1,082,696    0  OK</code></pre>
<p>becomes</p>
<pre><code>Case                 Bytes  GCs  Check
4kb/xeno/dom        22,816    0  OK
31kb/xeno/dom       14,968    0  OK
211kb/xeno/dom   1,638,392    1  OK</code></pre>
<p>See that GC there? We shouldn’t need it.</p>
<p>Finally, one more remark for the DOM parser. If we forsake safety and
use the <code>unsafeWrite</code> and <code>unsafeRead</code> methods
from the vector package, we do see a small increase:</p>
<pre><code>File   xeno-dom
4KB    9.827 μs
31KB   5.545 μs
211KB  490.1 μs</code></pre>
<p>But it’s nothing to write home about. I’ll prefer memory safety over
a few microseconds this time.</p>
<h2 id="the-dom-api">The DOM API</h2>
<p>I wrote some functions to access our vector and provide a DOM-like
API:</p>
<div class="sourceCode" id="cb40"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb40-1"><a href="#cb40-1" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> <span class="kw">let</span> <span class="dt">Right</span> node <span class="ot">=</span> parse <span class="st">&quot;&lt;foo k=&#39;123&#39;&gt;&lt;p&gt;hi&lt;/p&gt;ok&lt;/foo&gt;&quot;</span></span>
<span id="cb40-2"><a href="#cb40-2" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> node</span>
<span id="cb40-3"><a href="#cb40-3" aria-hidden="true" tabindex="-1"></a>(<span class="dt">Node</span> <span class="st">&quot;foo&quot;</span> [(<span class="st">&quot;k&quot;</span>,<span class="st">&quot;123&quot;</span>)] [<span class="dt">Element</span> (<span class="dt">Node</span> <span class="st">&quot;p&quot;</span> [] [<span class="dt">Text</span> <span class="st">&quot;hi&quot;</span>]),<span class="dt">Text</span> <span class="st">&quot;ok&quot;</span>])</span>
<span id="cb40-4"><a href="#cb40-4" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> name node</span>
<span id="cb40-5"><a href="#cb40-5" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;foo&quot;</span></span>
<span id="cb40-6"><a href="#cb40-6" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> children node</span>
<span id="cb40-7"><a href="#cb40-7" aria-hidden="true" tabindex="-1"></a>[(<span class="dt">Node</span> <span class="st">&quot;p&quot;</span> [] [<span class="dt">Text</span> <span class="st">&quot;hi&quot;</span>])]</span>
<span id="cb40-8"><a href="#cb40-8" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> attributes node</span>
<span id="cb40-9"><a href="#cb40-9" aria-hidden="true" tabindex="-1"></a>[(<span class="st">&quot;k&quot;</span>,<span class="st">&quot;123&quot;</span>)]</span>
<span id="cb40-10"><a href="#cb40-10" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> contents node</span>
<span id="cb40-11"><a href="#cb40-11" aria-hidden="true" tabindex="-1"></a>[<span class="dt">Element</span> (<span class="dt">Node</span> <span class="st">&quot;p&quot;</span> [] [<span class="dt">Text</span> <span class="st">&quot;hi&quot;</span>]),<span class="dt">Text</span> <span class="st">&quot;ok&quot;</span>]</span></code></pre></div>
<p>So that works.</p>
<h2 id="wrapping-up">Wrapping-up</h2>
<p>The final results are in:</p>
<p>[image deleted due to region politics]</p>
<p>And just to check that a 1MB file doesn’t give wildly different
results:</p>
<pre><code>benchmarking 1MB/hexml-dom
time                 1.225 ms   (1.221 ms .. 1.229 ms)
                     1.000 R²   (1.000 R² .. 1.000 R²)
mean                 1.239 ms   (1.234 ms .. 1.249 ms)
std dev              25.23 μs   (12.28 μs .. 40.84 μs)

benchmarking 1MB/xeno-sax
time                 1.206 ms   (1.203 ms .. 1.211 ms)
                     1.000 R²   (1.000 R² .. 1.000 R²)
mean                 1.213 ms   (1.210 ms .. 1.218 ms)
std dev              14.58 μs   (10.18 μs .. 21.34 μs)

benchmarking 1MB/xeno-dom
time                 2.768 ms   (2.756 ms .. 2.779 ms)
                     1.000 R²   (1.000 R² .. 1.000 R²)
mean                 2.801 ms   (2.791 ms .. 2.816 ms)
std dev              41.10 μs   (30.14 μs .. 62.60 μs)</code></pre>
<p>Tada! We matched Hexml, in pure Haskell, using safe accessor
functions. We provided a SAX API which is very fast, and a simple
demonstration DOM parser with a familiar API which is also quite fast.
We use reasonably little memory in doing so.</p>
<p>This package is an experiment for educational purposes, to show what
Haskell can do and what it can’t, for a very specific domain problem. If
you would like to use this package, consider adopting it and giving it a
good home. I’m not looking for more packages to maintain.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2017-01-11 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Wed, 11 Jan 2017 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[hindent 5: One style to rule them all]]></title><link>https://chrisdone.com/posts/hindent-5</link><guid>https://chrisdone.com/posts/hindent-5</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>hindent 5: One style to rule them all</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>hindent 5: One style to rule them all</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<h2 id="reminder-of-the-past">Reminder of the past</h2>
<p>In 2014, in <a href="http://chrisdone.com/posts/hindent">my last
post</a> about <a
href="https://github.com/chrisdone/hindent">hindent</a>, I wrote these
points:</p>
<ol type="1">
<li><a
href="http://chrisdone.com/posts/hindent#whats-the-deal-with-code-style">Automatic
formatting is important</a>:
<ul>
<li><a
href="http://chrisdone.com/posts/hindent#okay-but-is-this-a-problem-tooling-even-needs-to-solve">External
tooling works better</a></li>
<li>Reading code is easier</li>
<li>Writing code is faster</li>
</ul></li>
<li><a
href="http://chrisdone.com/posts/hindent#is-this-really-an-issue-though">Other
people also care about this</a></li>
<li><a
href="http://www.reddit.com/r/haskell/comments/15gz8q/a_nondirty_shot_at_tabs_vs_spaces/">The
Haskell community is not immune to code formatting debates</a></li>
</ol>
<p>I <a
href="http://chrisdone.com/posts/hindent#a-practical-way-forward">proposed</a>
my hindent tool, which:</p>
<ol type="1">
<li>Would format your code.</li>
<li>Supported multiple styles.</li>
<li>Supported further extension/addition of more styles trivially.</li>
</ol>
<h2 id="things-learned">Things learned</h2>
<p>I made some statements in that post that I’m going to re-evaluate in
this post:</p>
<ol type="1">
<li>Let’s have a code style discussion. I propose to solve it with
tooling.</li>
<li>It’s not practical to force everyone into one single style.</li>
</ol>
<h2 id="code-formatting-is-solved-with-tooling">Code formatting is
solved with tooling</h2>
<p>I’ve used hindent for two years, it solves the problem. There are a
couple exceptions<a href="#fn1" class="footnote-ref" id="fnref1"
role="doc-noteref"><sup>1</sup></a>. On the whole, though, it’s a
completely different working experience:</p>
<ul>
<li>Code always looks the same.</li>
<li>I don’t make <em>any</em> style decisions. I just think about the
tree I need for my program.</li>
<li>I don’t do any manual line-breaking.</li>
<li>I’ve come to exploit it by writing lazy code like
<code>do   x&lt;-getLine;when(x&gt;5)(print 5)</code> and then hitting a
keybinding to reformat it.</li>
</ul>
<h2 id="switching-style-is-realistic">Switching style is realistic</h2>
<p>I’ve been writing Haskell in my own style for years. For me, my style
is better for structured editing, more consistent, and visually easier
to read, than most code I’ve seen. It’s like Lisp. Using hindent, with
my ChrisDone style, I had it automatically formatted for me. I used
2-space indents.</p>
<p>The most popular style in the community<a href="#fn2"
class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> is
JohanTibell: The alignment, line-breaking, and spacing (4 spaces instead
of 2) differs significantly to my own style.</p>
<p>At FP Complete I’ve done a lot of projects, private FP Complete
projects, client projects, and public FP Complete projects (like Stack).
For the first year or so I generally stuck to my guns when working on
code only I was going to touch and used my superior style.</p>
<p>But once the JohanTibell style in hindent was quite stable, I found
that <strong>I didn’t mind</strong> using it while collaborating with
people who prefer that style. The tooling made it so automatic, that I
didn’t have to understand the style or make any style decisions, I just
wrote code and got on with it. It doesn’t work great with
structured-haskell-mode, but that’s ok. Eventually I got used to it, and
eventually switched to using it for my own personal projects.</p>
<p>I completely did a U-turn. So I’m hoping that much of the community
can do so too and put aside their stylistic preferences and embrace a
standard.</p>
<h2 id="going-forward">Going forward</h2>
<p>hindent-5.* now supports <em>one style</em>, based on <a
href="https://github.com/tibbe/haskell-style-guide/blob/master/haskell-style.md">the
Johan Tibell style guide</a>. My <a
href="https://github.com/chrisdone/haskell-style-guide">own style
guide</a> is now deprecated in favor of that. The style flag
<code>--style foo</code> is now silently ignored.</p>
<p>There is a <a href="http://chrisdone.com/hindent/">demonstration web
site</a> in which you can try examples, and also get a link for the
example to show other people the output (for debugging).</p>
<p>HIndent now has a “literate” test suite here: <a
href="https://github.com/chrisdone/hindent/blob/master/TESTS.md">TESTS.md</a>.
You can read through it as a document, a bit like Johan’s style guide.
But running the test suite parses this file and checks that each code
fence is printed as written.</p>
<p>There’s also a <a
href="https://github.com/chrisdone/hindent/blob/master/BENCHMARKS.md">BENCHMARKS.md</a>,
since I rewrote comment handling, switched to a bytestring-builder,
improved the quadratic line-breaking algorithm to short-circuit, among
other improvements, hindent now formats things in 1.5ms instead of
1s.</p>
<p>For those who still want to stick with their old hindent, Andrew
Gibiansky is <a href="https://github.com/gibiansky/hindent">keeping a
fork of hindent 4</a> for his personal use, and has said he’ll accept
PR’s for that.</p>
<p>HIndent is not perfect, there’s always room for improvement (<a
href="https://github.com/chrisdone/hindent/issues">issue tracker</a>
welcomes issues), but over time that problem space gets smaller and
smaller. There is support for Emacs, Vim and Atom. I would appreciate
support for SublimeText too.</p>
<p>Give it a try!</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Such as CPP <code>#if</code>
directives–they are tricky to handle. Comments are also tricky, but I’ve
re-implemented comment handling from scratch and it works pretty well
now. See the <a
href="https://github.com/chrisdone/hindent/blob/master/TESTS.md#comments">pretty
extensive tests</a>.<a href="#fnref1" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p>From a survey of the top downloaded
1000 packages on Hackage, 660 are 4-spaced and 343 are 2-spaced. All
else being equal, 4 spaces wins.<a href="#fnref2" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2016-08-29 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Mon, 29 Aug 2016 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[A philosophical difference between Haskell and Lisp]]></title><link>https://chrisdone.com/posts/haskell-lisp-philosophy-difference</link><guid>https://chrisdone.com/posts/haskell-lisp-philosophy-difference</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>A philosophical difference between Haskell and Lisp</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>A philosophical difference between Haskell and Lisp</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p><strong>UPDATE 2020-08-03</strong>: I no longer stand by the content
in this post. I think the overall sentiment is marginally accurate;
however, the details in the post are incorrect (as many have pointed out
over the years).</p>
<p>As has been pointed out, <code>remove-if-not</code>’s start/count
parameters behave differently and cannot easily be separated out of the
function, a design trade-off that I appreciate.</p>
<p>As has been noted and pointed out, Clojure permits compositional
style and laziness. I would also point out that laziness isn’t exactly
necessary for stream fusion (just purity will do), but it helps with
ergonomics.</p>
<p>I don’t feel like pulling the article completely. It has made the
rounds on HN/reddit for years. I feel good about just admitting that
it’s not very good. Feel free to read on, but take it with a grain of
salt.</p>
<hr />
<p>One difference in philosophy of Lisp (e.g. Common Lisp, Emacs Lisp)
and Haskell is that the latter makes liberal use of many tiny functions
that do one single task. This is known as <em>composability</em>, or the
UNIX philosophy. In Lisp a procedure tends to accept many options which
configure its behaviour. This is known as <em>monolithism</em>, or to
make procedures like a kitchen-sink, or a Swiss-army knife.</p>
<p>Which one is better can be discussed in another post. I just want to
make the simple case that there is indeed a difference in philosophy and
practice. Having written my fair share of non-trivial Emacs Lisp (and a
small share of Common Lisp; I’ve maintained Common Lisp systems) and my
fair share of non-trivial Haskell I think I’m in a position to
judge.</p>
<p>Full disclosure: We’ll just look at some trivial examples anyone can
understand, with the (unproven but asserted) implication that these
examples are representative of the general way software is written in
these languages.</p>
<p>An example which should be readily familiar to any programmer of any
background is working on lists. For example, CL has the
<code>remove-if-not</code> procedure. Its documentation signature is
like this:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode lisp"><code class="sourceCode commonlisp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>(REMOVE-IF-NOT predicate seq <span class="bu">:key</span> <span class="bu">:count</span> <span class="bu">:start</span> <span class="bu">:end</span> <span class="bu">:from-end</span>)</span></code></pre></div>
<p>It packs a number of ideas into one procedure.</p>
<p>By comparison, Haskell has the <code>filter</code> function:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="fu">filter</span><span class="ot"> ::</span> (a <span class="ot">-&gt;</span> <span class="dt">Bool</span>) <span class="ot">-&gt;</span> [a] <span class="ot">-&gt;</span> [a]</span></code></pre></div>
<p>Given a problem statement “take all elements from the list–except the
first three–that satisfy predicate <code>p</code>, and take only the
first five of those”, in Common Lisp you’d express it quite concisely as
this:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode lisp"><code class="sourceCode commonlisp"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>(<span class="kw">remove-if-not</span> #&#39;p xs <span class="bu">:count</span> <span class="dv">5</span> <span class="bu">:start</span> <span class="dv">3</span>)</span></code></pre></div>
<p>The same in Haskell would be expressed as this:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="fu">take</span> <span class="dv">5</span> <span class="op">.</span> <span class="fu">filter</span> p <span class="op">.</span> <span class="fu">drop</span> <span class="dv">3</span></span></code></pre></div>
<p>The difference which should be obvious whether you know Haskell or
Lisp is that in the Lisp code the function does a few behaviours and
accepts arguments to configure them. In the Haskell code, we use three
different functions which do one task:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="fu">take</span> ∷ <span class="dt">Int</span> <span class="ot">-&gt;</span> [a] <span class="ot">-&gt;</span> [a]</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="fu">filter</span> ∷ (a <span class="ot">-&gt;</span> <span class="dt">Bool</span>) <span class="ot">-&gt;</span> [a] <span class="ot">-&gt;</span> [a]</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="fu">drop</span> ∷ <span class="dt">Int</span> <span class="ot">-&gt;</span> [a] <span class="ot">-&gt;</span> [a]</span></code></pre></div>
<p>The <code>.</code> operator composes functions together, just like
pipes in UNIX. We might express this in UNIX something like:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode bash"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="ex">bash-3.2$</span> cat <span class="kw">|</span> <span class="fu">tail</span> <span class="at">-n</span> <span class="st">&#39;+4&#39;</span> <span class="kw">|</span> <span class="fu">grep</span> <span class="at">-v</span> <span class="st">&#39;^p&#39;</span> <span class="kw">|</span> <span class="fu">head</span> <span class="at">-n</span> 5</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="ex">1</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="ex">2</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="ex">3</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="ex">4</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a><span class="ex">5</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a><span class="ex">6</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a><span class="ex">7</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a><span class="ex">8</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a><span class="ex">9</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a><span class="ex">10</span></span></code></pre></div>
<p>Press Ctrl-d here we get:</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode bash"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="ex">4</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="ex">5</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="ex">6</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="ex">7</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="ex">8</span></span></code></pre></div>
<p>Like pipes in UNIX, the functions are clever enough to be performant
when composed together–we don’t traverse the whole list and generate a
new list each time, each item is generated on demand. In fact, due to <a
href="http://chrisdone.com/posts/stream-composability">stream
fusion</a>, the code will be compiled into one fast loop.</p>
<p>If we want things that don’t satisfy the predicate, we just compose
again with <code>not</code>:</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="fu">take</span> <span class="dv">5</span> <span class="op">.</span> <span class="fu">filter</span> (<span class="fu">not</span> <span class="op">.</span> p) <span class="op">.</span> <span class="fu">drop</span> <span class="dv">3</span></span></code></pre></div>
<p>In Common Lisp composition is a bit wordier because it’s rarely if
ever used, so instead there is another function for that:</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>(remove<span class="op">-</span><span class="kw">if</span> <span class="op">#</span>&#39;p xs <span class="op">:</span>count <span class="dv">5</span> <span class="op">:</span>start <span class="dv">3</span>)</span></code></pre></div>
<p>(Probably a more Lispy approach would’ve been to have a
<code>:not</code> keyword argument to the <code>remove-if</code>
function.)</p>
<p>The most pathological example of such a kitchen sink in Lisp is the
well known LOOP macro.</p>
<p>Problem: get all elements less than 5, then just the even ones of
that set.</p>
<p>With the LOOP macro this can be expressed quite readily:</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode lisp"><code class="sourceCode commonlisp"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> (<span class="kw">loop</span> for i in &#39;(<span class="dv">1</span> <span class="dv">2</span> <span class="dv">3</span> <span class="dv">4</span>)</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>        <span class="kw">when</span> (<span class="kw">evenp</span> i)</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>        collect i</span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>        <span class="kw">when</span> (<span class="op">&gt;</span> i <span class="dv">5</span>) <span class="kw">do</span> (<span class="kw">return</span>))</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>(<span class="dv">2</span> <span class="dv">4</span>)</span></code></pre></div>
<p>In Haskell this is expressed with two separate functions:</p>
<div class="sourceCode" id="cb11"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> (<span class="fu">filter</span> <span class="fu">even</span> <span class="op">.</span> <span class="fu">takeWhile</span> (<span class="op">&lt;</span> <span class="dv">5</span>)) [<span class="dv">1</span><span class="op">..</span><span class="dv">4</span>]</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>[<span class="dv">2</span>,<span class="dv">4</span>]</span></code></pre></div>
<p>In Haskell the same applies to vector libraries and text libraries
and bytes libraries, which can be fused. Fusion is chiefly an advantage
of purity – you can fuse n loops together into one loop if you know that
they don’t do side-effects. Such an advantage can also be applied to
other pure languages like Idris or PureScript or Elm.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2015-12-19 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sat, 19 Dec 2015 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Use the REPL, Luke]]></title><link>https://chrisdone.com/posts/haskell-repl</link><guid>https://chrisdone.com/posts/haskell-repl</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Use the REPL, Luke</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Use the REPL, Luke</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>There was an online discussion about iteration times in Haskell and
whether and why they are slow. For me, it’s not slow. I do all my
Haskell development using a REPL. Here are some tips I wrote up in that
discussion.</p>
<h2 id="prepare-for-ghci-use">Prepare for GHCi use</h2>
<p>The first thing you want to do before writing anything for your
project is make sure you can load your code in the REPL; GHCi. Sometimes
you have special configuration options or whatnot
(<code>cabal repl</code> and <code>stack ghci</code> make this much
easier than in the past). The sooner you start the better. It can be a
PITA to load some projects that expect to just be a “start, run and die”
process, they often launch threads without any clean-up procedure; in
this way the REPL makes you think about cleaner architecture.</p>
<h2 id="make-sure-it-scales">Make sure it scales</h2>
<p>Learn <a href="http://chrisdone.com/posts/making-ghci-fast">how to
make GHCi</a> fast for your project so that you don’t hit a wall as your
project scales. Loading code with byte-code is much faster than object
code, but loading with object code has a cache so that in a 100 module
project if you only need to reload one, it’ll just load one. Make sure
this is happening for you, when you need it. Dabble with the
settings.</p>
<h2 id="write-small-parametrized-functions">Write small, parametrized
functions</h2>
<p>Code that is good for unit tests is code that is good for the REPL.
Write small functions that take state as arguments (<a
href="https://en.wikipedia.org/wiki/Dependency_injection">dependency
injection</a>) rather than loading their own state, then they can be ran
in the REPL and used in a test suite easily. Regard functions that you
can’t just call directly with suspicion.</p>
<h2 id="test-work-in-progress-implementations-in-the-repl">Test
work-in-progress implementations in the REPL</h2>
<p>While writing, test your function in the REPL with typical arguments
it will expect, rather than implementing a function and then immediately
using it in the place you want to ultimately use it. You can skip this
for trivial “glue” functions, but it’s helpful for non-trivial
functions.</p>
<h2 id="setupteardown-helpers">Setup/teardown helpers</h2>
<p>Write helpful setup/teardown code for your tests and REPL code. For
example, if you have a function that needs a database and application
configuration to do anything, write a function that automatically and
conveniently gets you a basic development config and database connection
for running some action.</p>
<h2 id="make-data-inspectable">Make data inspectable</h2>
<p>Make sure to include <code>Show</code> instances for your data types,
so that you can inspect them in the REPL. Treat <code>Show</code> as
your development instance, it’s for you, don’t use it for “real”
serialization or for “user-friendly” messages. Develop a distaste for
data structures that are hard to inspect.</p>
<h2 id="figure-out-the-fastest-iteration-for-you">Figure out the fastest
iteration for you</h2>
<p>Use techniques like <code>:reload</code> to help you out. For
example, if I’m working on <a
href="http://hackage.haskell.org/package/hindent">hindent</a>, then I
will test a style with <code>HIndent.test chrisDone "x = 1"</code>, for
example, in the REPL, and I’ll see the output pretty printed as Haskell
in my Emacs REPL. But I work on module
<code>HIndent.Style.ChrisDone</code>. So I first
<code>:load HIndent</code> and then for future work I use
<code>:reload</code> to reload my <code>.ChrisDone</code> changes and
give me the <code>HIndent</code> environment again.</p>
<h2 id="configuration">Configuration</h2>
<p>Make sure you know about the <code>.ghci</code> file which you can
put in your <code>~/</code> and also in the project directory where GHCi
is run from. You can use <code>:set</code> to set regular GHC options
including packages (<code>-package foo</code>) and extensions
(<code>-XFoo</code>), and any special include directories
(<code>-ifoo</code>).</p>
<h2 id="more-advanced-tricks">More advanced tricks</h2>
<p>Consider tricks like <a
href="http://chrisdone.com/posts/ghci-reload">live reloading</a>; if you
can support it. I wrote an IRC server and I can run it in the REPL,
reload the code, and update the handler function without losing any
state. If you use foreign-store you can make things available, like the
program’s state, in an IORef or MVar.</p>
<p>This trick is a trick, so don’t use it in production. But it’s about
as close as we can get to Lisp-style image development.</p>
<h2 id="in-summary">In summary</h2>
<p>Haskell’s lucky to have a small REPL culture, but you have to work
with a Lisp or Smalltalk to really know what’s possible when you fully
“buy in”. Many Haskellers come from C++ and “stop program, edit file,
re-run compiler, re-run whole program” cycles and don’t have much
awareness or interest in it. If you are such a person, the above
probably won’t come naturally, but try it out.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2015-07-15 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Wed, 15 Jul 2015 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[The path package]]></title><link>https://chrisdone.com/posts/path-package</link><guid>https://chrisdone.com/posts/path-package</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>The path package</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>The path package</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Here I’d like to announce and explain the motivations behind my <a
href="http://hackage.haskell.org/package/path">path</a> package.</p>
<h2 id="motivation">Motivation</h2>
<p>It was after working on a number of projects at FP Complete that use
file paths in various ways. We used the system-filepath package, which
was supposed to solve many path problems by being an opaque path type.
It occurred to me that the same kind of bugs kept cropping up:</p>
<ul>
<li>Expected a path to be absolute but it was relative, or
vice-versa.</li>
<li>Expected two equivalent paths to be equal or order the same, but
they did not (<code>/home//foo</code> vs <code>/home/foo/</code> vs
<code>/home/bar/../foo</code>, etc.).</li>
<li>Unpredictable behaviour with regards to concatenating paths.</li>
<li>Confusing files and directories.</li>
<li>Not knowing whether a path was a file or directory or relative or
absolute based on the type alone was a drag.</li>
</ul>
<p>All of these bugs are preventable.</p>
<h2 id="approach">Approach</h2>
<p>My approach to problems like this is to make a type that encodes the
properties I want and then make it <em>impossible</em> to let those
invariants be broken, without compromise or backdoors to let the wrong
value “slip in”. Once I have a path, I want to be able to trust it
fully. This theme will be seen throughout the things I lay out
below.</p>
<h2 id="solution">Solution</h2>
<p>After having to fix bugs due to these in our software, I put my foot
down and made:</p>
<ul>
<li>An opaque Path type (a newtype wrapper around String).</li>
<li>Smart constructors which are very stringent in the parsing.</li>
<li>Make the parsers highly normalizing.</li>
<li>Leave equality and concatenation to basic string equality and
concatenation.</li>
<li>Include relativity (absolute/relative) and type (directory/file) in
the type itself.</li>
<li>Use the already cross-platform <a
href="http://hackage.haskell.org/package/filepath">filepath</a> package
for implementation details.</li>
</ul>
<h2 id="implementation">Implementation</h2>
<h3 id="the-data-types">The data types</h3>
<p>Here is the type:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">Path</span> b t <span class="ot">=</span> <span class="dt">Path</span> <span class="dt">FilePath</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">deriving</span> (<span class="dt">Typeable</span>)</span></code></pre></div>
<p>The type variables are:</p>
<ul>
<li><code>b</code> - base, the base location of the path; absolute or
relative.</li>
<li><code>t</code> - type, whether file or directory.</li>
</ul>
<p>The base types can be filled with these:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Abs</span> <span class="kw">deriving</span> (<span class="dt">Typeable</span>)</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Rel</span> <span class="kw">deriving</span> (<span class="dt">Typeable</span>)</span></code></pre></div>
<p>And the type can be filled with these:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">File</span> <span class="kw">deriving</span> (<span class="dt">Typeable</span>)</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Dir</span> <span class="kw">deriving</span> (<span class="dt">Typeable</span>)</span></code></pre></div>
<p>(Why not use data kinds like <code>data Type = File | Dir</code>?
Because that imposes an extension overhead of adding
<code>{-# LANGUAGE DataKinds #-}</code> to every module you might want
to write out a path type in. Given that one cannot construct paths of
types other than these, via the operations in the module, it’s not a
concern for me.)</p>
<p>There is a conversion function to give you back the filepath:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ot">toFilePath ::</span> <span class="dt">Path</span> b t <span class="ot">-&gt;</span> <span class="dt">FilePath</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>toFilePath (<span class="dt">Path</span> l) <span class="ot">=</span> l</span></code></pre></div>
<h3 id="parsers">Parsers</h3>
<p>To get a path value, you need to use one of the four parsers:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ot">parseAbsDir  ::</span> <span class="dt">MonadThrow</span> m <span class="ot">=&gt;</span> <span class="dt">FilePath</span> <span class="ot">-&gt;</span> m (<span class="dt">Path</span> <span class="dt">Abs</span> <span class="dt">Dir</span>)</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="ot">parseRelDir  ::</span> <span class="dt">MonadThrow</span> m <span class="ot">=&gt;</span> <span class="dt">FilePath</span> <span class="ot">-&gt;</span> m (<span class="dt">Path</span> <span class="dt">Rel</span> <span class="dt">Dir</span>)</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="ot">parseAbsFile ::</span> <span class="dt">MonadThrow</span> m <span class="ot">=&gt;</span> <span class="dt">FilePath</span> <span class="ot">-&gt;</span> m (<span class="dt">Path</span> <span class="dt">Abs</span> <span class="dt">File</span>)</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="ot">parseRelFile ::</span> <span class="dt">MonadThrow</span> m <span class="ot">=&gt;</span> <span class="dt">FilePath</span> <span class="ot">-&gt;</span> m (<span class="dt">Path</span> <span class="dt">Rel</span> <span class="dt">File</span>)</span></code></pre></div>
<p>The following properties apply:</p>
<ul>
<li>Absolute parsers will reject non-absolute paths.</li>
<li>The only delimiter syntax accepted is the path separator;
<code>/</code> on POSIX and <code>\</code> on Windows.</li>
<li>Any other delimiter is rejected; <code>..</code>, <code>~/</code>,
<code>/./</code>, etc.</li>
<li>All parsers normalize into single separators:
<code>/home//foo</code> -&gt; <code>/home/foo</code>.</li>
<li>Directory parsers always normalize with a final trailing
<code>/</code>. So <code>/home/foo</code> parses into the string
<code>/home/foo/</code>.</li>
</ul>
<p>It was discussed briefly whether we should just have a class for
parsing rather than four separate parsing functions. In my experience so
far, I have had type errors where I wrote something like
<code>x &lt;- parseAbsDir someAbsDirString</code> because x was then
passed to a place that expected a relative directory. In this way,
overloading the return value would’ve just been accepted. So I don’t
think having a class is a good idea. Being explicit here doesn’t exactly
waste our time, either.</p>
<p>Why are these functions in <code>MonadThrow</code>? Because it means
I can have it return an Either, or a Maybe, if I’m in pure code, and if
I’m in IO, and I don’t expect parsing to ever fail, I can use it in IO
like this:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">do</span> x <span class="ot">&lt;-</span> parseRelFile (fromCabalFileName x)</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>   foo x</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>   …</span></code></pre></div>
<p>That’s really convenient and we take advantage of this at FP Complete
a lot.</p>
<h3 id="the-instances">The instances</h3>
<p>Equality, ordering and printing are simply re-using the String
instances:</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Eq</span> (<span class="dt">Path</span> b t) <span class="kw">where</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>  (<span class="op">==</span>) (<span class="dt">Path</span> x) (<span class="dt">Path</span> y) <span class="ot">=</span> x <span class="op">==</span> y</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Ord</span> (<span class="dt">Path</span> b t) <span class="kw">where</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>  <span class="fu">compare</span> (<span class="dt">Path</span> x) (<span class="dt">Path</span> y) <span class="ot">=</span> <span class="fu">compare</span> x y</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Show</span> (<span class="dt">Path</span> b t) <span class="kw">where</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>  <span class="fu">show</span> (<span class="dt">Path</span> x) <span class="ot">=</span> <span class="fu">show</span> x</span></code></pre></div>
<p>Which gives us for free the following equational properties:</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>toFilePath x <span class="op">==</span> toFilePath y        ≡ x <span class="op">==</span> y           <span class="co">-- Eq instance</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>toFilePath x <span class="ot">`compare`</span> toFilePath y ≡ x <span class="ot">`compare`</span> y    <span class="co">-- Ord instance</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>toFilePath x <span class="op">==</span> toFilePath y        ≡ <span class="fu">show</span> x <span class="op">==</span> <span class="fu">show</span> y <span class="co">-- Show instance</span></span></code></pre></div>
<p>In other words, the representation and the path you get out at the
end are the same. Two paths that are equal will always give you back the
same thing.</p>
<h3 id="smart-constructors">Smart constructors</h3>
<p>For when you know what a path will be at compile-time, there are
constructors for that:</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="op">$</span>(mkAbsDir <span class="st">&quot;/home/chris&quot;</span>)</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="op">$</span>(mkRelDir <span class="st">&quot;chris&quot;</span>)</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="op">$</span>(mkAbsFile <span class="st">&quot;/home/chris/x.txt&quot;</span>)</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="op">$</span>(mkRelFile <span class="st">&quot;chris/x.txt&quot;</span>)</span></code></pre></div>
<p>These will run at compile-time and underneath use the appropriate
parser.</p>
<h3 id="overloaded-strings">Overloaded strings</h3>
<p>No <code>IsString</code> instance is provided, because that has no
way to statically determine whether the path is correct, and would
otherwise have to be a partial function.</p>
<p>In practice I have written the wrong path format in a
<code>$(mk… "")</code> and been thankful it was caught early.</p>
<h3 id="operations">Operations</h3>
<p>There is path concatenation:</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="ot">(&lt;/&gt;) ::</span> <span class="dt">Path</span> b <span class="dt">Dir</span> <span class="ot">-&gt;</span> <span class="dt">Path</span> <span class="dt">Rel</span> t <span class="ot">-&gt;</span> <span class="dt">Path</span> b t</span></code></pre></div>
<p>Get the parent directory of a path:</p>
<div class="sourceCode" id="cb11"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="ot">parent ::</span> <span class="dt">Path</span> <span class="dt">Abs</span> t <span class="ot">-&gt;</span> <span class="dt">Path</span> <span class="dt">Abs</span> <span class="dt">Dir</span></span></code></pre></div>
<p>Get the filename of a file path:</p>
<div class="sourceCode" id="cb12"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="ot">filename ::</span> <span class="dt">Path</span> b <span class="dt">File</span> <span class="ot">-&gt;</span> <span class="dt">Path</span> <span class="dt">Rel</span> <span class="dt">File</span></span></code></pre></div>
<p>Get the directory name of a directory path:</p>
<div class="sourceCode" id="cb13"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="ot">dirname ::</span> <span class="dt">Path</span> b <span class="dt">Dir</span> <span class="ot">-&gt;</span> <span class="dt">Path</span> <span class="dt">Rel</span> <span class="dt">Dir</span></span></code></pre></div>
<p>Stripping the parent directory from a path:</p>
<div class="sourceCode" id="cb14"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="ot">stripDir ::</span> <span class="dt">MonadThrow</span> m <span class="ot">=&gt;</span> <span class="dt">Path</span> b <span class="dt">Dir</span> <span class="ot">-&gt;</span> <span class="dt">Path</span> b t <span class="ot">-&gt;</span> m (<span class="dt">Path</span> <span class="dt">Rel</span> t)</span></code></pre></div>
<h2 id="review">Review</h2>
<p>Let’s review my initial list of complaints and see if they’ve been
satisfied.</p>
<h3 id="relative-vs-absolute-confusion">Relative vs absolute
confusion</h3>
<p>Paths now distinguish in the type system whether they are relative or
absolute. You can’t append two absolute paths, for example:</p>
<div class="sourceCode" id="cb15"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="op">$</span>(mkAbsDir <span class="st">&quot;/home/chris&quot;</span>) <span class="op">&lt;/&gt;</span> <span class="op">$</span>(mkAbsDir <span class="st">&quot;/home/chris&quot;</span>)</span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>interactive<span class="op">&gt;:</span><span class="dv">23</span><span class="op">:</span><span class="dv">31</span><span class="op">-</span><span class="dv">55</span><span class="op">:</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Couldn&#39;t</span> match <span class="kw">type</span> ‘<span class="dt">Abs</span>’ with ‘<span class="dt">Rel</span>’</span></code></pre></div>
<h3 id="the-equality-problem">The equality problem</h3>
<p>Paths are now stringently normalized. They have to be a valid path,
and they only support single path separators, and all directories are
suffixed with a trailing path separator:</p>
<div class="sourceCode" id="cb16"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="op">$</span>(mkAbsDir <span class="st">&quot;/home/chris//&quot;</span>) <span class="op">==</span> <span class="op">$</span>(mkAbsDir <span class="st">&quot;/./home//chris&quot;</span>)</span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a><span class="dt">True</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> toFilePath <span class="op">$</span>(mkAbsDir <span class="st">&quot;/home/chris//&quot;</span>) <span class="op">==</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>   toFilePath <span class="op">$</span>(mkAbsDir <span class="st">&quot;/./home//chris&quot;</span>)</span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a><span class="dt">True</span></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> (<span class="op">$</span>(mkAbsDir <span class="st">&quot;/home/chris//&quot;</span>),toFilePath <span class="op">$</span>(mkAbsDir <span class="st">&quot;/./home//chris&quot;</span>))</span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a>(<span class="st">&quot;/home/chris/&quot;</span>,<span class="st">&quot;/home/chris/&quot;</span>)</span></code></pre></div>
<h3 id="unpredictable-concatenation-issues">Unpredictable concatenation
issues</h3>
<p>Because of the stringent normalization, path concatenation, as seen
above, is simply string concatenation. This is about as predictable as
it can get:</p>
<div class="sourceCode" id="cb17"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> toFilePath <span class="op">$</span>(mkAbsDir <span class="st">&quot;/home/chris//&quot;</span>)</span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;/home/chris/&quot;</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> toFilePath <span class="op">$</span>(mkRelDir <span class="st">&quot;foo//bar&quot;</span>)</span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;foo/bar/&quot;</span></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="op">$</span>(mkAbsDir <span class="st">&quot;/home/chris//&quot;</span>) <span class="op">&lt;/&gt;</span> <span class="op">$</span>(mkRelDir <span class="st">&quot;foo//bar&quot;</span>)</span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;/home/chris/foo/bar/&quot;</span></span></code></pre></div>
<h3 id="confusing-files-and-directories">Confusing files and
directories</h3>
<p>Now that the path type is encoded in the type system, our
<code>&lt;/&gt;</code> operator prevents improper appending:</p>
<div class="sourceCode" id="cb18"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="op">$</span>(mkAbsDir <span class="st">&quot;/home/chris/&quot;</span>) <span class="op">&lt;/&gt;</span> <span class="op">$</span>(mkRelFile <span class="st">&quot;foo//bar&quot;</span>)</span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;/home/chris/foo/bar&quot;</span></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="op">$</span>(mkAbsFile <span class="st">&quot;/home/chris&quot;</span>) <span class="op">&lt;/&gt;</span> <span class="op">$</span>(mkRelFile <span class="st">&quot;foo//bar&quot;</span>)</span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>interactive<span class="op">&gt;:</span><span class="dv">35</span><span class="op">:</span><span class="dv">1</span><span class="op">-</span><span class="dv">26</span><span class="op">:</span></span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Couldn&#39;t</span> match <span class="kw">type</span> ‘<span class="dt">File</span>’ with ‘<span class="dt">Dir</span>’</span></code></pre></div>
<h3 id="self-documentation">Self-documentation</h3>
<p>Now I can read the path like:</p>
<div class="sourceCode" id="cb19"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a>{<span class="ot"> fooPath ::</span> <span class="dt">Path</span> <span class="dt">Rel</span> <span class="dt">Dir</span>, <span class="op">...</span> }</span></code></pre></div>
<p>And know that this refers to the directory relative to some other
path, meaning I should be careful to consider the current directory when
using this in IO, or that I’ll probably need a parent to append to it at
some point.</p>
<h2 id="in-practice">In practice</h2>
<p>We’ve been using this at FP Complete in a number of packages for some
months now, it’s turned out surprisingly sufficient for most of our path
work with only one bug found. We weren’t sure initially whether it would
just be too much of a pain to use, but really it’s quite acceptable
given the advantages. You can see its use all over the <a
href="http://github.com/fpco/stack">stack</a> codebase.</p>
<h2 id="doing-io">Doing I/O</h2>
<p>Currently any operations involving I/O can be done by using the
existing I/O library:</p>
<div class="sourceCode" id="cb20"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a>doesFileExist (toFilePath fp)</span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a><span class="fu">readFile</span> (toFilePath fp)</span></code></pre></div>
<p>etc. This has problems with respect to accidentally running something
like:</p>
<div class="sourceCode" id="cb21"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a>doesFileExist <span class="op">$</span>(mkRelDir <span class="st">&quot;foo&quot;</span>)</span></code></pre></div>
<p>But I/O is currently outside the scope of what this package solves.
Once you leave the realm of the Path type invariants are back to your
responsibility.</p>
<p>As with the original version of this library, we’re currently
building up a set of functions in a <a
href="https://github.com/commercialhaskell/stack/blob/master/src/Path/IO.hs#L1"><code>Path.IO</code></a>
module over time that fits our real-world use-cases. It may or may not
appear in the path package eventually. It’ll need cleaning up and
considering what should really be included.</p>
<h2 id="doing-textual-manipulations">Doing textual manipulations</h2>
<p>One problem that crops up sometimes is wanting to manipulate paths.
Currently the way we do it is via the filepath library and re-parsing
the path:</p>
<div class="sourceCode" id="cb22"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a>parseAbsFile <span class="op">.</span> addExtension <span class="st">&quot;/directory/path&quot;</span> <span class="st">&quot;ext&quot;</span> <span class="op">.</span> toFilePath</span></code></pre></div>
<p>It doesn’t happen too often, in our experience, to the extent this
needs to be more convenient.</p>
<h2 id="accepting-user-input">Accepting user input</h2>
<p>Sometimes you have user input that contains <code>../</code>. The
solution we went with is to have a function like
<code>resolveDir</code>:</p>
<div class="sourceCode" id="cb23"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="ot">resolveDir ::</span> (<span class="dt">MonadIO</span> m, <span class="dt">MonadThrow</span> m)</span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>           <span class="ot">=&gt;</span> <span class="dt">Path</span> <span class="dt">Abs</span> <span class="dt">Dir</span> <span class="ot">-&gt;</span> <span class="dt">FilePath</span> <span class="ot">-&gt;</span> m (<span class="dt">Path</span> <span class="dt">Abs</span> <span class="dt">Dir</span>)</span></code></pre></div>
<p>Which will call <code>canonicalizePath</code> which collapses and
normalizes a path and then we parse with regular old
<code>parseAbsDir</code> and we’re cooking with gas. This and others
like it might get added to the <code>path</code> package.</p>
<h2 id="comparing-with-existing-path-libraries">Comparing with existing
path libraries</h2>
<h3 id="filepath-and-system-filepath">filepath and system-filepath</h3>
<p>The <a
href="http://hackage.haskell.org/package/filepath">filepath</a> package
is intended as the complimentary package to be used before parsing into
a Path value, and/or after printing from a Path value. The package
itself contains no type-safety, instead contains a range of
cross-platform textual operations. Definitely reach for this library
when you want to do more involved manipulations.</p>
<p>The <a
href="http://hackage.haskell.org/package/system-filepath">system-filepath</a>
package is deprecated in favour of <a
href="http://hackage.haskell.org/package/system-filepath">filepath</a>.</p>
<h3
id="system-canonicalpath-canonical-filepath-directory-tree">system-canonicalpath,
canonical-filepath, directory-tree</h3>
<p>The <a
href="http://hackage.haskell.org/package/system-canonicalpath">system-canonicalpath</a>
and the <a
href="http://hackage.haskell.org/package/canonical-filepath-1.0.0.3/docs/System-FilePath-Canonical.html">canonical-filepath</a>
packages both are a kind of subset of <code>path</code>. They
canonicalize a string into an opaque path, but neither distinguish
directories from files or absolute/relative. Useful if you just want a
canonical path but doesn’t do anything else.</p>
<p>The <a
href="http://hackage.haskell.org/package/directory-tree">directory-tree</a>
package contains a sum type of dir/file/etc but doesn’t distinguish in
its operations relativity or path type.</p>
<h3 id="pathtype">pathtype</h3>
<p>Finally, we come to a path library that <code>path</code> is similar
to: the <a
href="http://hackage.haskell.org/package/pathtype">pathtype</a> library.
There are the same types of <code>Path Abs File</code> /
<code>Path Rel Dir</code>, etc.</p>
<p>The points where this library isn’t enough for me are:</p>
<ul>
<li><p>There is an <code>IsString</code> instance, which means people
<em>will</em> use it, and <em>will</em> make mistakes.</p></li>
<li><p>Paths are not normalized into a predictable format, leading to me
being unsure when equality will succeed. This is the same problem I
encountered in system-filepath. The equality function normalizes, but
according to what properties I can reason about? I don’t know.</p></li>
</ul>
<div class="sourceCode" id="cb24"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="dt">System.Path.Posix</span><span class="op">&gt;</span> (<span class="st">&quot;/tmp//&quot;</span><span class="ot"> ::</span> <span class="dt">Path</span> a <span class="dt">Dir</span>) <span class="op">==</span> (<span class="st">&quot;/tmp&quot;</span><span class="ot"> ::</span> <span class="dt">Path</span> a <span class="dt">Dir</span>)</span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a><span class="dt">True</span></span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a><span class="dt">System.Path.Posix</span><span class="op">&gt;</span> (<span class="st">&quot;tmp&quot;</span><span class="ot"> ::</span> <span class="dt">Path</span> a <span class="dt">Dir</span>) <span class="op">==</span> (<span class="st">&quot;/tmp&quot;</span><span class="ot"> ::</span> <span class="dt">Path</span> a <span class="dt">Dir</span>)</span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a><span class="dt">True</span></span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a><span class="dt">System.Path.Posix</span><span class="op">&gt;</span> (<span class="st">&quot;/etc/passwd/&quot;</span><span class="ot"> ::</span> <span class="dt">Path</span> a b) <span class="op">==</span> (<span class="st">&quot;/etc/passwd&quot;</span><span class="ot"> ::</span> <span class="dt">Path</span> a b)</span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a><span class="dt">True</span></span>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a><span class="dt">System.Path.Posix</span><span class="op">&gt;</span> (<span class="st">&quot;/tmp//&quot;</span><span class="ot"> ::</span> <span class="dt">Path</span> <span class="dt">Abs</span> <span class="dt">Dir</span>) <span class="op">==</span> (<span class="st">&quot;/tmp/./&quot;</span><span class="ot"> ::</span> <span class="dt">Path</span> <span class="dt">Abs</span> <span class="dt">Dir</span>)</span>
<span id="cb24-8"><a href="#cb24-8" aria-hidden="true" tabindex="-1"></a><span class="dt">False</span></span>
<span id="cb24-9"><a href="#cb24-9" aria-hidden="true" tabindex="-1"></a><span class="dt">System.Path.Posix</span><span class="op">&gt;</span> (<span class="st">&quot;/tmp/../&quot;</span><span class="ot"> ::</span> <span class="dt">Path</span> <span class="dt">Abs</span> <span class="dt">Dir</span>) <span class="op">==</span> (<span class="st">&quot;/&quot;</span><span class="ot"> ::</span> <span class="dt">Path</span> <span class="dt">Abs</span> <span class="dt">Dir</span>)</span>
<span id="cb24-10"><a href="#cb24-10" aria-hidden="true" tabindex="-1"></a><span class="dt">False</span></span></code></pre></div>
<ul>
<li>Empty string should not be allowed, and introduction of
<code>.</code> due to that gets weird:</li>
</ul>
<div class="sourceCode" id="cb25"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="dt">System.Path.Posix</span><span class="op">&gt;</span> <span class="fu">fmap</span> getPathString (<span class="dt">Right</span> (<span class="st">&quot;.&quot;</span><span class="ot"> ::</span> <span class="dt">Path</span> <span class="dt">Rel</span> <span class="dt">File</span>))</span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Right</span> <span class="st">&quot;.&quot;</span></span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a><span class="dt">System.Path.Posix</span><span class="op">&gt;</span> <span class="fu">fmap</span> getPathString (mkPathAbsOrRel <span class="st">&quot;&quot;</span>)</span>
<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a><span class="dt">Right</span> <span class="st">&quot;.&quot;</span></span>
<span id="cb25-5"><a href="#cb25-5" aria-hidden="true" tabindex="-1"></a><span class="dt">System.Path.Posix</span><span class="op">&gt;</span> (<span class="dt">Right</span> (<span class="st">&quot;.&quot;</span><span class="ot"> ::</span> <span class="dt">Path</span> <span class="dt">Rel</span> <span class="dt">File</span>)) <span class="op">==</span> (mkPathAbsOrRel <span class="st">&quot;&quot;</span>)</span>
<span id="cb25-6"><a href="#cb25-6" aria-hidden="true" tabindex="-1"></a><span class="dt">False</span></span>
<span id="cb25-7"><a href="#cb25-7" aria-hidden="true" tabindex="-1"></a><span class="dt">System.Path.Posix</span><span class="op">&gt;</span> takeDirectory (<span class="st">&quot;tmp&quot;</span><span class="ot"> ::</span> <span class="dt">Path</span> <span class="dt">Rel</span> <span class="dt">Dir</span>)</span>
<span id="cb25-8"><a href="#cb25-8" aria-hidden="true" tabindex="-1"></a><span class="op">.</span></span>
<span id="cb25-9"><a href="#cb25-9" aria-hidden="true" tabindex="-1"></a><span class="dt">System.Path.Posix</span><span class="op">&gt;</span> (getPathString (<span class="st">&quot;.&quot;</span><span class="ot"> ::</span> <span class="dt">Path</span> <span class="dt">Rel</span> <span class="dt">File</span>) <span class="op">==</span></span>
<span id="cb25-10"><a href="#cb25-10" aria-hidden="true" tabindex="-1"></a>                    getPathString (<span class="st">&quot;&quot;</span><span class="ot"> ::</span> <span class="dt">Path</span> <span class="dt">Rel</span> <span class="dt">File</span>))</span>
<span id="cb25-11"><a href="#cb25-11" aria-hidden="true" tabindex="-1"></a><span class="dt">True</span></span>
<span id="cb25-12"><a href="#cb25-12" aria-hidden="true" tabindex="-1"></a><span class="dt">System.Path.Posix</span><span class="op">&gt;</span> ((<span class="st">&quot;.&quot;</span><span class="ot"> ::</span> <span class="dt">Path</span> <span class="dt">Rel</span> <span class="dt">File</span>) <span class="op">==</span> (<span class="st">&quot;&quot;</span><span class="ot"> ::</span> <span class="dt">Path</span> <span class="dt">Rel</span> <span class="dt">File</span>))</span>
<span id="cb25-13"><a href="#cb25-13" aria-hidden="true" tabindex="-1"></a><span class="dt">False</span></span></code></pre></div>
<ul>
<li><p>It has functions like
<code>&lt;.&gt;</code>/<code>addExtension</code> which lets you insert
an arbitrary string into a path.</p></li>
<li><p>Some functions let you produce nonsense (could be prevented by a
stricter type), for example:</p></li>
</ul>
<div class="sourceCode" id="cb26"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><span class="dt">System.Path.Posix</span><span class="op">&gt;</span> takeFileName (<span class="st">&quot;/tmp/&quot;</span><span class="ot"> ::</span> <span class="dt">Path</span> <span class="dt">Abs</span> <span class="dt">Dir</span>)</span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a>tmp</span></code></pre></div>
<p>I’m being a bit picky here, a bit unfair. But the point is really to
show the kind of things I tried to avoid in <code>path</code>. In
summary, it’s just hard to know where things can go wrong, similar to
what was going on in system-filepath.</p>
<h3 id="data-filepath">data-filepath</h3>
<p>The <a
href="http://hackage.haskell.org/package/data-filepath-2.2.0.0/docs/Data-FilePath.html">data-filepath</a>
is also very similar, I discovered it after writing my own at work and
was pleased to see it’s mostly the same. The main differences are:</p>
<ul>
<li>Uses DataKinds for the relative/absolute and file/dir distinction
which as I said above is an overhead.</li>
<li>Uses a GADT for the path type, which is fine. In my case I wanted to
retain the original string which functions that work on the
<code>FilePath</code> (String) type already deal with well. It does
change the parsing step somewhat, because it parses into segments.</li>
<li>It’s more lenient at parsing (allowing <code>..</code> and trailing
<code>.</code>).</li>
</ul>
<p>The API is a bit awkward to just parse a directory, requires a couple
functions to get it (going via <code>WeakFilePath</code>), returning
only an Either, and there are no functions like <code>parent</code>. But
there’s not much to complain about. It’s a fine library, but I didn’t
feel the need to drop my own in favor of it. Check it out and decide for
yourself.</p>
<h2 id="summary">Summary</h2>
<p>There’s a growing interest in making practical use of well-typed file
path handling. I think everyone’s wanted it for a while, but few people
have really committed to it in practice. Now that I’ve been using
<code>path</code> for a while, I can’t really go back. It’ll be
interesting to see what new packages crop up in the coming year, I
expect there’ll be more.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2015-06-27 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sat, 27 Jun 2015 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Existentials and the heterogenous list fallacy]]></title><link>https://chrisdone.com/posts/existentials</link><guid>https://chrisdone.com/posts/existentials</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Existentials and the heterogenous list fallacy</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Existentials and the heterogenous list fallacy</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>An oft-stated argument against static typing is that heterogenous
lists are unreasonably difficult to model. Why is static typing being so
difficult? Why can’t it just be like dynamic typing? This is a specious
argument.</p>
<p>For example, in one article I read, I saw:</p>
<blockquote>
<p>In fact you can program heterogeneous lists in dependently typed
languages, but it’s unreasonably complicated. Python makes no
complaints:</p>
<pre><code>&gt;&gt;&gt; g = lambda x: x**2
&gt;&gt;&gt; [1, &#39;a&#39;, &quot;hello&quot;, g]
[1, &#39;a&#39;, &#39;hello&#39;, &lt;function &lt;lambda&gt; at 0x103e4aed8&gt;]</code></pre>
<p>To me this is one methodological weakness of type theory […]</p>
</blockquote>
<p>(I’m not sure what “methodological weakness” is supposed to mean, but
let’s ignore that.)</p>
<p>There are two problems with this argument and demonstration:</p>
<ol type="1">
<li>It’s contrived. I’ve written about as much Emacs Lisp and JavaScript
as I have written Haskell and C#, and I cannot with all intellectual
honesty remember wanting a heterogenous list.<a href="#fn1"
class="footnote-ref" id="fnref1"
role="doc-noteref"><sup>1</sup></a></li>
<li>It’s ill-defined. What is this data structure? What can I assume
about the elements so that I can write operations generically? Which, I
presume, is the only reason I would be using a list in the first place
(otherwise a record would be the correct thing to use); to write
algorithms that apply generally to any index.</li>
</ol>
<p>Even cutting the author some slack and assuming they might want to
just temporarily put some things together as a tuple, static languages
have tuples, which are heterogenous.</p>
<p>When you look at it beyond the superficial, it’s rather odd.</p>
<p>Regardless, I am sporting. Some people will say, yes, okay, it’s
contrived, and never really arises, but <em>if I really wanted
this</em>, how could I do it in a statically typed language? So here is
the above in Haskell.</p>
<p>Let’s look at the example:</p>
<pre><code>&gt;&gt;&gt; g = lambda x: x**2
&gt;&gt;&gt; [1, &#39;a&#39;, &quot;hello&quot;, g]
[1, &#39;a&#39;, &#39;hello&#39;, &lt;function &lt;lambda&gt; at 0x103e4aed8&gt;]</code></pre>
<p>So the list contains a bunch of disparate things and the implicit
invariant here is that we can print each of them out. So we can model
that with an existential data type <code>Py</code> (for “Python”) that
holds some type <code>a</code> that is showable.</p>
<pre><code>data Py = forall a. Show a =&gt; Py a
instance Show Py where show (Py s) = show s</code></pre>
<p>(Oh, Haskell doesn’t define an instance for printing functions, so
let’s use
<code>instance Show (a -&gt; b) where show _ = "&lt;function&gt;"</code>
to vaguely match Python.)</p>
<p>I may not know, or care, <em>what</em> the type is, but I at least
need to know <em>something about it</em>, in a duck-typing kind of way.
If it walks like a duck, quacks like a duck, etc. then it’s a good
enough duck for my purposes. In this case, <code>Py</code> says, is it
at least showable?</p>
<p>Now we can wrap up any type which is an instance of <code>Show</code>
with that:</p>
<pre><code>λ&gt; [Py 1,Py &#39;a&#39;,Py &quot;hello&quot;,Py (\x -&gt; x ** 2)]
[1,&#39;a&#39;,&quot;hello&quot;,&lt;function&gt;]</code></pre>
<p>And we can apply the <code>show</code> method (from the
<code>Show</code> class) to each element generically:</p>
<pre><code>λ&gt; map (\(Py p) -&gt; show p) [Py 1,Py &#39;a&#39;,Py &quot;hello&quot;,Py (\x -&gt; x ** 2)]
[&quot;1&quot;,&quot;&#39;a&#39;&quot;,&quot;\&quot;hello\&quot;&quot;,&quot;&lt;function&gt;&quot;]</code></pre>
<p>So that’s how to do it.</p>
<p>Continuing the discussion, if I extend the type to support also
<code>Num</code> (numbers),</p>
<pre><code>data Py = forall a. (Show a,Num a) =&gt; Py a</code></pre>
<p>then I can use <code>*</code>, but only for actual numbers. If I try
something else I get a type error:</p>
<pre><code>λ&gt; map (\(Py p) -&gt; Py (p*2)) [Py 1,Py &#39;c&#39;]
&lt;interactive&gt;:634:33:
    No instance for (Num Char) arising from a use of ‘Py’
    In the expression: Py &#39;c&#39;
λ&gt; map (\(Py p) -&gt; Py (p*2)) [Py 1,Py 2.0]
[2,4.0]</code></pre>
<p>Doing the same in Python, we have more or less the same error:</p>
<pre><code>&gt;&gt;&gt; def pow2(x): return x ** 2
...
&gt;&gt;&gt; list(map(pow2,[1,5,&#39;a&#39;]))
Traceback (most recent call last):
  File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
  File &quot;&lt;stdin&gt;&quot;, line 1, in pow2
TypeError: unsupported operand type(s) for ** or pow(): &#39;str&#39; and &#39;int&#39;</code></pre>
<p>The difference being the Haskell error was signaled statically at
compile-time and the Python error was signalled dynamically at
run-time.</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>To demonstrate my good faith, I have
constructed heterogenous lists in Emacs Lisp to model a record, but this
is because Emacs Lisp lacks native records. JavaScript, on the other
hand, has records.<a href="#fnref1" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2015-06-21 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sun, 21 Jun 2015 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[The constraint trick for instances]]></title><link>https://chrisdone.com/posts/haskell-constraint-trick</link><guid>https://chrisdone.com/posts/haskell-constraint-trick</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>The constraint trick for instances</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>The constraint trick for instances</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Ever seen this in a library,</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> (var <span class="op">~</span> <span class="dt">AType</span>) <span class="ot">=&gt;</span> <span class="dt">ClassName</span> (<span class="dt">SomeType</span> var)</span></code></pre></div>
<p>and thought, “Shenanigans! Why not just have this?”</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">ClassName</span> (<span class="dt">SomeType</span> <span class="dt">AType</span>)</span></code></pre></div>
<p>Me too!</p>
<p>I only learned of this solution relatively recently, and I know
experienced Haskellers who also only understood this recently or still
don’t. Hence this quick write up. Here’s the thought process.</p>
<p>We’re writing a trivial pretty printer and we’re using
<code>Writer</code>. We write things like:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> execWriter (<span class="kw">do</span> tell <span class="st">&quot;hello&quot;</span>; tell <span class="st">&quot;world&quot;</span><span class="ot"> ::</span> <span class="dt">Writer</span> <span class="dt">String</span> ())</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;helloworld&quot;</span></span></code></pre></div>
<p>Quality. But writing <code>tell</code> every time is so boring! How
about we use the <code>IsString</code> class so that we can just write
the string literals like this?</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">do</span> <span class="st">&quot;hello&quot;</span>; <span class="st">&quot;world&quot;</span></span></code></pre></div>
<p>Let’s write the <code>IsString</code> instance:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">IsString</span> (<span class="dt">Writer</span> <span class="dt">String</span> a) <span class="kw">where</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>  fromString <span class="ot">=</span> tell</span></code></pre></div>
<p>What do you say, GHC?</p>
<blockquote>
<p>Couldn’t match type ‘a’ with ‘()’</p>
<p>‘a’ is a rigid type variable bound by the instance declaration</p>
</blockquote>
<p>Oh. Good point. The type of our <code>tell</code> call results in
<code>Writer String ()</code>. A small set back. Fine, let’s change the
instance declaration to just be <code>()</code>:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">IsString</span> (<span class="dt">Writer</span> <span class="dt">String</span> ()) <span class="kw">where</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>  fromString <span class="ot">=</span> tell</span></code></pre></div>
<p>GHC loves it!</p>
<p>Let’s try using it:</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> execWriter (<span class="kw">do</span> <span class="st">&quot;hello&quot;</span>; <span class="st">&quot;world&quot;</span><span class="ot"> ::</span> <span class="dt">Writer</span> <span class="dt">String</span> ())</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>interactive<span class="op">&gt;:</span><span class="dv">42</span><span class="op">:</span><span class="dv">16</span><span class="op">:</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">No</span> <span class="kw">instance</span> for (<span class="dt">IsString</span> (<span class="dt">WriterT</span> <span class="dt">String</span> <span class="dt">Identity</span> a))</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>      arising from the literal ‘<span class="st">&quot;hello&quot;</span>’</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">The</span> <span class="kw">type</span> variable ‘a’ is ambiguous</span></code></pre></div>
<p>This displeases me. But it adds up given the type of
<code>(&gt;&gt;)</code>:</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ot">(&gt;&gt;) ::</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> m a <span class="ot">-&gt;</span> m b <span class="ot">-&gt;</span> m b</span></code></pre></div>
<p>In <code>_ &gt;&gt; return () :: Writer String ()</code>, the type of
<code>_</code> is <code>Writer String a</code>, so we really need an
<code>IsString</code> instance that matches that. But we
<em>already</em> tried that. Oh, woe<em>!</em></p>
<p>Some people reading this will be nodding in recognition of this same
problem they had while writing that perfect API that <em>just</em> won’t
work because of this niggling issue.</p>
<p>Here comes the trick.<a href="#fn1" class="footnote-ref" id="fnref1"
role="doc-noteref"><sup>1</sup></a> So let’s go back to a basic
instance:</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">MyTuple</span> a b <span class="ot">=</span> <span class="dt">MyTuple</span> a b</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Show</span> (<span class="dt">MyTuple</span> a b) <span class="kw">where</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>  <span class="fu">show</span> _ <span class="ot">=</span> <span class="st">&quot;MyTuple &lt;some value&gt; &lt;some value&gt;&quot;</span></span></code></pre></div>
<p>Suppose I replace this instance with a new instance that has
constraints:</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> (<span class="dt">Show</span> a,<span class="dt">Show</span> b) <span class="ot">=&gt;</span> <span class="dt">Show</span> (<span class="dt">MyTuple</span> a b) <span class="kw">where</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>  <span class="fu">show</span> (<span class="dt">MyTuple</span> a b) <span class="ot">=</span> <span class="st">&quot;MyTuple &quot;</span> <span class="op">++</span> <span class="fu">show</span> a <span class="op">++</span> <span class="st">&quot; &quot;</span> <span class="op">++</span> <span class="fu">show</span> b</span></code></pre></div>
<p>Question: Does that change whether GHC decides to pick this new
version of instance over others that may be available, compared to the
one above? Have a think.</p>
<p>The answer is: nein! The constraints of an instance don’t have
anything to do with deciding whether an instance is picked from the list
of instances available. Constraints only apply <em>after GHC has already
decided it’s going with this instance</em>.</p>
<p>So, cognizant of this obvious-after-the-fact property, let’s use the
equality constraint that was introduced with GADTs and type families
(enabling either brings in <code>~</code>):</p>
<div class="sourceCode" id="cb11"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> a <span class="op">~</span> () <span class="ot">=&gt;</span> <span class="dt">IsString</span> (<span class="dt">Writer</span> <span class="dt">String</span> a) <span class="kw">where</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>  fromString <span class="ot">=</span> tell</span></code></pre></div>
<p>Let’s try it:</p>
<div class="sourceCode" id="cb12"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> execWriter (<span class="kw">do</span> <span class="st">&quot;hello&quot;</span> ; <span class="st">&quot;world&quot;</span><span class="ot"> ::</span> <span class="dt">Writer</span> <span class="dt">String</span> ())</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;helloworld&quot;</span></span></code></pre></div>
<p>This instance is picked by GHC, as we hoped, because of the
<code>a</code>. The instance method also type checks, because the
constraint applies when type checking the instance methods, just like if
you write a regular declaration like:</p>
<div class="sourceCode" id="cb13"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="ot">foo ::</span> (a <span class="op">~</span> ()) <span class="ot">=&gt;</span> a</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>foo <span class="ot">=</span> ()</span></code></pre></div>
<p>That’s it! This crops up in a number of my own libraries and knowing
this really helped me. Here is <a
href="https://github.com/chrisdone/lucid/blob/16c4b09ee90e2e61fef0e1070c0c3ebaf6246da1/src/Lucid/Base.hs#L81">a
real example from my <code>lucid</code> library</a>:</p>
<div class="sourceCode" id="cb14"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> (a <span class="op">~</span> (),<span class="dt">Monad</span> m) <span class="ot">=&gt;</span> <span class="dt">Monoid</span> (<span class="dt">HtmlT</span> m a) <span class="kw">where</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>  <span class="fu">mempty</span>  <span class="ot">=</span> <span class="fu">return</span> <span class="fu">mempty</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>  <span class="fu">mappend</span> <span class="ot">=</span> liftM2 <span class="fu">mappend</span></span></code></pre></div>
<p>Hope this was helpful!</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Actually, it’s a natural consequence
to grokking how instance resolution works (but calling it a “trick”
makes for a catchy title).<a href="#fnref1" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2015-06-19 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Fri, 19 Jun 2015 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Stream fusion and composability (Java 8 and Haskell) for newbies]]></title><link>https://chrisdone.com/posts/stream-composability</link><guid>https://chrisdone.com/posts/stream-composability</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Stream fusion and composability (Java 8 and Haskell) for
newbies</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Stream fusion and composability (Java 8 and Haskell) for
newbies</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>In an online discussion, when Java 8 released their stream API,
written about <a
href="http://www.deadcoderising.com/java-8-no-more-loops/">here</a>, you
can write e.g.</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span> <span class="bu">List</span><span class="op">&lt;</span>Article<span class="op">&gt;</span> <span class="fu">getAllJavaArticles</span><span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> articles<span class="op">.</span><span class="fu">stream</span><span class="op">()</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">filter</span><span class="op">(</span>article <span class="op">-&gt;</span> article<span class="op">.</span><span class="fu">getTags</span><span class="op">().</span><span class="fu">contains</span><span class="op">(</span><span class="st">&quot;Java&quot;</span><span class="op">))</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>        <span class="op">.</span><span class="fu">collect</span><span class="op">(</span>Collectors<span class="op">.</span><span class="fu">toList</span><span class="op">());</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Someone asked, “But my question: would the streams be faster than
loops? Or is the only benefit better readability?” Someone answered that
the benefit is that streams compose and loops don’t. What does
composable mean here? Below is my answer, using two languages I know,
JavaScript and Haskell.</p>
<p>Composable in this context means: To be able to compose two things
into one without redundancy or overhead. For example, consider you want
to map a function <code>f</code> over an array <code>arr</code> to
produce a new array, you might do this:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> arr2 <span class="op">=</span> []<span class="op">;</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> (<span class="kw">var</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> arr<span class="op">.</span><span class="at">length</span><span class="op">;</span> i<span class="op">++</span>)</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    arr2<span class="op">.</span><span class="fu">push</span>(<span class="fu">f</span>(arr[i]))<span class="op">;</span></span></code></pre></div>
<p>If you want to filter the array based on a predicate <code>p</code>,
you might do this:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> arr3 <span class="op">=</span> []<span class="op">;</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> (<span class="kw">var</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> arr2<span class="op">.</span><span class="at">length</span><span class="op">;</span> i<span class="op">++</span>)</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> (<span class="fu">p</span>(arr2[i]))</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>        arr3<span class="op">.</span><span class="fu">push</span>(arr2[i])<span class="op">;</span></span></code></pre></div>
<p>Or maybe you want to take all elements until a a predicate
<code>p2</code> is not satisfied:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> arr4 <span class="op">=</span> []<span class="op">;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> (<span class="kw">var</span> i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> arr3<span class="op">.</span><span class="at">length</span><span class="op">;</span> i<span class="op">++</span>)</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> (<span class="fu">p2</span>(arr3[i]))</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>        arr4<span class="op">.</span><span class="fu">push</span>(arr3[i])<span class="op">;</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">else</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>        <span class="cf">break</span><span class="op">;</span></span></code></pre></div>
<p>Now, if you want to do that all in one process you have a few
options:</p>
<ul>
<li>Put them all one after the other verbatim as I’ve written above.
Redundant, a maintenance issue and inefficient.</li>
<li>Merge them all into one clever loop. Also redundant (re-implementing
the same concept of mapping, filtering and taking), error prone (it’s
easy to get manual loops wrong, especially merging several concepts
together), and a maintenance burden.</li>
<li>Put them each into a method on your language’s Array type as
<code>map()</code>, <code>filter()</code>, and <code>takeWhile()</code>
and then write <code>arr.map(f).filter(p).takeWhile(p2)</code>. Good
abstraction, very low maintenance because the functions are black boxes.
But inefficient.</li>
</ul>
<p>An ideal stream API will give you the last point, but be able to
understand concepts like mapping and filtering and know how to merge
them together into an efficient loop. This is called stream fusion,
which you can google if you want to know more.</p>
<p>I don’t know Java but I can give a Haskell example:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="fu">map</span> f <span class="op">.</span> <span class="fu">filter</span> p <span class="op">.</span> <span class="fu">takeWhile</span> p2</span></code></pre></div>
<p>(Note: In Haskell the operations separated by <code>.</code> are run
right to left, like <code>map f (filter p (takeWhile p2 …))</code>.)</p>
<p>If I compile this with GHC, e.g.</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="fu">print</span> ((<span class="fu">map</span> f <span class="op">.</span> <span class="fu">filter</span> p <span class="op">.</span> <span class="fu">takeWhile</span> p2) [<span class="dv">1</span><span class="op">..</span><span class="dv">10</span>])</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">where</span> p2 <span class="ot">=</span> (<span class="op">&lt;</span><span class="dv">5</span>)</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>        p <span class="ot">=</span> <span class="fu">even</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>        f <span class="ot">=</span> (<span class="op">+</span><span class="dv">2</span>)</span></code></pre></div>
<p>and look at the reduced output called Core, a language the compiler
generates code for before generating assembly or byte code, the
<code>map f . filter p</code> are both compiled into a single loop (Core
output is verbose, so I collapsed it into this more readable form). This
just walks over the list, checks whether the item is even, if so, keeps
it and adds 2 to it, otherwise skips that item:</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>mainzugo xs <span class="ot">=</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">case</span> xs <span class="kw">of</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>    [] <span class="ot">-&gt;</span> []</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>    (x<span class="op">:</span>ys) <span class="ot">-&gt;</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>      <span class="kw">case</span> <span class="fu">even</span> x <span class="kw">of</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>        <span class="dt">False</span> <span class="ot">-&gt;</span> mainzugo ys</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>        <span class="dt">True</span> <span class="ot">-&gt;</span> x <span class="op">+</span> <span class="dv">2</span> <span class="op">:</span> mainzugo ys</span></code></pre></div>
<p>Which is pretty nifty. Furthermore, if you fold (also called
reducing) e.g.</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="fu">foldr</span> (<span class="op">+</span>) <span class="dv">0</span> <span class="op">.</span> <span class="fu">map</span> f <span class="op">.</span> <span class="fu">filter</span> p</span></code></pre></div>
<p>Then that whole thing is also compiled into one loop:</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>mainzugo xs <span class="ot">=</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">case</span> xs <span class="kw">of</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>    [] <span class="ot">-&gt;</span> <span class="dv">0</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>    (x<span class="op">:</span>ys) <span class="ot">-&gt;</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>      <span class="kw">case</span> <span class="fu">even</span> x <span class="kw">of</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>        <span class="dt">False</span> <span class="ot">-&gt;</span> mainzugo ys</span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>        <span class="dt">True</span> <span class="ot">-&gt;</span> (x <span class="op">+</span> <span class="dv">2</span>) <span class="op">+</span> mainzugo ys</span></code></pre></div>
<p>There’re limits to what can compose with what, though.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2015-06-11 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Thu, 11 Jun 2015 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[My Haskell tooling wishlist]]></title><link>https://chrisdone.com/posts/haskell-wishlist</link><guid>https://chrisdone.com/posts/haskell-wishlist</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>My Haskell tooling wishlist</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>My Haskell tooling wishlist</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>I spend a lot of my time on Haskell tooling, both for my hobbies and
my job. Almost every project I work on sparks a desire for another piece
of tooling. Much of the time, I’ll follow that wish and take a detour to
implement that thing (Fay, structured-haskell-mode, hindent, are some
Haskell-specific examples). But in the end it means less time working on
the actual domain problem I’m interested in, so a while ago I
intentionally placed a quota on the amount of time I can spend on
this.</p>
<p>So this page will contain a list of things I’d work on if I had
infinite spare time, and that I wish someone else would make. I’ll
update it from time to time as ideas come to the fore.</p>
<p>These projects are non-trivial but are do-able by one person who has
enough free time and motivation. There is a common theme among the
projects listed, which is that they are things that Haskell among most
other well known languages is particularly well suited for and yet we
don’t have such tooling as standard tools in the Haskell tool box. They
should be!</p>
<h2 id="an-equational-reasoning-assistant">An equational reasoning
assistant</h2>
<p>Equational reasoning lets you prove properties about your functions
by following a simple substitution model to state that one term is equal
to another. The approach I typically take is to expand and reduce until
both sides of the equation are the same.</p>
<p>Here is an example. I have a data type, <code>Consumer</code>. Here
is an instance of <code>Functor</code>:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Functor</span> (<span class="dt">Consumer</span> s d) <span class="kw">where</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  <span class="fu">fmap</span> f (<span class="dt">Consumer</span> d p) <span class="ot">=</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Consumer</span> d</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>             (\s <span class="ot">-&gt;</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>                <span class="kw">case</span> p s <span class="kw">of</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>                  (<span class="dt">Failed</span> e,s&#39;) <span class="ot">-&gt;</span> (<span class="dt">Failed</span> e,s&#39;)</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>                  (<span class="dt">Continued</span> e,s&#39;) <span class="ot">-&gt;</span> (<span class="dt">Continued</span> e,s&#39;)</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>                  (<span class="dt">Succeeded</span> a,s&#39;) <span class="ot">-&gt;</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>                    (<span class="dt">Succeeded</span> (f a),s&#39;))</span></code></pre></div>
<p>I want to prove that it is a law-abiding instance of Functor, which
means proving that <code>fmap id ≡ id</code>. You don’t need to know
anything about the <code>Consumer</code> type itself, just this
implementation. Here are some very mechanical steps one can take to
prove this:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="fu">id</span> ≡ <span class="fu">fmap</span> <span class="fu">id</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>   ≡ \(<span class="dt">Consumer</span> d p) <span class="ot">-&gt;</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Consumer</span> d</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>         (\s <span class="ot">-&gt;</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>            <span class="kw">case</span> p s <span class="kw">of</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>              (<span class="dt">Failed</span> e,s&#39;) <span class="ot">-&gt;</span> (<span class="dt">Failed</span> e,s&#39;)</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>              (<span class="dt">Continued</span> e,s&#39;) <span class="ot">-&gt;</span> (<span class="dt">Continued</span> e,s&#39;)</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>              (<span class="dt">Succeeded</span> a,s&#39;) <span class="ot">-&gt;</span> (<span class="dt">Succeeded</span> (<span class="fu">id</span> a),s&#39;))</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>   ≡ \(<span class="dt">Consumer</span> d p) <span class="ot">-&gt;</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Consumer</span> d</span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>         (\s <span class="ot">-&gt;</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>            <span class="kw">case</span> p s <span class="kw">of</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>              (<span class="dt">Failed</span> e,s&#39;) <span class="ot">-&gt;</span> (<span class="dt">Failed</span> e,s&#39;)</span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>              (<span class="dt">Continued</span> e,s&#39;) <span class="ot">-&gt;</span> (<span class="dt">Continued</span> e,s&#39;)</span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>              (<span class="dt">Succeeded</span> a,s&#39;) <span class="ot">-&gt;</span> (<span class="dt">Succeeded</span> a,s&#39;))</span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>   ≡ \(<span class="dt">Consumer</span> d p) <span class="ot">-&gt;</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Consumer</span> d</span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a>         (\s <span class="ot">-&gt;</span> p s)</span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a>   ≡ \(<span class="dt">Consumer</span> d p) <span class="ot">-&gt;</span></span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Consumer</span> d p</span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a>   ≡ <span class="fu">id</span></span></code></pre></div>
<p>So that’s:</p>
<ul>
<li>Expand the <code>fmap id</code> into the instance’s
implementation.</li>
<li>Reduce by applying the property that <code>id x ≡ x</code>.</li>
<li>Reason that if every branch of a case returns the original value of
the case, then that whole case is an identity and can be dropped.</li>
<li>Eta-reduce.</li>
<li>Again, pattern-matching lambdas are just syntactic sugar for cases,
so by the same rule this can be considered identity.</li>
<li>End up with what we wanted to prove: <code>fmap id ≡ id</code></li>
</ul>
<p>These are pretty mechanical steps. They’re also pretty laborious and
error-prone. Of course, if you look at the first step, it’s pretty
obvious the whole thing is an identity, but writing the steps out
provides transformations that can be statically checked by a program. So
it’s a good example, because it’s easily understandable and you can
imagine proving something more complex would require a lot more steps
and a lot more substitutions. Proof of <a
href="http://lpaste.net/5232874250913710080">identity for Applicative
has substantially more steps</a>, but is equally mechanical.</p>
<p>Wouldn’t it be nice if there was a tool which given some expression
would do the following?</p>
<ul>
<li>Suggest a list of in-place expansions.</li>
<li>Suggest a list of reductions based on a set of pre-defined rules (or
axioms).</li>
</ul>
<p>Then I could easily provide an interactive interface for this from
Emacs.</p>
<p>In order to do expansion, you need the original source of the
function name you want to expand. So in the case of <code>id</code>,
that’s why I suggested stating an axiom (id a ≡ a) for this. Similarly,
I could state the identity law for Monoids by saying
<code>mappend mempty a ≡ a</code>, <code>mappend a mempty ≡ a</code>. I
don’t necessarily need to expand the source of all functions. Usually
just the ones I’m interested in.</p>
<p>Given such a system, for my example above, the program could actually
perform all those steps automatically and spit out the steps so that I
can read them if I choose, or otherwise accept that the proof was
derived sensibly.</p>
<p>In fact, suppose I have my implementation again, and I state what
must be satisfied by the equational process (and, perhaps, some axioms
that might be helpful for doing it, but in this case our axioms are
pretty standard), I might write it like this:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Functor</span> (<span class="dt">Consumer</span> s d) <span class="kw">where</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>  <span class="fu">fmap</span> f (<span class="dt">Consumer</span> d p) <span class="ot">=</span> <span class="op">...</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>proof [<span class="op">|</span><span class="fu">fmap</span> <span class="fu">id</span> ≡<span class="ot"> id ::</span> <span class="dt">Consumer</span> s d a<span class="op">|</span>]</span></code></pre></div>
<p>This template-haskell macro <code>proof</code> would run the steps
above and if the equivalence is satisfied, the program compiles. If not,
it generates a compile error, showing the steps it performed and where
it got stuck. TH has limitations, so it might require writing it another
way.</p>
<p>Such a helpful tool would also encourage people (even newbies) to do
more equational reasoning, which Haskell is often claimed to be good at
but you don’t often see it in evidence in codebases. In practice isn’t a
standard thing.</p>
<p>Promising work in this area:</p>
<ul>
<li><a
href="http://ittc.ku.edu/~andygill/papers/IntroHERA06.pdf">Introducing
the Haskell Equational Reasoning Assistant</a> – works pretty much how I
described above. I don’t know where the source is, I’ve emailed the
author about it. Will update with any results.</li>
</ul>
<p><strong>Update 2014-01-25</strong>: Andrew Gill got back to me that
<a href="http://ku-fpg.github.io/software/hermit/">HERMIT</a> is the
continuation of HERA. It seems that you can get <a
href="http://hackage.haskell.org/package/hermit-0.6.0.0/docs/HERMIT-Dictionary-Inline.html">inlining</a>,
<a
href="http://hackage.haskell.org/package/hermit-0.6.0.0/docs/HERMIT-Dictionary-Composite.html">general
reduction</a> and <a
href="http://hackage.haskell.org/package/hermit-0.6.0.0/docs/HERMIT-Dictionary-Local-Case.html">a
whole bunch of case rewrites</a> from this project. Check <a
href="http://ku-fpg.github.io/papers/Sculthorpe-14-KURE/">the KURE
paper</a> for the DSL used to do these rewrites, it looks pretty
aweeome. So if anyone’s thinking of working on this, I’d probably start
with reading <code>HERMIT.Shell</code> or <code>HERMIT.Plugin</code> and
see how to get it up and running. It’s a pity it has to work on Core,
that’s a little sad, but as far as trade-offs go it’s not too bad. Doing
proofs on things more complicated than core might be hard anyway. It
does mean you’ll probably want to make a rewrite that does a global
variable replacement: <code>x</code> and <code>y</code> is a little
easier to read than <code>x0_6</code> and the like that you get in
Core.</p>
<h2 id="catch-for-ghc">Catch for GHC</h2>
<p>Ideally, we would never have inexhaustive patterns in Haskell. But a
combination of an insufficient type system and people’s insistence on
using partial functions leads to a library ecosystem full of potential
landmines. <a href="http://community.haskell.org/~ndm/catch/">Catch</a>
is a project by Neil Mitchell which considers how a function is called
when determining whether its patterns are exhaustive or not. This lets
us use things like <code>head</code> and actually have a formal proof
that our use is correct, or a formal proof that our use, or someone
else’s use, will possibly crash.</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="fu">map</span> <span class="fu">head</span> <span class="op">.</span> <span class="fu">group</span></span></code></pre></div>
<p>This is an example which is always correct, because
<code>group</code> returns a list of non-empty lists.</p>
<p>Unfortunately, it currently works for a defunct Haskell compiler, but
apparently it can be ported to GHC Core with some work. I would very
much like for someone to do that. This is yet another project which is
the kind of thing people claim is possible thanks to Haskell’s unique
properties, but in practice it isn’t a standard thing, in the way that
QuickCheck is.</p>
<h2 id="a-substitution-stepper">A substitution stepper</h2>
<p>This is semi-related, but different, to the proof assistant. I would
like a program which can accept a Haskell module of source code and an
expression to evaluate in the context of that module and output the same
expression, as valid source code, with a single evaluation step
performed. This would be fantastic for writing new algorithms, for
understanding existing functions and algorithms, writing proofs, and
learning Haskell. There was something like this demonstrated in
Inventing on Principle. The opportunities for education and general
development practice are worth such a project.</p>
<p>Note: A debugger stepper is not the same thing.</p>
<p>Example:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="fu">foldr</span> (<span class="op">+</span>) <span class="dv">0</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>]</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="fu">foldr</span> (<span class="op">+</span>) <span class="dv">0</span> (<span class="dv">1</span> <span class="op">:</span> [<span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>])</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="dv">1</span> <span class="op">+</span> <span class="fu">foldr</span> (<span class="op">+</span>) <span class="dv">0</span> [<span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>]</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a><span class="dv">1</span> <span class="op">+</span> <span class="fu">foldr</span> (<span class="op">+</span>) <span class="dv">0</span> (<span class="dv">2</span> <span class="op">:</span> [<span class="dv">3</span>, <span class="dv">4</span>])</span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a><span class="dv">1</span> <span class="op">+</span> (<span class="dv">2</span> <span class="op">+</span> <span class="fu">foldr</span> (<span class="op">+</span>) <span class="dv">0</span> [<span class="dv">3</span>, <span class="dv">4</span>])</span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a><span class="dv">1</span> <span class="op">+</span> (<span class="dv">2</span> <span class="op">+</span> <span class="fu">foldr</span> (<span class="op">+</span>) <span class="dv">0</span> (<span class="dv">3</span> <span class="op">:</span> [<span class="dv">4</span>]))</span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a><span class="dv">1</span> <span class="op">+</span> (<span class="dv">2</span> <span class="op">+</span> (<span class="dv">3</span> <span class="op">+</span> <span class="fu">foldr</span> (<span class="op">+</span>) <span class="dv">0</span> [<span class="dv">4</span>]))</span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a><span class="dv">1</span> <span class="op">+</span> (<span class="dv">2</span> <span class="op">+</span> (<span class="dv">3</span> <span class="op">+</span> <span class="fu">foldr</span> (<span class="op">+</span>) <span class="dv">0</span> (<span class="dv">4</span> <span class="op">:</span> [])))</span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a><span class="dv">1</span> <span class="op">+</span> (<span class="dv">2</span> <span class="op">+</span> (<span class="dv">3</span> <span class="op">+</span> (<span class="dv">4</span> <span class="op">+</span> <span class="fu">foldr</span> (<span class="op">+</span>) <span class="dv">0</span> [])))</span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true" tabindex="-1"></a><span class="dv">1</span> <span class="op">+</span> (<span class="dv">2</span> <span class="op">+</span> (<span class="dv">3</span> <span class="op">+</span> (<span class="dv">4</span> <span class="op">+</span> <span class="dv">0</span>)))</span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true" tabindex="-1"></a><span class="dv">1</span> <span class="op">+</span> (<span class="dv">2</span> <span class="op">+</span> (<span class="dv">3</span> <span class="op">+</span> <span class="dv">4</span>))</span>
<span id="cb5-22"><a href="#cb5-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-23"><a href="#cb5-23" aria-hidden="true" tabindex="-1"></a><span class="dv">1</span> <span class="op">+</span> (<span class="dv">2</span> <span class="op">+</span> <span class="dv">7</span>)</span>
<span id="cb5-24"><a href="#cb5-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-25"><a href="#cb5-25" aria-hidden="true" tabindex="-1"></a><span class="dv">1</span> <span class="op">+</span> <span class="dv">9</span></span>
<span id="cb5-26"><a href="#cb5-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-27"><a href="#cb5-27" aria-hidden="true" tabindex="-1"></a><span class="dv">10</span></span></code></pre></div>
<p>Comparing this with foldl immediately shows the viewer how they
differ in structure:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="fu">foldl</span> (<span class="op">+</span>) <span class="dv">0</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>]</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="fu">foldl</span> (<span class="op">+</span>) <span class="dv">0</span> (<span class="dv">1</span> <span class="op">:</span> [<span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>])</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="fu">foldl</span> (<span class="op">+</span>) ((<span class="op">+</span>) <span class="dv">0</span> <span class="dv">1</span>) [<span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>]</span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a><span class="fu">foldl</span> (<span class="op">+</span>) ((<span class="op">+</span>) <span class="dv">0</span> <span class="dv">1</span>) (<span class="dv">2</span> <span class="op">:</span> [<span class="dv">3</span>, <span class="dv">4</span>])</span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a><span class="fu">foldl</span> (<span class="op">+</span>) ((<span class="op">+</span>) ((<span class="op">+</span>) <span class="dv">0</span> <span class="dv">1</span>) <span class="dv">2</span>) [<span class="dv">3</span>, <span class="dv">4</span>]</span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a><span class="fu">foldl</span> (<span class="op">+</span>) ((<span class="op">+</span>) ((<span class="op">+</span>) <span class="dv">0</span> <span class="dv">1</span>) <span class="dv">2</span>) (<span class="dv">3</span> <span class="op">:</span> [<span class="dv">4</span>])</span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a><span class="fu">foldl</span> (<span class="op">+</span>) ((<span class="op">+</span>) ((<span class="op">+</span>) ((<span class="op">+</span>) <span class="dv">0</span> <span class="dv">1</span>) <span class="dv">2</span>) <span class="dv">3</span>) [<span class="dv">4</span>]</span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a><span class="fu">foldl</span> (<span class="op">+</span>) ((<span class="op">+</span>) ((<span class="op">+</span>) ((<span class="op">+</span>) <span class="dv">0</span> <span class="dv">1</span>) <span class="dv">2</span>) <span class="dv">3</span>) (<span class="dv">4</span> <span class="op">:</span> [])</span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a><span class="fu">foldl</span> (<span class="op">+</span>) ((<span class="op">+</span>) ((<span class="op">+</span>) ((<span class="op">+</span>) ((<span class="op">+</span>) <span class="dv">0</span> <span class="dv">1</span>) <span class="dv">2</span>) <span class="dv">3</span>) <span class="dv">4</span>) []</span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a>(<span class="op">+</span>) ((<span class="op">+</span>) ((<span class="op">+</span>) ((<span class="op">+</span>) <span class="dv">0</span> <span class="dv">1</span>) <span class="dv">2</span>) <span class="dv">3</span>) <span class="dv">4</span></span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-21"><a href="#cb6-21" aria-hidden="true" tabindex="-1"></a><span class="dv">1</span> <span class="op">+</span> <span class="dv">2</span> <span class="op">+</span> <span class="dv">3</span> <span class="op">+</span> <span class="dv">4</span></span>
<span id="cb6-22"><a href="#cb6-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-23"><a href="#cb6-23" aria-hidden="true" tabindex="-1"></a><span class="dv">3</span> <span class="op">+</span> <span class="dv">3</span> <span class="op">+</span> <span class="dv">4</span></span>
<span id="cb6-24"><a href="#cb6-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-25"><a href="#cb6-25" aria-hidden="true" tabindex="-1"></a><span class="dv">6</span> <span class="op">+</span> <span class="dv">4</span></span>
<span id="cb6-26"><a href="#cb6-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-27"><a href="#cb6-27" aria-hidden="true" tabindex="-1"></a><span class="dv">10</span></span></code></pre></div>
<p>Each step in this is a valid Haskell program, and it’s just simple
substitution.</p>
<p>If the source for a function isn’t available, there are a couple
options for what to do:</p>
<ul>
<li>Have special-cases for things like <code>(+)</code>, as above.</li>
<li>Just perform no substitution for that function, it will still be a
legitimate program.</li>
</ul>
<p>It’s another project I could easily provide see-as-you-type support
for in Emacs, given an engine to query.</p>
<p>Again, this is just one more project which should just be a standard
thing Haskell can do. It’s a pure language. It’s used to teach
equational reasoning and following a simple lambda calculus substitution
model. But there is no such tool. Haskell is practically waving in our
faces with this opportunity.</p>
<p>Existing work in this area:</p>
<ul>
<li><a href="https://github.com/bmillwood/stepeval">stepeval</a> - a
prototype which nicely demonstrates the idea. It’s based on HSE and only
supports a tiny subset. There aren’t any plans to move this forward at
the moment. I’ll update the page if this changes.</li>
</ul>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2015-01-24 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sat, 24 Jan 2015 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Measuring duration in Haskell]]></title><link>https://chrisdone.com/posts/measuring-duration-in-haskell</link><guid>https://chrisdone.com/posts/measuring-duration-in-haskell</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Measuring duration in Haskell</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Measuring duration in Haskell</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Happy new year, everyone. It’s a new year and time for new
resolutions. Let’s talk about time. Specifically, measuring it in
Haskell.</p>
<h2 id="a-wrong-solution">A wrong solution</h2>
<p>How do you measure how long something takes in Haskell? Here’s a
naive attempt:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Exception</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Time</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>    start <span class="ot">&lt;-</span> getCurrentTime</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    evaluate (<span class="fu">sum</span> [<span class="dv">1</span> <span class="op">..</span> <span class="dv">1000000</span>])</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    end <span class="ot">&lt;-</span> getCurrentTime</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>    <span class="fu">print</span> (diffUTCTime end start)</span></code></pre></div>
<p>Running it, we see that it does what we expect:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> main</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="fl">0.316653</span>s</span></code></pre></div>
<h2 id="inaccurate-measuring">Inaccurate measuring</h2>
<p>Here’s what’s wrong with this implementation:</p>
<ul>
<li>The clock can be changed by the user at any moment.</li>
<li>Time synchronization services regularly update time.</li>
</ul>
<p>If you’re on an Ubuntu desktop, time is updated when you first boot
up from NTP servers. If you’re on a server, likely there is a daily cron
job to update your time, because you don’t tend to reboot servers. My
laptop has been on for 34 days:</p>
<pre><code>$ uptime
21:13:47 up 34 days,  2:06,  3 users,  load average: 0.74, 0.83, 0.84</code></pre>
<p>If I run a manual update, it adjusts my clock by 500
milliseconds:</p>
<pre><code>$ sudo ntpdate ntp.ubuntu.com
5 Jan 21:11:53 ntpdate[4805]: adjust time server x.x.x.x offset 0.517166 sec</code></pre>
<p>Because there is a certain amount of “drift” that occurs over
time.</p>
<p>Additionally, leap seconds can be introduced at any time and cannot
be predicated systematically, but there is at least a 6 months in
advance notice for time servers. In <a
href="http://hpiers.obspm.fr/iers/bul/bulc/bulletinc.dat">2015</a> there
will be an extra second added to time in-between the 30th of June to the
1st of July.</p>
<p>These factors mean that if our main function is run during an update,
the reported time could be completely wrong. For something simple like
the above, maybe it doesn’t matter. For long term logging and statistics
gathering, this would represent an anomaly. For a one-off, maybe it’s
forgivable, because it’s convenient. But above all, it’s simply
inaccurate reporting.</p>
<h2 id="accurate-measuring">Accurate measuring</h2>
<p>Readers familiar with this problem will think back to measuring time
in C; it requires inspecting the system clock and dividing by clocks per
second. In fact there are a couple solutions around that use this:</p>
<ul>
<li>The <a
href="http://hackage.haskell.org/package/timeit-1.0.0.0/docs/System-TimeIt.html">timeit</a>
package. This is good if your use-case is simple.</li>
<li>In turn, that package uses <a
href="http://hackage.haskell.org/package/base-4.7.0.2/docs/System-CPUTime.html">System.CPUTime</a>
from base, which is also handy.</li>
</ul>
<p>These are more reliable, because the time cannot be changed. But they
are limited, as both only measure CPU time and not IO time. So if your
program takes 10 seconds but only does 5 seconds of CPU processing and 5
seconds of waiting for the disk, then you will not have the real time.
Also known as <a
href="http://en.wikipedia.org/wiki/Wall-clock_time">wall time</a>.</p>
<p>In the Criterion package, there’s need for fine-grained, fast,
accurate measuring of both real and CPU time, so it includes its own
cross-platform implementations:</p>
<ul>
<li><a
href="https://github.com/bos/criterion/blob/master/Criterion/Measurement.hs#L54-60">Here
it does a measurement of times</a> using its internal API.</li>
<li>There is an <a
href="https://github.com/bos/criterion/blob/master/cbits/time-osx.c">OS
X</a>, <a
href="https://github.com/bos/criterion/blob/master/cbits/time-posix.c">POSIX</a>
and <a
href="https://github.com/bos/criterion/blob/master/cbits/time-windows.c">Windows</a>
C binding for each platform.</li>
</ul>
<p>That’s nice, but it’s embedded in a specific package built for
benchmarking, which we may not necessarily be doing. For example, I am
dabbling with a program to measure the speed of my key presses. It turns
out there is a package that does similarly to Criterion, already
prepared and similarly cross-platform and only depends on base and
ghc-prim.</p>
<h2 id="the-clock-package">The clock package</h2>
<p>I discovered this really nice package called <a
href="http://hackage.haskell.org/package/clock-0.4.1.3">clock</a> which
has <a
href="http://hackage.haskell.org/package/clock-0.4.1.3/docs/System-Clock.html">the
option for several time measurements</a>:</p>
<ul>
<li><code>Monotonic</code>: a monotonic but not-absolute time which
never changes after start-up.</li>
<li><code>Realtime</code>: an absolute Epoch-based time (which is the
system clock and can change).</li>
<li><code>ProcessCPUTime</code>: CPU time taken by the process.</li>
<li><code>ThreadCPUTime</code>: CPU time taken by the thread.</li>
</ul>
<p>Let’s rewrite our example using this package and the formatting
package (which provides a handy <code>TimeSpec</code> formatter as of
6.1):</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE OverloadedStrings #-}</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Exception</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Formatting</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Formatting.Clock</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">System.Clock</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">do</span> start <span class="ot">&lt;-</span> getTime <span class="dt">Monotonic</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>     evaluate (<span class="fu">sum</span> [<span class="dv">1</span> <span class="op">..</span> <span class="dv">1000000</span>])</span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>     end <span class="ot">&lt;-</span> getTime <span class="dt">Monotonic</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>     fprint (timeSpecs <span class="op">%</span> <span class="st">&quot;\n&quot;</span>) start end</span></code></pre></div>
<p>Running it, we see we get similar information as above, but now it’s
accurate.</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> main</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="fl">276.05</span> ms</span></code></pre></div>
<p>If you just want CPU time for the process, or the OS thread, just
provide a different argument to <code>getTime</code>.</p>
<h2 id="summary">Summary</h2>
<p>So next time you want to measure how long something takes, unless
you’re doing benchmarking, check out the <code>clock</code> package!</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2015-01-05 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Mon, 05 Jan 2015 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Lucid 2.0: clearer than before]]></title><link>https://chrisdone.com/posts/lucid2</link><guid>https://chrisdone.com/posts/lucid2</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Lucid 2.0: clearer than before</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Lucid 2.0: clearer than before</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Since <a href="http://chrisdone.com/posts/lucid">my last post</a>
about Lucid, I’ve <a
href="http://hackage.haskell.org/package/lucid">updated Lucid to major
version 2.0</a> in a way that removes the need for the <code>with</code>
combinator. Now, you can just write:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>term_ <span class="op">&lt;</span>children<span class="op">&gt;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>term_ [<span class="op">&lt;</span>props<span class="op">&gt;</span>] <span class="op">&lt;</span>children<span class="op">&gt;</span></span></code></pre></div>
<p>Example:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ot">page ::</span> <span class="dt">Html</span> ()</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>page <span class="ot">=</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>  html_</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    (<span class="kw">do</span> head_</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>          (<span class="kw">do</span> title_ <span class="st">&quot;Introduction page.&quot;</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>              link_ [rel_ <span class="st">&quot;stylesheet&quot;</span>,type_ <span class="st">&quot;text/css&quot;</span>,href_ <span class="st">&quot;screen.css&quot;</span>]</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>              style_ <span class="st">&quot;body{background:red}&quot;</span>)</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>        body_</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>          (<span class="kw">do</span> div_ [id_ <span class="st">&quot;header&quot;</span>,style_ <span class="st">&quot;color:white&quot;</span>] <span class="st">&quot;Syntax&quot;</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>              p_ (span_ (strong_ <span class="st">&quot;This is an example of Lucid syntax.&quot;</span>))</span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>              hr_ []</span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>              ul_ (<span class="fu">mapM_</span> (li_ <span class="op">.</span> toHtml <span class="op">.</span> <span class="fu">show</span>)</span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>                         [<span class="dv">1</span>,<span class="dv">2</span>,<span class="dv">3</span>])</span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>              table_ (tr_ (<span class="kw">do</span> td_ <span class="st">&quot;Hello!&quot;</span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>                              td_ [class_ <span class="st">&quot;alt&quot;</span>] <span class="st">&quot;World!&quot;</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>                              td_ <span class="st">&quot;Sup?&quot;</span>))))</span></code></pre></div>
<p>Here’s the (pretty printed) output:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode html"><code class="sourceCode html"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>λ&gt; page</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="dt">&lt;!DOCTYPE </span>html<span class="dt">&gt;</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="kw">&lt;html&gt;</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="kw">&lt;head&gt;</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">&lt;title&gt;</span>Introduction page.<span class="kw">&lt;/title&gt;</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">&lt;link</span> <span class="er">href</span><span class="ot">=</span><span class="st">&quot;screen.css&quot;</span> <span class="er">rel</span><span class="ot">=</span><span class="st">&quot;stylesheet&quot;</span> <span class="er">type</span><span class="ot">=</span><span class="st">&quot;text/css&quot;</span><span class="kw">&gt;</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">&lt;style&gt;</span>body{<span class="kw">background</span>:<span class="cn">red</span>}<span class="kw">&lt;/style&gt;</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a><span class="kw">&lt;/head&gt;</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a><span class="kw">&lt;body&gt;</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">&lt;div</span> <span class="er">id</span><span class="ot">=</span><span class="st">&quot;header&quot;</span> <span class="er">style</span><span class="ot">=</span><span class="st">&quot;color:white&quot;</span><span class="kw">&gt;</span>Syntax<span class="kw">&lt;/div&gt;</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">&lt;p&gt;&lt;span&gt;&lt;strong&gt;</span>This is an example of Lucid syntax.<span class="kw">&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">&lt;hr&gt;</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">&lt;ul&gt;</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>        <span class="kw">&lt;li&gt;</span>1<span class="kw">&lt;/li&gt;</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>        <span class="kw">&lt;li&gt;</span>2<span class="kw">&lt;/li&gt;</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>        <span class="kw">&lt;li&gt;</span>3<span class="kw">&lt;/li&gt;</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a>    <span class="kw">&lt;/ul&gt;</span></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a>    <span class="kw">&lt;table&gt;</span></span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true" tabindex="-1"></a>        <span class="kw">&lt;tr&gt;</span></span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true" tabindex="-1"></a>            <span class="kw">&lt;td&gt;</span>Hello!<span class="kw">&lt;/td&gt;</span></span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true" tabindex="-1"></a>            <span class="kw">&lt;td</span> <span class="er">class</span><span class="ot">=</span><span class="st">&quot;alt&quot;</span><span class="kw">&gt;</span>World!<span class="kw">&lt;/td&gt;</span></span>
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true" tabindex="-1"></a>            <span class="kw">&lt;td&gt;</span>Sup?<span class="kw">&lt;/td&gt;</span></span>
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true" tabindex="-1"></a>        <span class="kw">&lt;/tr&gt;</span></span>
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true" tabindex="-1"></a>    <span class="kw">&lt;/table&gt;</span></span>
<span id="cb3-25"><a href="#cb3-25" aria-hidden="true" tabindex="-1"></a><span class="kw">&lt;/body&gt;</span></span>
<span id="cb3-26"><a href="#cb3-26" aria-hidden="true" tabindex="-1"></a><span class="kw">&lt;/html&gt;</span></span></code></pre></div>
<h2 id="overloaded">Overloaded</h2>
<p>Element terms are now typed like this:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ot">p_ ::</span> <span class="dt">Term</span> arg result <span class="ot">=&gt;</span> arg <span class="ot">-&gt;</span> result</span></code></pre></div>
<p>Giving a couple overloaded instances:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ot">p_ ::</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> [<span class="dt">Attribute</span>] <span class="ot">-&gt;</span> <span class="dt">HtmlT</span> m () <span class="ot">-&gt;</span> <span class="dt">HtmlT</span> m ()</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="ot">p_ ::</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> <span class="dt">HtmlT</span> m () <span class="ot">-&gt;</span> <span class="dt">HtmlT</span> m ()</span></code></pre></div>
<p>This is similar to the variadic <code>printf</code> from
<code>Text.Printf</code>, but limited to one level of variance.</p>
<h1 id="retaining-old-invariants">Retaining old invariants</h1>
<p>In <a href="http://chrisdone.com/posts/lucid">my last post I
listed</a> a bunch of factors that Lucid should solve, I worked hard to
make sure these were met in this change.</p>
<h2 id="preserving-liberal-term-use">Preserving liberal term use</h2>
<p>You can still use <code>style_</code> or <code>title_</code> as an
element or an attribute:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> style_ [style_ <span class="st">&quot;inception&quot;</span>] <span class="st">&quot;Go deeper.&quot;</span><span class="ot"> ::</span> <span class="dt">Html</span> ()</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>style style<span class="ot">=</span><span class="st">&quot;inception&quot;</span><span class="op">&gt;</span><span class="dt">Go</span> deeper<span class="op">.&lt;/</span>style<span class="op">&gt;</span></span></code></pre></div>
<h2 id="preserving-encoding-properties">Preserving encoding
properties</h2>
<p>The <code>script_</code> and <code>style_</code> elements still
output unencoded:</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> script_ <span class="st">&quot;alert(&#39;Hello!&#39; &gt; 12)&quot;</span><span class="ot"> ::</span> <span class="dt">Html</span> ()</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>script<span class="op">&gt;</span>alert(<span class="dt">&#39;Hello</span><span class="op">!</span>&#39; <span class="op">&gt;</span> <span class="dv">12</span>)<span class="op">&lt;/</span>script<span class="op">&gt;</span></span></code></pre></div>
<h2 id="with-is-still-available">With is still available</h2>
<p>You can still add attributes to elements using <code>with</code>:</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> p_ [id_ <span class="st">&quot;foo&quot;</span>] <span class="st">&quot;&quot;</span><span class="ot"> ::</span> <span class="dt">Html</span> ()</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>p <span class="fu">id</span><span class="ot">=</span><span class="st">&quot;foo&quot;</span><span class="op">&gt;&lt;/</span>p<span class="op">&gt;</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> with (p_ [id_ <span class="st">&quot;foo&quot;</span>]) [class_ <span class="st">&quot;red&quot;</span>] <span class="st">&quot;yo&quot;</span><span class="ot"> ::</span> <span class="dt">Html</span> ()</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>p <span class="fu">id</span><span class="ot">=</span><span class="st">&quot;foo&quot;</span> <span class="kw">class</span><span class="ot">=</span><span class="st">&quot;red&quot;</span><span class="op">&gt;</span>yo<span class="op">&lt;/</span>p<span class="op">&gt;</span></span></code></pre></div>
<h2 id="convenient-construction-of-custom-elements">Convenient
construction of custom elements</h2>
<p>You can construct custom elements if needed:</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> with (term <span class="st">&quot;potato&quot;</span> [id_ <span class="st">&quot;foo&quot;</span>]) [class_ <span class="st">&quot;red&quot;</span>] <span class="st">&quot;yo&quot;</span><span class="ot"> ::</span> <span class="dt">Html</span> ()</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>potato <span class="fu">id</span><span class="ot">=</span><span class="st">&quot;foo&quot;</span> <span class="kw">class</span><span class="ot">=</span><span class="st">&quot;red&quot;</span><span class="op">&gt;</span>yo<span class="op">&lt;/</span>potato<span class="op">&gt;</span></span></code></pre></div>
<p>But you can also construct normal elements with a custom class, so
that you don’t have to use <code>with</code> for extending elements like
our old <code>container_</code> example, you can construct an element
with some given attributes:</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="kw">let</span> container_ <span class="ot">=</span> termWith <span class="st">&quot;div&quot;</span> [class_ <span class="st">&quot; container &quot;</span>]</span></code></pre></div>
<p>And then use it later like a normal element:</p>
<div class="sourceCode" id="cb11"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> container_ [class_ <span class="st">&quot;main&quot;</span>] <span class="st">&quot;OK, go!&quot;</span><span class="ot"> ::</span> <span class="dt">Html</span> ()</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span><span class="fu">div</span> <span class="kw">class</span><span class="ot">=</span><span class="st">&quot; container main&quot;</span><span class="op">&gt;</span><span class="dt">OK</span>, go<span class="op">!&lt;/</span><span class="fu">div</span><span class="op">&gt;</span></span></code></pre></div>
<p>Some basic Bootstrap terms are available in <a
href="http://hackage.haskell.org/package/lucid-2.1/docs/Lucid-Bootstrap.html">Lucid.Bootstrap</a>.</p>
<h2 id="still-a-monad-transformer">Still a monad transformer</h2>
<p>I didn’t change anything about the monad itself. Just the
combinators. So you can still use it as a transformer:</p>
<div class="sourceCode" id="cb12"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> runReader (renderTextT (html_ (body_ (<span class="kw">do</span> name <span class="ot">&lt;-</span> lift ask</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>                                            p_ [class_ <span class="st">&quot;name&quot;</span>] (toHtml name)))))</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>             (<span class="st">&quot;Chris&quot;</span><span class="ot"> ::</span> <span class="dt">String</span>)</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;&lt;html&gt;&lt;body&gt;&lt;p class=\&quot;name\&quot;&gt;Chris&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;&quot;</span></span></code></pre></div>
<h2 id="small-trade-off">Small trade-off</h2>
<p>One small difference is that elements that take no children always
take arguments:</p>
<div class="sourceCode" id="cb13"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- | @input@ element</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="ot">input_ ::</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> [<span class="dt">Attribute</span>] <span class="ot">-&gt;</span> <span class="dt">HtmlT</span> m ()</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>input_ <span class="ot">=</span> with (makeElementNoEnd <span class="st">&quot;input&quot;</span>)</span></code></pre></div>
<p>So you will always write:</p>
<div class="sourceCode" id="cb14"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a>input_ [<span class="op">&lt;</span>something<span class="op">&gt;</span>]</span></code></pre></div>
<p>But in practice it seems that elements with no children almost always
take a number of attributes. Exceptions to that rule are
<code>br_</code> and <code>hr_</code>, but those are quite rare. So this
is a very happy trade-off, I feel. (See the ‘real examples’ at the end
of this post.)</p>
<p>Extending elements like this is straight-forward using our usual
<code>with</code> combinator. Example, suppose you’re sick of writing
the classic <code>input type="text"</code>, you can define a combinator
like this:</p>
<div class="sourceCode" id="cb15"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="ot">text_ ::</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> [<span class="dt">Attribute</span>] <span class="ot">-&gt;</span> <span class="dt">HtmlT</span> m ()</span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>text_ <span class="ot">=</span> with (with (makeElementNoEnd <span class="st">&quot;input&quot;</span>) [type_ <span class="st">&quot;text&quot;</span>])</span></code></pre></div>
<p>And now you can write:</p>
<div class="sourceCode" id="cb16"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> text_ []</span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>input <span class="kw">type</span><span class="ot">=</span><span class="st">&quot;text&quot;</span><span class="op">&gt;</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> text_ [class_ <span class="st">&quot;foo&quot;</span>]</span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>input <span class="kw">type</span><span class="ot">=</span><span class="st">&quot;text&quot;</span> <span class="kw">class</span><span class="ot">=</span><span class="st">&quot;foo&quot;</span><span class="op">&gt;</span></span></code></pre></div>
<h2 id="larger-trade-off">Larger trade-off</h2>
<p>Due to the overloadedness, similar to the overloaded strings
example:</p>
<div class="sourceCode" id="cb17"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="st">&quot;foo &gt; bar&quot;</span><span class="ot"> ::</span> <span class="dt">Html</span> ()</span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>foo <span class="op">&amp;</span>gt; bar</span></code></pre></div>
<p>You have to use a type annotation in GHCi:</p>
<div class="sourceCode" id="cb18"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> p_ <span class="st">&quot;foo&quot;</span><span class="ot"> ::</span> <span class="dt">Html</span> ()</span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>p<span class="op">&gt;</span>foo<span class="op">&lt;/</span>p<span class="op">&gt;</span></span></code></pre></div>
<p>Otherwise you get</p>
<blockquote>
<p>No instance for <code>(Term arg0 a0)</code> arising from a use of
<code>it</code></p>
</blockquote>
<p>Most Haskellers won’t care about this case, but for GHCi users it’s a
slight regression. Also, in some local where declarations, you might
need a type signature. For example, the following is OK:</p>
<div class="sourceCode" id="cb19"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="ot">people ::</span> <span class="dt">Html</span> ()</span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>people <span class="ot">=</span> ul_ (<span class="fu">mapM_</span> person [<span class="st">&quot;Mary Smith&quot;</span>,<span class="st">&quot;Dave Jones&quot;</span>])</span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">where</span> person name <span class="ot">=</span> li_ name</span></code></pre></div>
<p>Whereas in this case:</p>
<div class="sourceCode" id="cb20"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="ot">bigTable ::</span> [[<span class="dt">Int</span>]] <span class="ot">-&gt;</span> <span class="dt">Html</span> ()</span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>bigTable t <span class="ot">=</span> table_ (<span class="fu">mapM_</span> row t)</span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">where</span> row r <span class="ot">=</span> tr_ (<span class="fu">mapM_</span> (td_ <span class="op">.</span> toHtml <span class="op">.</span> <span class="fu">show</span>) r)</span></code></pre></div>
<p>It’s a little harder for GHC to infer this, so you add a
type-signature:</p>
<div class="sourceCode" id="cb21"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="ot">bigTable ::</span> [[<span class="dt">Int</span>]] <span class="ot">-&gt;</span> <span class="dt">Html</span> ()</span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>bigTable t <span class="ot">=</span> table_ (<span class="fu">mapM_</span> row t)</span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">where</span><span class="ot"> row ::</span> [<span class="dt">Int</span>] <span class="ot">-&gt;</span> <span class="dt">Html</span> ()</span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a>        row r <span class="ot">=</span> tr_ (<span class="fu">mapM_</span> (td_ <span class="op">.</span> toHtml <span class="op">.</span> <span class="fu">show</span>) r)</span></code></pre></div>
<p>Not a big deal given the benefits, but something to be aware of.</p>
<h2 id="summary">Summary</h2>
<p>In total, I’ve made this library almost perfect for my own tastes.
It’s concise, easy to read and edit (and auto-format), it lacks
namespace issues, it’s easy to make re-usable terms, and it’s fast
enough. The need for the <code>with</code> combinator was the only wart
that naggled me over the past week, I knew I’d end up making some
change. I’ve also covered the trade-offs that come with this design
decision.</p>
<p>As far as I’m concerned, Lucid can rest at major version
<code>2.*</code> for a long time now. I added some newfangled HTML5
elements (who knew <code>main</code> was now an element?) and <a
href="https://github.com/chrisdone/lucid/blob/master/test/Main.hs">a
test suite</a>. You can expect the only minor version bumps henceforth
to be bugfixes, regression tests, and more documentation.</p>
<p>For some real examples:</p>
<ul>
<li><a
href="https://github.com/chrisdone/tryhaskell/blob/d8b59e71d46cb890935f5c0c6c1d723cc9f78d99/src/TryHaskell.hs#L326-L419">Try
Haskell</a> is now using Lucid.</li>
<li>As is the upcoming <a
href="https://github.com/haskell-infra/hl/blob/master/src/HL/V/Template.hs#L37-171">Haskell
homepage</a>.</li>
<li>And <a
href="https://github.com/relrod/isysuclosed.com/blob/haskell/Main.hs#L34">isysuclosed.com</a>.</li>
</ul>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2014-11-20 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Thu, 20 Nov 2014 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Lucid: templating DSL for HTML]]></title><link>https://chrisdone.com/posts/lucid</link><guid>https://chrisdone.com/posts/lucid</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Lucid: templating DSL for HTML</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Lucid: templating DSL for HTML</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>I’m not big on custom templating languages, for reasons I’ll write
about another time. I prefer EDSLs. I preferred the <a
href="http://hackage.haskell.org/package/xhtml">xhtml</a> package back
when that was what everybody used. It looked like this:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>header <span class="op">&lt;&lt;</span> thetitle <span class="op">&lt;&lt;</span> <span class="st">&quot;Page title&quot;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>thediv noHtml <span class="op">!</span> [theclass <span class="st">&quot;logo&quot;</span>] <span class="op">&lt;&lt;</span> <span class="st">&quot;…&quot;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>thediv noHtml <span class="op">!</span> [identifier <span class="st">&quot;login&quot;</span>]</span></code></pre></div>
<p>Pretty line-noisy to read, write and hard to edit in a reasonable
manner.</p>
<p>Later, <a
href="http://hackage.haskell.org/package/blaze-html">blaze-html</a>
became the new goto HTML writing library. It improved upon the XHTML
package by being faster and having a convenient monad instance. It looks
like this:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>page1 <span class="ot">=</span> html <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    <span class="fu">head</span> <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>        title <span class="st">&quot;Introduction page.&quot;</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>        link <span class="op">!</span> rel <span class="st">&quot;stylesheet&quot;</span> <span class="op">!</span> type_ <span class="st">&quot;text/css&quot;</span> <span class="op">!</span> href <span class="st">&quot;screen.css&quot;</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>    body <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>        <span class="fu">div</span> <span class="op">!</span> <span class="fu">id</span> <span class="st">&quot;header&quot;</span> <span class="op">$</span> <span class="st">&quot;Syntax&quot;</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>        p <span class="st">&quot;This is an example of BlazeMarkup syntax.&quot;</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>        ul <span class="op">$</span> <span class="fu">mapM_</span> (li <span class="op">.</span> toMarkup <span class="op">.</span> <span class="fu">show</span>) [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>]</span></code></pre></div>
<p>Much easier to read, write and edit thanks to the monad instance.</p>
<p>However, after several years of using that, I’ve come to write my
own. I’ll cover the infelicities about Blaze and then discuss my
alternative approach.</p>
<p>Reading back through what I’ve written below, it could be read as a
bit attacky, and some of the issues are less philosophical and more
incidental. I think of it more that the work on writing HTML in a DSL is
incomplete and to some degree people somewhat gave up on doing it more
conveniently at some point. So I’m re-igniting that.</p>
<p>The combination of having a need to write a few HTML reports and
recent discussions about Blaze made me realise it was time for me to
come at this problem a-fresh with my own tastes in mind. I also haven’t
used my own approach much, other than porting some trivial apps to
it.</p>
<h1 id="blaze">Blaze</h1>
<h2 id="names-that-conflict-with-base">Names that conflict with
base</h2>
<p>The first problem is that Blaze exports many names which conflict
with base. Examples:</p>
<p><code>div</code>, <code>id</code>, <code>head</code>,
<code>map</code></p>
<p>The obvious problem with this is that you either have to qualify any
use of those names, which means you have to qualify Blaze, and end up
with something inconsistent like this:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>H.div <span class="op">!</span> A.id <span class="st">&quot;logo&quot;</span> <span class="op">$</span> <span class="st">&quot;…&quot;</span></span></code></pre></div>
<p>Where <code>H</code> and <code>A</code> come from importing the
element and attribute modules like this:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Text.Blaze.Html5</span>            <span class="kw">as</span> <span class="dt">H</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Text.Blaze.Html5.Attributes</span> <span class="kw">as</span> <span class="dt">A</span></span></code></pre></div>
<p>Or you don’t import <code>Prelude</code> and only import Blaze, but
then you can’t do a simple <code>map</code> without qualification.</p>
<p>You might’ve noticed in the old <code>xhtml</code> package that
<code>thediv</code> and <code>identifier</code> are used instead. The
problem with using different names from the actual things they refer to
is that they’re hard to learn and remember, both for regular Haskellers
and newbies coming to edit your templates.</p>
<h2 id="names-that-are-keywords">Names that are keywords</h2>
<p>This is a common problem in DSLs, too. In Blaze the problem is:
<code>class</code> or <code>type</code> (perhaps others I don’t recall).
Blaze solves it with: <code>class_</code> or <code>type_</code></p>
<p>Again, the problem with this is that it is inconsistent with the
other naming conventions. It’s another exception to the rule that you
have to remember and makes the code look bad.</p>
<h2 id="conflicting-attribute-and-element-names">Conflicting attribute
and element names</h2>
<p>There are also names which are used for both attributes and elements.
Examples are <code>style</code> and <code>map</code>. That means you
can’t write:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>H.head <span class="op">$</span> style <span class="st">&quot;body { background: red; }&quot;</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>body <span class="op">$</span> p <span class="op">!</span> style <span class="st">&quot;foo&quot;</span> <span class="op">$</span> …</span></code></pre></div>
<p>You end up writing:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>H.head <span class="op">$</span> H.style <span class="st">&quot;body { background: red; }&quot;</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>body <span class="op">$</span> p <span class="op">!</span> A.style <span class="st">&quot;foo&quot;</span> <span class="op">$</span> …</span></code></pre></div>
<h2 id="inconsistency-is-difficult-and-ugly">Inconsistency is difficult
and ugly</h2>
<p>What the above problems amount to is ending up with code like
this:</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>body <span class="op">$</span> H.div <span class="op">!</span> A.id <span class="st">&quot;logo&quot;</span> <span class="op">!</span> class_ <span class="st">&quot;left&quot;</span> <span class="op">!</span> hidden <span class="op">$</span> <span class="st">&quot;Content&quot;</span></span></code></pre></div>
<p>At this point users of Blaze give up with second-guessing every
markup term they write and decide it’s more consistent to qualify
<em>everything</em>:</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>H.body <span class="op">$</span> H.div <span class="op">!</span> A.id <span class="st">&quot;logo&quot;</span> <span class="op">!</span> A.class_ <span class="st">&quot;left&quot;</span> <span class="op">!</span> A.hidden <span class="op">$</span> <span class="st">&quot;Content&quot;</span></span></code></pre></div>
<p>Or, taken from some real code online:</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>H.input <span class="op">H.!</span> A.type_ <span class="st">&quot;checkbox&quot;</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>        <span class="op">H.!</span> A.checked <span class="dt">True</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>        <span class="op">H.!</span> A.readonly <span class="st">&quot;true&quot;</span></span></code></pre></div>
<p>This ends up being too much. Inconvenient to type, ugly to read, and
one more step removed from the HTML we’re supposed to be generating.</p>
<h2 id="the-monad-instance-isnt">The Monad instance isn’t</h2>
<p>The monad instance was originally conceived as a handy way to write
HTML nicely without having to use <code>&lt;&gt;</code> or lists of
lists and other less wieldy syntax.</p>
<p>In the end the monad ended up being defined like this:</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Monad</span> <span class="dt">MarkupM</span> <span class="kw">where</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>  <span class="fu">return</span> _ <span class="ot">=</span> <span class="dt">Empty</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>  <span class="ot">{-# INLINE return #-}</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>  (<span class="op">&gt;&gt;</span>) <span class="ot">=</span> <span class="dt">Append</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>  <span class="ot">{-# INLINE (&gt;&gt;) #-}</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>  h1 <span class="op">&gt;&gt;=</span> f <span class="ot">=</span> h1 <span class="op">&gt;&gt;</span> f</span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>      (<span class="fu">error</span> <span class="st">&quot;Text.Blaze.Internal.MarkupM: invalid use of monadic bind&quot;</span>)</span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>  <span class="ot">{-# INLINE (&gt;&gt;=) #-}</span></span></code></pre></div>
<p>And has been for some years. Let’s take a trivial example of why this
is not good. You render some HTML and while doing so build a result to
be used later:</p>
<div class="sourceCode" id="cb11"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">do</span> xs <span class="ot">&lt;-</span> foldM (\c i <span class="ot">-&gt;</span> …)</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>               <span class="fu">mempty</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>               ys</span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>   <span class="fu">mapM_</span> dd xs</span></code></pre></div>
<p>Uh-oh:</p>
<pre><code>*** Exception: Text.Blaze.Internal.MarkupM: invalid use of monadic bind</code></pre>
<h2 id="the-overloaded-strings-instance-is-bad">The overloaded strings
instance is bad</h2>
<p>The previous point leads onto this next point, which is that due to
this phantomesque monad type, the instance is like this:</p>
<div class="sourceCode" id="cb13"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">IsString</span> (<span class="dt">MarkupM</span> a) <span class="kw">where</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>    fromString <span class="ot">=</span> <span class="dt">Content</span> <span class="op">.</span> fromString</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>    <span class="ot">{-# INLINE fromString #-}</span></span></code></pre></div>
<p>How can it make this value? It cannot. If you want to go ahead and
extract that `a’, you get:</p>
<pre><code>*** Exception: Text.Blaze.Internal.MarkupM: invalid use of monadic bind</code></pre>
<p>Additionally, this instance is too liberal. You end up getting this
warning:</p>
<blockquote>
<p>A do-notation statement discarded a result of type
<code>GHC.Prim.Any</code></p>
<p>Suppress this warning by saying <code>_ &lt;- "Example"</code> or by
using the flag <code>-fno-warn-unused-do-bind</code></p>
</blockquote>
<p>So you end up having to write in practice (again, taken from a real
Blaze codebase by one of the authors):</p>
<pre><code>void &quot;Hello!&quot;</code></pre>
<p>Which pretty much negates the point of using <code>IsString</code> in
the first-place. Alternatively, you use
<code>-fno-warn-unused-do-bind</code> in your module.</p>
<h2 id="working-with-attributes-is-awkward">Working with attributes is
awkward</h2>
<p>The ! syntax seems pretty convenient from superficial inspection:</p>
<div class="sourceCode" id="cb16"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a>link <span class="op">!</span> rel <span class="st">&quot;stylesheet&quot;</span> <span class="op">!</span> type_ <span class="st">&quot;text/css&quot;</span> <span class="op">!</span> href <span class="st">&quot;screen.css&quot;</span></span></code></pre></div>
<p>But in practice it means you always have the same combination:</p>
<div class="sourceCode" id="cb17"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="fu">div</span> <span class="op">!</span> H.class_ <span class="st">&quot;logo&quot;</span> <span class="op">$</span> <span class="st">&quot;…&quot;</span></span></code></pre></div>
<p>Which I find—personally speaking—a bit distasteful to read, it’s not
far from what we saw in the old xhtml package:</p>
<div class="sourceCode" id="cb18"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a>thediv <span class="op">!</span> [theclass <span class="st">&quot;logo&quot;</span>] <span class="op">&lt;&lt;</span> <span class="st">&quot;…&quot;</span></span></code></pre></div>
<p>Did we really save that much in the attribute department? Operators
are evil.</p>
<p>But mostly presents an editing challenge. Operators like this make it
tricky to navigate, format in a regular way and do code transformations
on. All Haskell code has operators, so this is a general problem. But if
your DSL doesn’t actually need these operators, I consider this a
smell.</p>
<h2 id="attributes-dont-compose">Attributes don’t compose</h2>
<p>You should be able to compose <code>with</code>. For example, let’s
say you want to define a re-usable component with bootstrap:</p>
<div class="sourceCode" id="cb19"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a>container inner <span class="ot">=</span> <span class="fu">div</span> <span class="op">!</span> class_ <span class="st">&quot;container&quot;</span> <span class="op">$</span> inner</span></code></pre></div>
<p>Now you can use it to make a container. But consider now that you
also want to add additional attributes to it later. You can do that with
another call to with:</p>
<div class="sourceCode" id="cb20"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a>container <span class="op">!</span> class_ <span class="st">&quot;main&quot;</span> <span class="op">$</span> <span class="st">&quot;zot&quot;</span></span></code></pre></div>
<p>In Blaze this produces:</p>
<div class="sourceCode" id="cb21"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> main</span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;&lt;div class=\&quot;container\&quot; class=\&quot;main\&quot;&gt;My content!&lt;/div&gt;&quot;</span></span></code></pre></div>
<p>Browsers ignore the latter main, so the composition didn’t work.</p>
<h2 id="ceremony-is-tiring">Ceremony is tiring</h2>
<p>Here’s the example from Blaze’s package, that’s introduced to
users.</p>
<div class="sourceCode" id="cb22"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Prelude</span> <span class="kw">hiding</span> (head, id, div)</span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Text.Blaze.Html4.Strict</span> <span class="kw">hiding</span> (map)</span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Text.Blaze.Html4.Strict.Attributes</span> <span class="kw">hiding</span> (title)</span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Text.Blaze.Renderer.Utf8</span> (renderMarkup)</span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a><span class="ot">page1 ::</span> <span class="dt">Markup</span></span>
<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a>page1 <span class="ot">=</span> html <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a>    <span class="fu">head</span> <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a>        title <span class="st">&quot;Introduction page.&quot;</span></span>
<span id="cb22-10"><a href="#cb22-10" aria-hidden="true" tabindex="-1"></a>        link <span class="op">!</span> rel <span class="st">&quot;stylesheet&quot;</span> <span class="op">!</span> type_ <span class="st">&quot;text/css&quot;</span> <span class="op">!</span> href <span class="st">&quot;screen.css&quot;</span></span>
<span id="cb22-11"><a href="#cb22-11" aria-hidden="true" tabindex="-1"></a>    body <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb22-12"><a href="#cb22-12" aria-hidden="true" tabindex="-1"></a>        <span class="fu">div</span> <span class="op">!</span> <span class="fu">id</span> <span class="st">&quot;header&quot;</span> <span class="op">$</span> <span class="st">&quot;Syntax&quot;</span></span>
<span id="cb22-13"><a href="#cb22-13" aria-hidden="true" tabindex="-1"></a>        p <span class="st">&quot;This is an example of BlazeMarkup syntax.&quot;</span></span>
<span id="cb22-14"><a href="#cb22-14" aria-hidden="true" tabindex="-1"></a>        ul <span class="op">$</span> <span class="fu">mapM_</span> (li <span class="op">.</span> toMarkup <span class="op">.</span> <span class="fu">show</span>) [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>]</span>
<span id="cb22-15"><a href="#cb22-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-16"><a href="#cb22-16" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="fu">print</span> (renderMarkup page1)</span></code></pre></div>
<p>Apart from the import backflips you have to do to resolve names
properly, you have at least three imports to make just to render some
HTML. Call me lazy, or stupid, but I never remember this deep hierarchy
of modules and always have to look it up every single time. And I’ve
been using Blaze for as long as the authors have.</p>
<h2 id="transforming">Transforming</h2>
<p>A smaller complaint is that it would sometimes be nice to transform
over another monad. Simplest example is storing the read-only model
information in a reader monad and then you don’t have to pass around a
bunch of things as arguments to all your view functions. I’m a big fan
of function arguments for explicit state, but not so much if it’s the
same argument every time.</p>
<h2 id="no-show-instance">No Show instance</h2>
<p>It would be nice if you could just write some markup in the REPL
without having to import some other modules and wrap it all in a
function just to see it.</p>
<h1 id="lucid">Lucid</h1>
<p>My new library, Lucid, attempts to solve most of these problems.</p>
<h2 id="naming-issues">Naming issues</h2>
<p>Firstly, <em>all</em> names which are representations of HTML terms
are suffixed with an underscore <code>_</code>:</p>
<pre><code>p_, class_, table_, style_</code></pre>
<p>No ifs or buts. <em>All markup terms.</em></p>
<p>That solves the following problems (from the issues described
above):</p>
<ul>
<li>Names that conflict with base: <code>div_</code>, <code>id_</code>,
<code>head_</code>, <code>map_</code>, etc.</li>
<li>Names that are keywords: <code>class_</code>, <code>type_</code>,
etc.</li>
<li>Conflicting attribute and element names: solved by abstracting those
names via a class. You can write <code>style_</code> to mean either the
element name or the attribute name.</li>
<li>Inconsistency is difficult and ugly: there’s no inconsistency, all
names are the same format.</li>
</ul>
<p>No import problems or qualification. Just write code without worrying
about it.</p>
<h2 id="how-it-looks">How it looks</h2>
<p>Plain text is written using the <code>OverloadedStrings</code> and
<code>ExtendedDefaultRules</code> extensions, and is automatically
escaped:</p>
<div class="sourceCode" id="cb24"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="st">&quot;123 &lt; 456&quot;</span><span class="ot"> ::</span> <span class="dt">Html</span> ()</span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a><span class="dv">123</span> <span class="op">&amp;</span>lt; <span class="dv">456</span></span></code></pre></div>
<p>Elements nest by function application:</p>
<div class="sourceCode" id="cb25"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> table_ (tr_ (td_ (p_ <span class="st">&quot;Hello, World!&quot;</span>)))</span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>table<span class="op">&gt;&lt;</span>tr<span class="op">&gt;&lt;</span>td<span class="op">&gt;&lt;</span>p<span class="op">&gt;</span><span class="dt">Hello</span>, <span class="dt">World</span><span class="op">!&lt;/</span>p<span class="op">&gt;&lt;/</span>td<span class="op">&gt;&lt;/</span>tr<span class="op">&gt;&lt;/</span>table<span class="op">&gt;</span></span></code></pre></div>
<p>Elements are juxtaposed via monoidal append:</p>
<div class="sourceCode" id="cb26"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> p_ <span class="st">&quot;hello&quot;</span> <span class="op">&lt;&gt;</span> p_ <span class="st">&quot;sup&quot;</span></span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>p<span class="op">&gt;</span>hello<span class="op">&lt;/</span>p<span class="op">&gt;&lt;</span>p<span class="op">&gt;</span>sup<span class="op">&lt;/</span>p<span class="op">&gt;</span></span></code></pre></div>
<p>Or monadic sequencing:</p>
<div class="sourceCode" id="cb27"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> div_ (<span class="kw">do</span> p_ <span class="st">&quot;hello&quot;</span>; p_ <span class="st">&quot;sup&quot;</span>)</span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span><span class="fu">div</span><span class="op">&gt;&lt;</span>p<span class="op">&gt;</span>hello<span class="op">&lt;/</span>p<span class="op">&gt;&lt;</span>p<span class="op">&gt;</span>sup<span class="op">&lt;/</span>p<span class="op">&gt;&lt;/</span><span class="fu">div</span><span class="op">&gt;</span></span></code></pre></div>
<p>Attributes are set using the with combinator:</p>
<div class="sourceCode" id="cb28"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> with p_ [class_ <span class="st">&quot;brand&quot;</span>] <span class="st">&quot;Lucid Inc&quot;</span></span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>p <span class="kw">class</span><span class="ot">=</span><span class="st">&quot;brand&quot;</span><span class="op">&gt;</span><span class="dt">Lucid</span> <span class="dt">Inc</span><span class="op">&lt;/</span>p<span class="op">&gt;</span></span></code></pre></div>
<p>Conflicting attributes (like <code>style_</code>) work for attributes
or elements:</p>
<div class="sourceCode" id="cb29"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> html_ (head_ (style_ <span class="st">&quot;body{background:red}&quot;</span>) <span class="op">&lt;&gt;</span></span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a>                 with body_ [style_ <span class="st">&quot;color:white&quot;</span>]</span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a>                      <span class="st">&quot;Look ma, no qualification!&quot;</span>)</span>
<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>html<span class="op">&gt;&lt;</span><span class="fu">head</span><span class="op">&gt;&lt;</span>style<span class="op">&gt;</span>body{background<span class="op">:</span>red}<span class="op">&lt;/</span>style<span class="op">&gt;&lt;/</span><span class="fu">head</span><span class="op">&gt;</span></span>
<span id="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>body style<span class="ot">=</span><span class="st">&quot;color:white&quot;</span><span class="op">&gt;</span><span class="dt">Look</span> ma, no qualification<span class="op">!&lt;/</span>body<span class="op">&gt;&lt;/</span>html<span class="op">&gt;</span></span></code></pre></div>
<h2 id="the-blaze-example">The Blaze example</h2>
<p>For comparison, here’s the Blaze example again:</p>
<div class="sourceCode" id="cb30"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a>page1 <span class="ot">=</span> html <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a>    <span class="fu">head</span> <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a>        title <span class="st">&quot;Introduction page.&quot;</span></span>
<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a>        link <span class="op">!</span> rel <span class="st">&quot;stylesheet&quot;</span> <span class="op">!</span> type_ <span class="st">&quot;text/css&quot;</span> <span class="op">!</span> href <span class="st">&quot;screen.css&quot;</span></span>
<span id="cb30-5"><a href="#cb30-5" aria-hidden="true" tabindex="-1"></a>    body <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb30-6"><a href="#cb30-6" aria-hidden="true" tabindex="-1"></a>        <span class="fu">div</span> <span class="op">!</span> <span class="fu">id</span> <span class="st">&quot;header&quot;</span> <span class="op">$</span> <span class="st">&quot;Syntax&quot;</span></span>
<span id="cb30-7"><a href="#cb30-7" aria-hidden="true" tabindex="-1"></a>        p <span class="st">&quot;This is an example of BlazeMarkup syntax.&quot;</span></span>
<span id="cb30-8"><a href="#cb30-8" aria-hidden="true" tabindex="-1"></a>        ul <span class="op">$</span> <span class="fu">mapM_</span> (li <span class="op">.</span> toMarkup <span class="op">.</span> <span class="fu">show</span>) [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>]</span></code></pre></div>
<p>And the same thing in Lucid:</p>
<div class="sourceCode" id="cb31"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a>page2 <span class="ot">=</span> html_ <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a>    head_ <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a>      title_ <span class="st">&quot;Introduction page.&quot;</span></span>
<span id="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a>      with link_ [rel_ <span class="st">&quot;stylesheet&quot;</span>,type_ <span class="st">&quot;text/css&quot;</span>,href_ <span class="st">&quot;screen.css&quot;</span>]</span>
<span id="cb31-5"><a href="#cb31-5" aria-hidden="true" tabindex="-1"></a>    body_ <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb31-6"><a href="#cb31-6" aria-hidden="true" tabindex="-1"></a>        with div_ [id_ <span class="st">&quot;header&quot;</span>] <span class="st">&quot;Syntax&quot;</span></span>
<span id="cb31-7"><a href="#cb31-7" aria-hidden="true" tabindex="-1"></a>        p_ <span class="st">&quot;This is an example of Lucid syntax.&quot;</span></span>
<span id="cb31-8"><a href="#cb31-8" aria-hidden="true" tabindex="-1"></a>        ul_ <span class="op">$</span> <span class="fu">mapM_</span> (li_ <span class="op">.</span> toHtml <span class="op">.</span> <span class="fu">show</span>) [<span class="dv">1</span>,<span class="dv">2</span>,<span class="dv">3</span>]</span></code></pre></div>
<p>I’m not into operators like <code>($)</code> and swung indentation
like that, but I followed the same format.</p>
<p>I’d write it in a more Lispy style and run my hindent tool on it:</p>
<div class="sourceCode" id="cb32"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a>page1 <span class="ot">=</span></span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a>  html_ (<span class="kw">do</span> head_ (<span class="kw">do</span> title_ <span class="st">&quot;Introduction page.&quot;</span></span>
<span id="cb32-3"><a href="#cb32-3" aria-hidden="true" tabindex="-1"></a>                      with link_</span>
<span id="cb32-4"><a href="#cb32-4" aria-hidden="true" tabindex="-1"></a>                           [rel_ <span class="st">&quot;stylesheet&quot;</span></span>
<span id="cb32-5"><a href="#cb32-5" aria-hidden="true" tabindex="-1"></a>                           ,type_ <span class="st">&quot;text/css&quot;</span></span>
<span id="cb32-6"><a href="#cb32-6" aria-hidden="true" tabindex="-1"></a>                           ,href_ <span class="st">&quot;screen.css&quot;</span>])</span>
<span id="cb32-7"><a href="#cb32-7" aria-hidden="true" tabindex="-1"></a>            body_ (<span class="kw">do</span> with div_ [id_ <span class="st">&quot;header&quot;</span>] <span class="st">&quot;Syntax&quot;</span></span>
<span id="cb32-8"><a href="#cb32-8" aria-hidden="true" tabindex="-1"></a>                      p_ <span class="st">&quot;This is an example of Lucid syntax.&quot;</span></span>
<span id="cb32-9"><a href="#cb32-9" aria-hidden="true" tabindex="-1"></a>                      ul_ (<span class="fu">mapM_</span> (li_ <span class="op">.</span> toHtml <span class="op">.</span> <span class="fu">show</span>)</span>
<span id="cb32-10"><a href="#cb32-10" aria-hidden="true" tabindex="-1"></a>                                 [<span class="dv">1</span>,<span class="dv">2</span>,<span class="dv">3</span>])))</span></code></pre></div>
<p>But that’s another discussion.</p>
<h2 id="its-a-real-monad">It’s a real monad</h2>
<p>Normal monadic operations work properly:</p>
<div class="sourceCode" id="cb33"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> (<span class="fu">return</span> <span class="st">&quot;OK!&quot;</span> <span class="op">&gt;&gt;=</span> p_)</span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>p<span class="op">&gt;</span><span class="dt">OK</span><span class="op">!&lt;/</span>p<span class="op">&gt;</span></span></code></pre></div>
<p>It’s basically a writer monad.</p>
<p>In fact, it’s also a monad transformer:</p>
<div class="sourceCode" id="cb34"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> runReader (renderTextT (html_ (body_ (<span class="kw">do</span> name <span class="ot">&lt;-</span> lift ask</span>
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a>                                            p_ (toHtml name)))))</span>
<span id="cb34-3"><a href="#cb34-3" aria-hidden="true" tabindex="-1"></a>             (<span class="st">&quot;Chris&quot;</span><span class="ot"> ::</span> <span class="dt">String</span>)</span>
<span id="cb34-4"><a href="#cb34-4" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;&lt;html&gt;&lt;body&gt;&lt;p&gt;Chris&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;&quot;</span></span></code></pre></div>
<h2 id="overloaded-strings-instance-is-fine">Overloaded strings instance
is fine</h2>
<p>The instance is constrained over the return type being
<code>()</code>. So string literals can only be type
<code>HtmlT m ()</code>.</p>
<div class="sourceCode" id="cb35"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="kw">do</span> <span class="st">&quot;x&quot;</span> <span class="op">&gt;&gt;</span> <span class="st">&quot;y&quot;</span><span class="ot"> ::</span> <span class="dt">Html</span> ()</span>
<span id="cb35-2"><a href="#cb35-2" aria-hidden="true" tabindex="-1"></a>xy</span>
<span id="cb35-3"><a href="#cb35-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-4"><a href="#cb35-4" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="kw">do</span> x <span class="ot">&lt;-</span> <span class="st">&quot;x&quot;</span>; toHtml (<span class="fu">show</span> x)</span>
<span id="cb35-5"><a href="#cb35-5" aria-hidden="true" tabindex="-1"></a>x()</span></code></pre></div>
<h2 id="attributes">Attributes</h2>
<p>Attributes are simply written as a list. That’s all. Easy to
manipulate as a data structure, easy to write and edit, and
automatically indent in a predictable way:</p>
<div class="sourceCode" id="cb36"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb36-1"><a href="#cb36-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> with p_ [id_ <span class="st">&quot;person-name&quot;</span>,class_ <span class="st">&quot;attribute&quot;</span>] <span class="st">&quot;Mary&quot;</span></span>
<span id="cb36-2"><a href="#cb36-2" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>p <span class="fu">id</span><span class="ot">=</span><span class="st">&quot;person-name&quot;</span> <span class="kw">class</span><span class="ot">=</span><span class="st">&quot;attribute&quot;</span><span class="op">&gt;</span><span class="dt">Mary</span><span class="op">&lt;/</span>p<span class="op">&gt;</span></span></code></pre></div>
<p>No custom operators are required. Just the <code>with</code>
combinator. If you want to indent it, just indent it like normal
function application:</p>
<div class="sourceCode" id="cb37"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb37-1"><a href="#cb37-1" aria-hidden="true" tabindex="-1"></a>with p_</span>
<span id="cb37-2"><a href="#cb37-2" aria-hidden="true" tabindex="-1"></a>     [id_ <span class="st">&quot;person-name&quot;</span>,class_ <span class="st">&quot;attribute&quot;</span>]</span>
<span id="cb37-3"><a href="#cb37-3" aria-hidden="true" tabindex="-1"></a>     <span class="st">&quot;Mary&quot;</span></span></code></pre></div>
<p>And you’re done.</p>
<h2 id="composing-attributes">Composing attributes</h2>
<p>You should be able to compose <code>with</code>. For example, let’s
say you want to define a re-usable component with bootstrap:</p>
<div class="sourceCode" id="cb38"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb38-1"><a href="#cb38-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="kw">let</span> container_ <span class="ot">=</span> with div_ [class_ <span class="st">&quot;container &quot;</span>]</span></code></pre></div>
<p>Now you can use it to make a container:</p>
<div class="sourceCode" id="cb39"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb39-1"><a href="#cb39-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> container_ <span class="st">&quot;My content!&quot;</span></span>
<span id="cb39-2"><a href="#cb39-2" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span><span class="fu">div</span> <span class="kw">class</span><span class="ot">=</span><span class="st">&quot;container &quot;</span><span class="op">&gt;</span><span class="dt">My</span> content<span class="op">!&lt;/</span><span class="fu">div</span><span class="op">&gt;</span></span></code></pre></div>
<p>But consider now that you also want to add additional attributes to
it later. You can do that with another call to with:</p>
<div class="sourceCode" id="cb40"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb40-1"><a href="#cb40-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> with container_ [class_ <span class="st">&quot;main&quot;</span>] <span class="st">&quot;My content!&quot;</span></span>
<span id="cb40-2"><a href="#cb40-2" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span><span class="fu">div</span> <span class="kw">class</span><span class="ot">=</span><span class="st">&quot;container main&quot;</span><span class="op">&gt;</span><span class="dt">My</span> content<span class="op">!&lt;/</span><span class="fu">div</span><span class="op">&gt;</span></span></code></pre></div>
<p>Duplicate attributes are composed with normal monoidal append. Note
that I added a space in my definition of container anticipating further
extension later. Other attributes might not compose with spaces.</p>
<h2 id="unceremonious">Unceremonious</h2>
<p>Another part I made sure was right was lack of import nightmare. You
just <code>import Lucid</code> and away you go:</p>
<div class="sourceCode" id="cb41"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb41-1"><a href="#cb41-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="kw">import</span> <span class="dt">Lucid</span></span>
<span id="cb41-2"><a href="#cb41-2" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> p_ <span class="st">&quot;OK!&quot;</span></span>
<span id="cb41-3"><a href="#cb41-3" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>p<span class="op">&gt;</span><span class="dt">OK</span><span class="op">!&lt;/</span>p<span class="op">&gt;</span></span>
<span id="cb41-4"><a href="#cb41-4" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> p_ (span_ (strong_ <span class="st">&quot;Woot!&quot;</span>))</span>
<span id="cb41-5"><a href="#cb41-5" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>p<span class="op">&gt;&lt;</span><span class="fu">span</span><span class="op">&gt;&lt;</span>strong<span class="op">&gt;</span><span class="dt">Woot</span><span class="op">!&lt;/</span>strong<span class="op">&gt;&lt;/</span><span class="fu">span</span><span class="op">&gt;&lt;/</span>p<span class="op">&gt;</span></span>
<span id="cb41-6"><a href="#cb41-6" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> renderBS (p_ (span_ (strong_ <span class="st">&quot;Woot!&quot;</span>)))</span>
<span id="cb41-7"><a href="#cb41-7" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;&lt;p&gt;&lt;span&gt;&lt;strong&gt;Woot!&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&quot;</span></span>
<span id="cb41-8"><a href="#cb41-8" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> renderToFile <span class="st">&quot;/tmp/foo.html&quot;</span> (p_ (span_ (strong_ <span class="st">&quot;Woot!&quot;</span>)))</span></code></pre></div>
<p>If I want to do more advanced stuff, it’s all available in
<code>Lucid</code>. But by default it’s absolutely trivial to get going
and output something.</p>
<h2 id="speed">Speed</h2>
<p>Actually, despite having a trivial implementation, being a real monad
and a monad transformer, it’s not far from Blaze. A quick test of
writing 38M of HTML to file yielded the same speed (about 1.5s) for both
Lucid and Blaze. With such decent performance for very little work I’m
already ready to start using it for real work.</p>
<h2 id="summary">Summary</h2>
<p>So the point of this post was really to explain <em>why another HTML
DSL</em> and I hope I did that well enough.</p>
<p>The code is <a href="https://github.com/chrisdone/lucid">on
Github</a>. I pushed to Hackage but you can consider it beta for
now.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2014-11-20 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Thu, 20 Nov 2014 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Fast pagination on PostgreSQL]]></title><link>https://chrisdone.com/posts/postgresql-pagination</link><guid>https://chrisdone.com/posts/postgresql-pagination</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Fast pagination on PostgreSQL</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Fast pagination on PostgreSQL</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p><strong>UPDATE: 2014-11-19:</strong> Some people asked me how much
creating an index on <code>event(channel,id)</code> helps. Answer: not
much.</p>
<p>During the implementation of <a
href="http://ircbrowse.net/">IRCBrowse</a> I discovered that Postgres’s
built-in offset is not very fast.</p>
<p>Here are the characteristics of my data:</p>
<pre><code>ircbrowse=&gt; \d event
                                    Table &quot;public.event&quot;
  Column   |           Type           |
-----------+--------------------------+
 timestamp | timestamp with time zone |
 type      | text                     |
 nick      | text                     |
 text      | text                     |
 network   | integer                  |
 channel   | integer                  |
 id        | bigint                   |
Indexes:
    &quot;event_unique&quot; UNIQUE CONSTRAINT,
    btree (network, channel, &quot;timestamp&quot;, nick, type, text)
    &quot;event_unique_id&quot; UNIQUE CONSTRAINT, btree (id)
    &quot;event_channel_idx&quot; btree (channel)
    &quot;event_nick_idx&quot; btree (nick)
    &quot;event_timestamp_idx&quot; btree (&quot;timestamp&quot;)
    &quot;event_type_idx&quot; btree (type)</code></pre>
<p>And the size:</p>
<pre><code>ircbrowse=&gt; select count(*) from event;
  count
----------
 28673917</code></pre>
<p>Channel 1 is the biggest:</p>
<pre><code>ircbrowse=&gt; select count(*) from event where channel = 1;
  count
----------
 19340467</code></pre>
<p>When you’re working with data on this scale (large, but not “big
data”), PostgreSQL handles it beautifully. But the speed of
<code>OFFSET</code>/<code>LIMIT</code> is not great:</p>
<pre><code>ircbrowse=&gt; explain analyze select * from event where channel = 1
                            order by id offset 500000 limit 30;
QUERY PLAN
Limit  (cost=5648.81..5818.28 rows=30 width=85)
       (actual time=0.301..0.309 rows=30 loops=1)
   -&gt;  Index Scan using event_unique_id on event
   (cost=0.00..81914674.39 rows=14501220 width=85)
   (actual time=0.020..0.288 rows=1030 loops=1)
         Filter: (channel = 1)</code></pre>
<p>I think that this index scan is simply too expensive. Notice that I’m
ordering by id which has a unique btree index on it. Check out the
speed:</p>
<pre><code>ircbrowse=&gt; select * from event where channel = 1
            order by id offset 1000 limit 30;
Time: 0.721 ms
ircbrowse=&gt; select * from event where channel = 1
            order by id offset 500000 limit 30;
Time: 191.926 ms</code></pre>
<p>You might think less than a second to sift through 500,000 rows of a
28million row table is pretty good, but I think it sucks. It’s also
deceptive. Let’s increase it to 1,000,000 rows (of 19,000,00):</p>
<pre><code>ircbrowse=&gt; select * from event where channel = 1
            order by id offset 1000000 limit 30;
Time: 35022.464 ms</code></pre>
<p>This is getting worse and worse! It’s probably linear in its poor
performance.</p>
<p>However, there’s a solution. Use an index table. A separate table
which contains foreign keys pointing to this table:</p>
<pre><code>ircbrowse=&gt; \d event_order_index
Table &quot;public.event_order_index&quot;
 Column |  Type   | Modifiers
--------+---------+-----------
 id     | integer | not null
 origin | integer | not null
 idx    | integer | not null
Indexes:
    &quot;event_order_id_origin&quot; UNIQUE CONSTRAINT, btree (id, origin)
    &quot;event_order_idx&quot; btree (id)
    &quot;event_order_idx_idx&quot; btree (idx)
    &quot;event_order_origin_dx&quot; btree (origin)</code></pre>
<p>Now you can have a pagination index for channel 1:</p>
<pre><code>ircbrowse=&gt; select * from event_order_index where idx = 1000 limit 1;
 id | origin | idx
----+--------+------
  1 |      1 | 1000</code></pre>
<p>(I used idx=1000 for channel 1, 2000 for channel 2, etc. so that I
would have space for other numerical indexes for the same channel.)</p>
<p>Now you can make a very efficient query for the same data as
above:</p>
<pre><code>ircbrowse=&gt; SELECT idx.id,e.timestamp,e.network,e.channel,
ircbrowse=&gt; e.type,e.nick,e.text FROM event e,
ircbrowse-&gt; event_order_index idx
ircbrowse-&gt; WHERE e.id = idx.origin and idx.idx = 1000 and
ircbrowse=&gt; idx.id &gt; 1000000 and idx.id &lt; 1000030
ircbrowse-&gt; ORDER BY e.id asc
ircbrowse-&gt; LIMIT 30;
Time: 1.001 ms</code></pre>
<p>This is more or less constant time.</p>
<p>And you can see this in action on the site. Takes about 30ms to load
and render the page if I run this on the server:</p>
<pre><code>$ time curl &#39;http://ircbrowse.net/browse/haskell?events_page=234&#39;

real    0m0.031s
user    0m0.000s
sys     0m0.004s</code></pre>
<p>Of course, sending a request in your browser will take longer due to
the connection overhead and assets, but generally the goal was for it to
be very snappy. The old ircbrowse.com (by another individual, who kindly
let me have the name) was very slow indeed. You’d see the page loading
the data incrementally from the database.</p>
<p>Anyhoo, thought that was a decent, practical PostgreSQL-specific
optimization regarding pagination. Hope it was worth writing up.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2014-10-28 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Tue, 28 Oct 2014 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[shell-conduit: Write shell scripts in Haskell with Conduit]]></title><link>https://chrisdone.com/posts/shell-conduit</link><guid>https://chrisdone.com/posts/shell-conduit</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>shell-conduit: Write shell scripts in Haskell with
Conduit</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>shell-conduit: Write shell scripts in Haskell with Conduit</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>As part of my series of write-about-personal-projects, my latest
obsession is writing shell scripts with Michael Snoyman’s <a
href="http://hackage.haskell.org/package/conduit">Conduit</a>.</p>
<p>Here is my package, <a
href="http://github.com/chrisdone/shell-conduit/">shell-conduit</a>.
It’s still in the experimental phase, but I don’t forsee any changes now
for a while.</p>
<h2 id="bash-is-evil">Bash is evil</h2>
<p>I hate writing scripts in Bash. Until now, it was the easiest way to
just write unix scripts. Its syntax is insane, incredibly error prone,
its defaults are awful, and it’s not a real big person programming
language.</p>
<h2 id="perlpythonruby-are-also-evil">Perl/Python/Ruby are also
evil</h2>
<p>If you’re going to go as far as using a real programming language,
why bother with these dynamically typed messes? Go straight for
Haskell.</p>
<h2 id="like-a-glove">Like a glove</h2>
<p><img
src="http://24.media.tumblr.com/tumblr_m3037pY5x71qbkdr4o1_500.gif" /></p>
<p>I had an inkling a while back that conduits mirror the behaviour of
bash pipes very well. I knew there was something to the idea, but didn’t
act on it fully for a while. Last week I experimented somewhat and
realised that the following Haskell code</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>source <span class="op">$=</span> conduit <span class="op">$$</span> sink</span></code></pre></div>
<p>does indeed accurately mirror</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode bash"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="bu">source</span> <span class="kw">|</span> <span class="ex">conduit</span> <span class="op">&gt;</span> sink</span></code></pre></div>
<p>And that also the following</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>(<span class="kw">do</span> source</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    source <span class="op">$=</span> conduit)</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="op">$$$$</span> sink</span></code></pre></div>
<p>is analogous to</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode bash"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="bu">source</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="bu">source</span> <span class="kw">|</span> <span class="ex">conduit</span></span></code></pre></div>
<p>We’ll see examples of why this works later.</p>
<h2 id="i-must-haskell-all-the-things">I must Haskell all the
things</h2>
<p>Another trick I realised is to write some template Haskell code which
will calculate all executables in your PATH at compilation time and
generate a top-level name that is a Haskell function to launch that
process. So instead of writing</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>run <span class="st">&quot;ls&quot;</span></span></code></pre></div>
<p>you could instead just write</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>ls</span></code></pre></div>
<p>There are a few thousand executables, so it takes about 10 seconds to
compile such a module of names. But that’s all.</p>
<p>Again, we’ll see how awesome this looks in a minute.</p>
<h2 id="modeling-stdin-stderr-and-stdout">Modeling stdin, stderr and
stdout</h2>
<p>My choice of modeling the typical shell scripting pipe handles is by
having a type called <code>Chunk</code>:</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Chunk</span> <span class="ot">=</span> <span class="dt">Either</span> <span class="dt">ByteString</span> <span class="dt">ByteString</span></span></code></pre></div>
<p>All <code>Left</code> values are from <code>stderr</code>. All
<code>Right</code> values are either being pulled from
<code>stdin</code> or being sent to <code>stdout</code>. In a conduit
the difference between <code>stdin</code> and <code>stdout</code> is
more conceptual than real.</p>
<p>When piping two commands, the idea is that any <code>Left</code>
values are just re-yielded along, they are not consumed and passed into
the process.</p>
<h2 id="a-process-conduit-on-chunks">A process conduit on chunks</h2>
<p>Putting the previous model into practice, we come up with a type for
launching a process like this:</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ot">conduitProcess ::</span> (<span class="dt">MonadResource</span> m)</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>               <span class="ot">=&gt;</span> <span class="dt">CreateProcess</span> <span class="ot">-&gt;</span> <span class="dt">Conduit</span> <span class="dt">Chunk</span> m <span class="dt">Chunk</span></span></code></pre></div>
<p>Meaning the process will be launched, and the conduit will accept any
upstream <code>stdin</code> (<code>Right</code> values), and send
downstream anything that comes from the actual process (both
<code>Left</code> and <code>Right</code> values).</p>
<h2 id="process-conduits-api">Process conduits API</h2>
<p>I defined two handy functions for running process conduits:</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="ot">shell ::</span> (<span class="dt">MonadResource</span> m)</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>      <span class="ot">=&gt;</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Conduit</span> <span class="dt">Chunk</span> m <span class="dt">Chunk</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="ot">proc ::</span> (<span class="dt">MonadResource</span> m)</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>     <span class="ot">=&gt;</span> <span class="dt">String</span> <span class="ot">-&gt;</span> [<span class="dt">String</span>] <span class="ot">-&gt;</span> <span class="dt">Conduit</span> <span class="dt">Chunk</span> m <span class="dt">Chunk</span></span></code></pre></div>
<p>One to launch via a shell, one to launch via program name and
arguments. These functions can be used in your shell scripts. Though,
we’ll see in a minute why you should rarely need either.</p>
<h2 id="executing-a-shell-scripting-conduit">Executing a shell scripting
conduit</h2>
<p>First we want something to consume any remainder chunks after a
script has finished. That’s <code>writeChunks</code>:</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="ot">writeChunks ::</span> (<span class="dt">MonadIO</span> m)</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>            <span class="ot">=&gt;</span> <span class="dt">Consumer</span> <span class="dt">Chunk</span> m ()</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>writeChunks <span class="ot">=</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>  awaitForever</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>    (\c <span class="ot">-&gt;</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>       <span class="kw">case</span> c <span class="kw">of</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>         <span class="dt">Left</span> e <span class="ot">-&gt;</span> liftIO (S.hPut stderr e)</span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>         <span class="dt">Right</span> o <span class="ot">-&gt;</span> liftIO (S.hPut stdout o))</span></code></pre></div>
<p>This simply consumes anything left in the pipeline and outputs to the
correct file handles, either <code>stderr</code> or
<code>stdout</code>.</p>
<p>Now we can write a simple <code>run</code> function:</p>
<div class="sourceCode" id="cb11"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="ot">run ::</span> (<span class="dt">MonadIO</span> m,<span class="dt">MonadBaseControl</span> <span class="dt">IO</span> m)</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>    <span class="ot">=&gt;</span> <span class="dt">Conduit</span> <span class="dt">Chunk</span> (<span class="dt">ShellT</span> m) <span class="dt">Chunk</span> <span class="ot">-&gt;</span> m ()</span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>run p <span class="ot">=</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>  runResourceT</span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>    (runShellT (sourceList [] <span class="op">$=</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>                p <span class="op">$$</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>                writeChunks))</span></code></pre></div>
<p>First it yields an empty upstream of chunks. That’s the source. Then
our script <code>p</code> is run as the conduit in between, finally we
write out any chunks that remain.</p>
<p>Let’s try that out:</p>
<div class="sourceCode" id="cb12"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> run (shell <span class="st">&quot;echo hello!&quot;</span>)</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>hello<span class="op">!</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> run (proc <span class="st">&quot;date&quot;</span> [<span class="st">&quot;+%Y&quot;</span>])</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a><span class="dv">2014</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> run (shell <span class="st">&quot;echo oops &gt; /dev/stderr&quot;</span>)</span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>oops</span></code></pre></div>
<p>Looks good. Standard output was written properly, as was stderr.</p>
<h2 id="returning-to-our-mass-name-generation">Returning to our mass
name generation</h2>
<p>Let’s take our earlier work of generating names with
template-haskell. With that in place, we have a process conduit for
every executable in <code>PATH</code>. Add to that variadic argument
handling for each one, we get a list of names like this:</p>
<div class="sourceCode" id="cb13"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="ot">rmdir ::</span> <span class="dt">ProcessType</span> r <span class="ot">=&gt;</span> r</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="ot">ls ::</span> <span class="dt">ProcessType</span> r <span class="ot">=&gt;</span> r</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a><span class="ot">egrep ::</span> <span class="dt">ProcessType</span> r <span class="ot">=&gt;</span> r</span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a><span class="ot">dmesg ::</span> <span class="dt">ProcessType</span> r <span class="ot">=&gt;</span> r</span></code></pre></div>
<p>The real types when instantiated will look like:</p>
<div class="sourceCode" id="cb14"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a>rmdir <span class="st">&quot;foo&quot;</span><span class="ot"> ::</span> <span class="dt">Conduit</span> <span class="dt">Chunk</span> m <span class="dt">Chunk</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a><span class="ot">ls ::</span> <span class="dt">Conduit</span> <span class="dt">Chunk</span> m <span class="dt">Chunk</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>ls <span class="st">&quot;.&quot;</span><span class="ot"> ::</span> <span class="dt">Conduit</span> <span class="dt">Chunk</span> m <span class="dt">Chunk</span></span></code></pre></div>
<h2 id="putting-it-all-together">Putting it all together</h2>
<p>We can now provide any number of arguments:</p>
<div class="sourceCode" id="cb15"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> run ls</span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>dist</span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a><span class="dt">LICENSE</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>README.md</span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>Setup.hs</span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a>shell<span class="op">-</span>conduit<span class="op">.</span>cabal</span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a>src</span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a><span class="dt">TAGS</span></span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true" tabindex="-1"></a>TODO.org</span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> run (ls <span class="st">&quot;/&quot;</span>)</span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true" tabindex="-1"></a>bin</span>
<span id="cb15-12"><a href="#cb15-12" aria-hidden="true" tabindex="-1"></a>boot</span>
<span id="cb15-13"><a href="#cb15-13" aria-hidden="true" tabindex="-1"></a>cdrom</span>
<span id="cb15-14"><a href="#cb15-14" aria-hidden="true" tabindex="-1"></a>…</span></code></pre></div>
<p>We can pipe things together:</p>
<div class="sourceCode" id="cb16"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> run (<span class="kw">do</span> ls <span class="st">&quot;-1&quot;</span> <span class="op">$=</span> head&#39; <span class="st">&quot;-2&quot;</span>)</span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>dist</span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a><span class="dt">LICENSE</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> run (ls <span class="op">$=</span> grep <span class="st">&quot;Key&quot;</span> <span class="op">$=</span> shell <span class="st">&quot;cat&quot;</span> <span class="op">$=</span> CL.map (second (S8.map <span class="fu">toUpper</span>)))</span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a><span class="dt">KEYBOARD.HI</span></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a><span class="dt">KEYBOARD.HS</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a><span class="dt">KEYBOARD.O</span></span></code></pre></div>
<p>Results are outputted to stdout unless piped into other
processes:</p>
<div class="sourceCode" id="cb17"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> run (<span class="kw">do</span> shell <span class="st">&quot;echo sup&quot;</span>; shell <span class="st">&quot;echo hi&quot;</span>)</span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>sup</span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>hi</span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> run (<span class="kw">do</span> shell <span class="st">&quot;echo sup&quot;</span>; sed <span class="st">&quot;s/u/a/&quot;</span>; shell <span class="st">&quot;echo hi&quot;</span>)</span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a>sup</span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a>hi</span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> run (<span class="kw">do</span> shell <span class="st">&quot;echo sup&quot;</span> <span class="op">$=</span> sed <span class="st">&quot;s/u/a/&quot;</span>; shell <span class="st">&quot;echo hi&quot;</span>)</span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a>sap</span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a>hi</span></code></pre></div>
<p>Live streaming between pipes like in normal shell scripting is
possible:</p>
<div class="sourceCode" id="cb18"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> run (<span class="kw">do</span> tail&#39; <span class="st">&quot;/tmp/example.txt&quot;</span> <span class="st">&quot;-f&quot;</span> <span class="op">$=</span> grep <span class="st">&quot;--line-buffered&quot;</span> <span class="st">&quot;Hello&quot;</span>)</span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Hello</span>, world<span class="op">!</span></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a><span class="dt">Oh</span>, hello<span class="op">!</span></span></code></pre></div>
<p>(Remember that <code>grep</code> needs <code>--line-buffered</code>
if it is to output things line-by-line).</p>
<h2 id="error-handling">Error handling</h2>
<p>By default, if a process errors out, the whole script ends. This is
contrary to Bash, which keeps going regardless of failure. This is
bad.</p>
<p>In Bash, to revert this default, you run:</p>
<div class="sourceCode" id="cb19"><pre
class="sourceCode bash"><code class="sourceCode bash"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="bu">set</span> <span class="at">-e</span></span></code></pre></div>
<p>And the way to ignore erroneous commands on case-by-case basis is to
use <code>|| true</code>:</p>
<div class="sourceCode" id="cb20"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a>killall nonexistant <span class="op">||</span> true</span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>echo <span class="dt">OK</span>, done<span class="op">.</span></span></code></pre></div>
<p>Which means “do foo, or otherwise ignore it, continue the
script”.</p>
<p>We can express the same thing using the Alternative instance for the
<code>ShellT</code> type:</p>
<div class="sourceCode" id="cb21"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> run (<span class="kw">do</span> killall <span class="st">&quot;nonexistant&quot;</span> <span class="st">&quot;-q&quot;</span>; echo <span class="st">&quot;OK, done.&quot;</span>)</span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a><span class="op">***</span> <span class="dt">Exception</span><span class="op">:</span> <span class="dt">ShellExitFailure</span> <span class="dv">1</span></span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> run (<span class="kw">do</span> killall <span class="st">&quot;nonexistant&quot;</span> <span class="st">&quot;-q&quot;</span> <span class="op">&lt;|&gt;</span> <span class="fu">return</span> (); echo <span class="st">&quot;OK, done.&quot;</span>)</span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a><span class="dt">OK</span>, done<span class="op">.</span></span></code></pre></div>
<h2 id="string-types">String types</h2>
<p>If using <code>OverloadedStrings</code> so that you can use
<code>Text</code> for arguments, then also enable
<code>ExtendedDefaultRules</code>, otherwise you’ll get ambiguous type
errors.</p>
<div class="sourceCode" id="cb22"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE ExtendedDefaultRules #-}</span></span></code></pre></div>
<p>But this isn’t necessary if you don’t need to use <code>Text</code>
yet. Strings literals will be interpreted as <code>String</code>. Though
you can pass a value of type <code>Text</code> or any instance of
<code>CmdArg</code> without needing conversions.</p>
<h2 id="examples-of-script-files">Examples of script files</h2>
<p>Quick script to reset my keyboard (Linux tends to forget these things
when I unplug my keyboard):</p>
<div class="sourceCode" id="cb23"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Conduit.Shell</span></span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span></span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a>  run (<span class="kw">do</span> xmodmap <span class="st">&quot;.xmodmap&quot;</span></span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a>          xset <span class="st">&quot;r&quot;</span> <span class="st">&quot;rate&quot;</span> <span class="st">&quot;150&quot;</span> <span class="st">&quot;50&quot;</span>)</span></code></pre></div>
<p>Cloning and initializing a repo (ported from a bash script):</p>
<div class="sourceCode" id="cb24"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Monad.IO.Class</span></span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Conduit.Shell</span></span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">System.Directory</span></span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span></span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a>  run (<span class="kw">do</span> exists <span class="ot">&lt;-</span> liftIO (doesDirectoryExist <span class="st">&quot;fpco&quot;</span>)</span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a>          <span class="kw">if</span> exists</span>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a>             <span class="kw">then</span> rm <span class="st">&quot;fpco/.hsenvs&quot;</span> <span class="st">&quot;-rf&quot;</span></span>
<span id="cb24-8"><a href="#cb24-8" aria-hidden="true" tabindex="-1"></a>             <span class="kw">else</span> git <span class="st">&quot;clone&quot;</span> <span class="st">&quot;git@github.com:fpco/fpco.git&quot;</span></span>
<span id="cb24-9"><a href="#cb24-9" aria-hidden="true" tabindex="-1"></a>          liftIO (setCurrentDirectory <span class="st">&quot;fpco&quot;</span>)</span>
<span id="cb24-10"><a href="#cb24-10" aria-hidden="true" tabindex="-1"></a>          shell <span class="st">&quot;./dev-scripts/update-repo.sh&quot;</span></span>
<span id="cb24-11"><a href="#cb24-11" aria-hidden="true" tabindex="-1"></a>          shell <span class="st">&quot;./dev-scripts/build-all.sh&quot;</span></span>
<span id="cb24-12"><a href="#cb24-12" aria-hidden="true" tabindex="-1"></a>          alertDone)</span></code></pre></div>
<p>Script to restart a web process (ported from an old bash script I
had):</p>
<div class="sourceCode" id="cb25"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Applicative</span></span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Monad.Fix</span></span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Conduit.Shell</span></span>
<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span></span>
<span id="cb25-5"><a href="#cb25-5" aria-hidden="true" tabindex="-1"></a>  run (<span class="kw">do</span> ls</span>
<span id="cb25-6"><a href="#cb25-6" aria-hidden="true" tabindex="-1"></a>          echo <span class="st">&quot;Restarting server ... ?&quot;</span></span>
<span id="cb25-7"><a href="#cb25-7" aria-hidden="true" tabindex="-1"></a>          killall name <span class="st">&quot;-q&quot;</span> <span class="op">&lt;|&gt;</span> <span class="fu">return</span> ()</span>
<span id="cb25-8"><a href="#cb25-8" aria-hidden="true" tabindex="-1"></a>          fix (\loop <span class="ot">-&gt;</span></span>
<span id="cb25-9"><a href="#cb25-9" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">do</span> echo <span class="st">&quot;Waiting for it to terminate ...&quot;</span></span>
<span id="cb25-10"><a href="#cb25-10" aria-hidden="true" tabindex="-1"></a>                    sleep <span class="st">&quot;1&quot;</span></span>
<span id="cb25-11"><a href="#cb25-11" aria-hidden="true" tabindex="-1"></a>                    (ps <span class="st">&quot;-C&quot;</span> name <span class="op">$=</span> discardChunks <span class="op">&gt;&gt;</span> loop) <span class="op">&lt;|&gt;</span> <span class="fu">return</span> ())</span>
<span id="cb25-12"><a href="#cb25-12" aria-hidden="true" tabindex="-1"></a>          shell <span class="st">&quot;dist/build/ircbrowse/ircbrowse ircbrowse.conf&quot;</span>)</span>
<span id="cb25-13"><a href="#cb25-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">where</span> name <span class="ot">=</span> <span class="st">&quot;ircbrowse&quot;</span></span></code></pre></div>
<h2 id="youve-seen-shelly-right">You’ve seen Shelly, right?</h2>
<p>Right. Shelly’s fine. It just lacks the two killer things for me:</p>
<ul>
<li>All names are bound, so I can just use them as normal
functions.</li>
<li>shell-conduit also, due to its mass name binding, prioritizes
commands. For example, Shelly has <a
href="http://hackage.haskell.org/package/shelly-1.5.5/docs/Shelly.html#g:9">a
group of functions for manipulating the file system</a>. In
shell-conduit, you just use your normal commands: <code>rm "x"</code>
and <code>mv   "x" "y"</code>.</li>
<li>Not based on conduit. Conduit is a whole suite of streaming
utilities perfect for scripting.</li>
<li>Piped is not the default, either. There’re a bunch of choices:
Shelly, Shelly.Lifted, Shelly.Pipe. Choice is good, but for a scripting
language I personally prefer one goto way to do something.</li>
</ul>
<p>Also, Shelly cannot do live streams like Conduit can.</p>
<h2 id="conduits-as-good-scripting-libraries">Conduits as good scripting
libraries</h2>
<p>You might want to import the regular Conduit modules qualified,
too:</p>
<div class="sourceCode" id="cb26"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.Conduit.List</span> <span class="kw">as</span> <span class="dt">CL</span></span></code></pre></div>
<p>Which contains handy functions for working on streams in a list-like
way. See the rest of the handy modules for Conduit in <a
href="http://hackage.haskell.org/package/conduit-extra">conduit-extra</a>.</p>
<p>Also of interest is <a
href="http://hackage.haskell.org/package/csv-conduit">csv-conduit</a>,
<a
href="http://hackage.haskell.org/package/html-conduit">html-conduit</a>,
and <a
href="http://hackage.haskell.org/package/http-conduit">http-conduit</a>.</p>
<p>Finally, see the Conduit category on Hackage for other useful
libraries: <a href="http://hackage.haskell.org/packages/#cat:Conduit"
class="uri">http://hackage.haskell.org/packages/#cat:Conduit</a></p>
<p>All of these general purpose Conduits can be used in shell
scripting.</p>
<h2 id="using-it-for-real-scripts">Using it for real scripts</h2>
<p>So far I have ported a few small scripts to shell-conduit from Bash
and have been happy every time. I suck at Bash. I’m pretty good at
Haskell.</p>
<p>The next test is applying this to my Hell shell and seeing if I can
use it as a commandline shell, too.</p>
<p>My friend complained that having to quote all arguments is a pain. I
don’t really agree that this is bad. In Bash it’s often unclear how
arguments are going to be interpreted. I’m happy just writing something
predictable than something super convenient but possibly nonsense.</p>
<h2 id="summary">Summary</h2>
<p>I set out a week ago to just stop writing Bash scripts. I’ve written
a bunch of scripts in Haskell, but I would still write Bash scripts too.
Some things were just too boring to write. I wanted to commit to Haskell
for scripting. Today, I’m fairly confident I have a solution that is
going to be satisfactory for a long while.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2014-09-21 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sun, 21 Sep 2014 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[hindent: A Haskell indenter]]></title><link>https://chrisdone.com/posts/hindent</link><guid>https://chrisdone.com/posts/hindent</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>hindent: A Haskell indenter</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>hindent: A Haskell indenter</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<h2 id="a-question-of-style">A question of style</h2>
<p>In this post I’m going to use the word “style” to refer to the way
code is printed in concrete terms. No changes in the code that would
yield a different syntax tree are considered “style” here.</p>
<h2 id="whats-the-deal-with-code-style">What’s the deal with code
style?</h2>
<p>Code style is important! If you’re a professional Haskell programmer,
you’re working with Haskell code all day. The following things are
affected by the style used:</p>
<ul>
<li>How easily it can be manipulated with regular editors: the more code
is laid out in a way that prevents you from readily using your normal
editor functions, the less efficient you are.</li>
<li>How well general tooling works with it: do diff and things like that
work well?</li>
<li>How easily you can absorb the structure: do you have to spend time
hunting around for the start and end of syntactical nodes? Can’t see the
tree for the forest?</li>
<li>How quickly you can write it: can you just write code or do you have
to spend time thinking about how it’s going to be laid out before
writing, or editing the layout afterwards?</li>
<li>How aesthetically offended you are<a href="#fn1"
class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a>:
does the code you’re looking at assault your sense of beauty?</li>
</ul>
<p>Code style is important! Let’s have a code style discussion. I
propose to solve it with tooling.</p>
<h2 id="is-this-really-an-issue-though">Is this really an issue,
though?</h2>
<p>Okay, so I’m one guy with a bee in his bonnet. Let’s do a quick
Google and see what others are saying in <a
href="http://stackoverflow.com/questions/1983047/good-haskell-coding-standards">this
StackOverflow</a> question:</p>
<blockquote>
<p>Could someone provide a link to a good coding standard for Haskell?
I’ve found this and this, but they are far from comprehensive.</p>
</blockquote>
<p>The following points refer to style:</p>
<ul>
<li>Format your code so it fits in 80 columns. (Advanced users may
prefer 87 or 88; beyond that is pushing it.)</li>
<li>Put spaces around infix operators. Put a space following each comma
in a tuple literal.</li>
<li>Prefer a space between a function and its argument, even if the
argument is parenthesized.</li>
<li>Use line breaks carefully. Line breaks can increase readability, but
there is a trade-off: Your editor may display only 40–50 lines at once.
If you need to read and understand a large function all at once, you
mustn’t overuse line breaks.</li>
<li>When possible, align – lines, = signs, and even parentheses and
commas that occur in adjacent lines.</li>
</ul>
<p>Even the Haskell community is not immune to <a
href="http://www.reddit.com/r/haskell/comments/15gz8q/a_nondirty_shot_at_tabs_vs_spaces/">long,
protracted debates about tabs vs spaces.</a> That reddit submission has
zero points. That means it’s very controversial. The submission also has
117 comments. That means people are very vocal about this topic. That’s
because bike-shedding is inversely proportional to the triviality of the
debated thing. We know that.</p>
<p>Nevertheless, style is important enough to be discussed.</p>
<h2 id="so-lets-formalise-a-standard-style">So let’s formalise a
standard style</h2>
<p>That’s a simplification. There are many style guides:</p>
<ul>
<li><a
href="http://courses.cms.caltech.edu/cs11/material/haskell/misc/haskell_style_guide.html">Caltech’s
style guide</a></li>
<li><a href="http://urchin.earth.li/~ian/style/haskell.html">Good
Haskell Style</a> (unattributed)</li>
<li><a href="https://github.com/tibbe/haskell-style-guide">Johan
Tibell’s</a> style guide</li>
<li><a href="https://github.com/chrisdone/haskell-style-guide">My own
style guide</a></li>
<li><a href="http://snapframework.com/docs/style-guide">Snap’s style
guide</a></li>
</ul>
<p>These are just public ones. In-house styles are also common, for a
particular company. It’s not practical to force everyone into one single
style. It’s <a href="http://en.wikipedia.org/wiki/Indent_style#Styles">a
well-worn topic in the C world</a>.</p>
<h2 id="okay-but-is-this-a-problem-tooling-even-needs-to-solve">Okay,
but is this a problem tooling even needs to solve?</h2>
<p>There is precedent for other tooling based on style:</p>
<ul>
<li><a href="http://community.haskell.org/~ndm/hlint/">Neil Mitchell’s
hlint</a>: “HLint (formerly Dr. Haskell) reads Haskell programs and
suggests changes that hopefully make them easier to read.”</li>
<li><a href="https://github.com/mightybyte/hstyle">Doug Beardsley’s
hstyle</a>: “The ultimate goal would be an automatic reformatter that
generates gorgeous code–but that’s a hard problem.”</li>
<li>The <a
href="http://courses.cms.caltech.edu/cs11/material/haskell/misc/haskell_style_guide.html">previously
mentioned Caltech style guide</a> contains a program to check source
code.</li>
<li>That’s not to mention <a
href="http://www.gnu.org/software/indent/">the venerable GNU
indent</a>.</li>
<li>And more recently, <a
href="https://www.npmjs.org/package/js-beautify">js-beautify</a></li>
</ul>
<h2 id="everyone-has-their-own-style">Everyone has their own style</h2>
<p>So then let’s make a tool with a select number of styles, you might
say. The problem is that people don’t even use the standards that exist
out there. They used slightly varying versions. Ask any Haskeller what
style they use, and they will say “mostly like X, but with some
differences.”</p>
<p>For example <a
href="http://www.quora.com/What-are-some-good-style-guides-for-writing-Haskell-code">What
are some good style guides for writing Haskell code?</a><a href="#fn2"
class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a></p>
<blockquote>
<p>I use a very similar style, with a few modifications. […] Perhaps I
should write out my own style guide at some point, especially as I’ve
become pretty set in my style lately.</p>
</blockquote>
<p>And <a
href="http://robertmassaioli.wordpress.com/2011/02/19/good-haskell-coding-style/">Good
Haskell Coding Style</a><a href="#fn3" class="footnote-ref" id="fnref3"
role="doc-noteref"><sup>3</sup></a>:</p>
<blockquote>
<p>My Personal Pet Peeves</p>
<p>For the most part the style guides that I have added above (and the
tools provided) mirror my own style guide (or perhaps my guide mirrors
them). However, there is one item of style that particularly annoys me
on a regular basis. […]</p>
</blockquote>
<h2 id="cant-we-just-use-structured-editors">Can’t we just use
structured editors?</h2>
<p>Some more optimistic folk out there might suggest, perhaps, we should
just throw away text files and go straight for structured code
databases. Put all this formatting nonsense behind us. Layout is just a
stylesheet! It’s not data to be stored in a file!</p>
<p>Maybe so. But nobody is using structured editors yet.</p>
<h2 id="a-practical-way-forward">A practical way forward</h2>
<p>Taking all of the above into consideration, here is my approach at
the problem. The <a
href="https://github.com/chrisdone/hindent">hindent</a> library and
program. Styled on GNU indent, the intention is that you simply run the
program on some source code and it reformats it.</p>
<pre><code>$ hindent
hindent: arguments: --style [fundamental|chris-done|johan-tibell]</code></pre>
<p>hindent has the concept of styles built in. There is <a
href="http://chrisdone.github.io/hindent/HIndent-Types.html#t:Style">a
type</a> for it:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Style</span> <span class="ot">=</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">forall</span> s<span class="op">.</span> <span class="dt">Style</span> {<span class="ot">styleName ::</span> <span class="op">!</span><span class="dt">Text</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>                  ,<span class="ot">styleAuthor ::</span> <span class="op">!</span><span class="dt">Text</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>                  ,<span class="ot">styleDescription ::</span> <span class="op">!</span><span class="dt">Text</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>                  ,<span class="ot">styleInitialState ::</span> <span class="op">!</span>s</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>                  ,<span class="ot">styleExtenders ::</span> <span class="op">!</span>[<span class="dt">Extender</span> s]</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>                  ,<span class="ot">styleDefConfig ::</span> <span class="op">!</span><span class="dt">Config</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>                  }</span></code></pre></div>
<p>It contains authorship metadata. It holds an initial state which can
be used during printing. Most importantly, it has a list of extenders.
Means to extend the printer and change its behaviour on a
node-type-specific basis.</p>
<p>Take a normal pretty printing approach. It’s usually something
like:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> <span class="dt">Pretty</span> a <span class="kw">where</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="ot">  pretty ::</span> a <span class="ot">-&gt;</span> <span class="dt">String</span></span></code></pre></div>
<p>Then for all the types in <a
href="http://hackage.haskell.org/package/haskell-src-exts-1.15.0.1/docs/Language-Haskell-Exts-Annotated-Syntax.html">the
AST</a> we implement an instance of <code>Pretty</code>.</p>
<p>The limitation here is that we can’t, as a user of the library,
decide to print one particular node type differently.</p>
<p>Instead, here’s a new class:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> (<span class="dt">Annotated</span> ast,<span class="dt">Typeable</span> ast) <span class="ot">=&gt;</span> <span class="dt">Pretty</span> ast <span class="kw">where</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="ot">  prettyInternal ::</span> ast <span class="dt">NodeInfo</span> <span class="ot">-&gt;</span> <span class="dt">Printer</span> ()</span></code></pre></div>
<p>(It runs in a <code>Printer</code> type to store some state about the
current column and indentation level, things like that.)</p>
<p>Now, we implement the <code>prettyInternal</code> method for all our
types. But when implementing instances, we never use the
<code>prettyInternal</code> method directly. Instead, we use another
function, <code>pretty</code>, which can be considered the main “API”
for printing, like before. Here’s the type:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ot">pretty ::</span> (<span class="dt">Pretty</span> ast) <span class="ot">=&gt;</span> ast <span class="dt">NodeInfo</span> <span class="ot">-&gt;</span> <span class="dt">Printer</span> ()</span></code></pre></div>
<p>We’ll look at its implementation in a moment. Here is an example
instance of <code>Pretty</code>:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Pretty</span> <span class="dt">ClassDecl</span> <span class="kw">where</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>  prettyInternal x <span class="ot">=</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">case</span> x <span class="kw">of</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>      <span class="dt">ClsTyDef</span> _ this that <span class="ot">-&gt;</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">do</span> write <span class="st">&quot;type &quot;</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>           pretty this</span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>           write <span class="st">&quot; = &quot;</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>           pretty that</span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>      …</span></code></pre></div>
<p>See how <code>pretty this</code> and <code>pretty that</code> are
used for recursing instead of <code>prettyInternal</code>? This approach
is used for <a
href="http://chrisdone.github.io/hindent/HIndent-Pretty.html#g:1">all
instances</a>.</p>
<p>Now let’s see what that affords us:</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="ot">pretty ::</span> (<span class="dt">Pretty</span> ast) <span class="ot">=&gt;</span> ast <span class="dt">NodeInfo</span> <span class="ot">-&gt;</span> <span class="dt">Printer</span> ()</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>pretty a <span class="ot">=</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">do</span> st <span class="ot">&lt;-</span> get</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>     <span class="kw">case</span> st <span class="kw">of</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>       <span class="dt">PrintState</span>{psExtenders <span class="ot">=</span> es,psUserState <span class="ot">=</span> s} <span class="ot">-&gt;</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>         <span class="kw">do</span> <span class="kw">case</span> listToMaybe (mapMaybe (makePrinter s) es) <span class="kw">of</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>              <span class="dt">Just</span> m <span class="ot">-&gt;</span> m</span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>              <span class="dt">Nothing</span> <span class="ot">-&gt;</span> prettyNoExt a</span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>            printComments a</span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">where</span> makePrinter s (<span class="dt">Extender</span> f) <span class="ot">=</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a>          <span class="kw">case</span> cast a <span class="kw">of</span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a>            <span class="dt">Just</span> v <span class="ot">-&gt;</span> <span class="dt">Just</span> (f s v)</span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a>            <span class="dt">Nothing</span> <span class="ot">-&gt;</span> <span class="dt">Nothing</span></span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true" tabindex="-1"></a>        makePrinter s (<span class="dt">CatchAll</span> f) <span class="ot">=</span> (f s a)</span></code></pre></div>
<p>In this function, we’re grabbing our (mentioned earlier) list of
<code>[Extender s]</code> values from <code>psExtenders</code> and then
looking up to see if any of the types match. To clarify, here is the
<code>Extender</code> type:</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Extender</span> s <span class="kw">where</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Extender</span><span class="ot"> ::</span> <span class="kw">forall</span> s a<span class="op">.</span> (<span class="dt">Typeable</span> a) <span class="ot">=&gt;</span> (s <span class="ot">-&gt;</span> a <span class="ot">-&gt;</span> <span class="dt">Printer</span> ())</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>           <span class="ot">-&gt;</span> <span class="dt">Extender</span> s</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">CatchAll</span><span class="ot"> ::</span> <span class="kw">forall</span> s<span class="op">.</span> (<span class="kw">forall</span> a<span class="op">.</span> <span class="dt">Typeable</span> a <span class="ot">=&gt;</span> s <span class="ot">-&gt;</span> a <span class="ot">-&gt;</span> <span class="dt">Maybe</span> (<span class="dt">Printer</span> ()))</span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>           <span class="ot">-&gt;</span> <span class="dt">Extender</span> s</span></code></pre></div>
<p>Both constructors are rank-n. Both accept the current state as an
argument and the current node. The <code>Extender</code> constructor is
Prismesque. It’s existential, and lets you say “I want things of this
type”. The <code>CatchAll</code> will just accept anything.</p>
<p>All that adds up to me being able to do something like this. Here’s a
demo style:</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>demo <span class="ot">=</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Style</span> {styleName <span class="ot">=</span> <span class="st">&quot;demo&quot;</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>        ,styleAuthor <span class="ot">=</span> <span class="st">&quot;Chris Done&quot;</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>        ,styleDescription <span class="ot">=</span> <span class="st">&quot;Demo for hindent.&quot;</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>        ,styleInitialState <span class="ot">=</span> ()</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>        ,styleExtenders <span class="ot">=</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>           [<span class="dt">Extender</span> (\_ x <span class="ot">-&gt;</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">case</span> x <span class="kw">of</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>                          <span class="dt">InfixApp</span> _ a op b <span class="ot">-&gt;</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>                            <span class="kw">do</span> pretty a</span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a>                               pretty op</span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a>                               pretty b</span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a>                          _ <span class="ot">-&gt;</span> prettyNoExt x)]</span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true" tabindex="-1"></a>        ,styleDefConfig <span class="ot">=</span> def}</span></code></pre></div>
<p>(The <code>prettyNoExt</code> is a publicly exposed version of the
(private) method <code>prettyInternal</code>.)</p>
<p>Now let’s test the <code>fundamental</code> style versus our
<code>demo</code> style:</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> test fundamental <span class="st">&quot;x = foo (a * b) + what&quot;</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>x <span class="ot">=</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>  foo</span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>    (a <span class="op">*</span> b) <span class="op">+</span> what</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> test demo <span class="st">&quot;x = foo (a * b) + what&quot;</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>x <span class="ot">=</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>  foo</span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>    (a<span class="op">*</span>b)<span class="op">+</span>what</span></code></pre></div>
<p>Viola! We’ve configured how to pretty print infix operators in a few
lines of code.</p>
<p>In practice, there are three styles. Here’s a larger example:</p>
<div class="sourceCode" id="cb11"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>foo <span class="ot">=</span> <span class="kw">do</span> <span class="fu">print</span> <span class="st">&quot;OK, go&quot;</span>; foo (foo bar) <span class="co">-- Yep.</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>          (<span class="kw">if</span> bar <span class="kw">then</span> bob <span class="kw">else</span> pif) (<span class="kw">case</span> mu <span class="co">{- cool -}</span> zot <span class="kw">of</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>            <span class="dt">Just</span> x <span class="ot">-&gt;</span> <span class="fu">return</span> ();</span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>            <span class="dt">Nothing</span> <span class="ot">-&gt;</span> <span class="kw">do</span> <span class="fu">putStrLn</span> <span class="st">&quot;yay&quot;</span>; <span class="fu">return</span> (<span class="dv">1</span>,<span class="dv">2</span>)) bill <span class="co">-- Etc</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">where</span> potato <span class="dt">Cakes</span> {} <span class="ot">=</span> <span class="dv">2</span> <span class="op">*</span> x foo <span class="op">*</span> bar <span class="op">/</span> <span class="dv">5</span></span></code></pre></div>
<p>Fundamental style:</p>
<div class="sourceCode" id="cb12"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>foo <span class="ot">=</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">do</span> <span class="fu">print</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>       <span class="st">&quot;OK, go&quot;</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>     foo</span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>       (foo</span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>          bar)</span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a>       (<span class="kw">if</span> bar</span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a>           <span class="kw">then</span> bob</span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>           <span class="kw">else</span> pif)</span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a>       (<span class="kw">case</span> mu <span class="co">{- cool -}</span></span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a>               zot <span class="kw">of</span></span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true" tabindex="-1"></a>          <span class="dt">Just</span> x <span class="ot">-&gt;</span></span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true" tabindex="-1"></a>            <span class="fu">return</span></span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true" tabindex="-1"></a>              ()</span>
<span id="cb12-15"><a href="#cb12-15" aria-hidden="true" tabindex="-1"></a>          <span class="dt">Nothing</span> <span class="ot">-&gt;</span></span>
<span id="cb12-16"><a href="#cb12-16" aria-hidden="true" tabindex="-1"></a>            <span class="kw">do</span> <span class="fu">putStrLn</span></span>
<span id="cb12-17"><a href="#cb12-17" aria-hidden="true" tabindex="-1"></a>                 <span class="st">&quot;yay&quot;</span></span>
<span id="cb12-18"><a href="#cb12-18" aria-hidden="true" tabindex="-1"></a>               <span class="fu">return</span></span>
<span id="cb12-19"><a href="#cb12-19" aria-hidden="true" tabindex="-1"></a>                 (<span class="dv">1</span>,<span class="dv">2</span>))</span>
<span id="cb12-20"><a href="#cb12-20" aria-hidden="true" tabindex="-1"></a>       bill <span class="co">-- Etc</span></span>
<span id="cb12-21"><a href="#cb12-21" aria-hidden="true" tabindex="-1"></a>  <span class="kw">where</span> potato <span class="dt">Cakes</span>{} <span class="ot">=</span></span>
<span id="cb12-22"><a href="#cb12-22" aria-hidden="true" tabindex="-1"></a>          <span class="dv">2</span> <span class="op">*</span> x</span>
<span id="cb12-23"><a href="#cb12-23" aria-hidden="true" tabindex="-1"></a>                foo <span class="op">*</span> bar <span class="op">/</span> <span class="dv">5</span></span></code></pre></div>
<p>Johan Tibell’s style (which I’ve only started implementing, there’re
some things I need to clarify):</p>
<div class="sourceCode" id="cb13"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a>foo <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>    <span class="fu">print</span> <span class="st">&quot;OK, go&quot;</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>    foo</span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>        (foo bar)</span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>        (<span class="kw">if</span> bar</span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>             <span class="kw">then</span> bob</span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>             <span class="kw">else</span> pif)</span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>        (<span class="kw">case</span> mu <span class="co">{- cool -}</span> zot <span class="kw">of</span></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>             <span class="dt">Just</span> x <span class="ot">-&gt;</span></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>                 <span class="fu">return</span> ()</span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a>             <span class="dt">Nothing</span> <span class="ot">-&gt;</span> <span class="kw">do</span></span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a>                 <span class="fu">putStrLn</span> <span class="st">&quot;yay&quot;</span></span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a>                 <span class="fu">return</span> (<span class="dv">1</span>, <span class="dv">2</span>))</span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a>        bill <span class="co">-- Etc</span></span>
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a>  <span class="kw">where</span></span>
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a>    potato <span class="dt">Cakes</span>{} <span class="ot">=</span></span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true" tabindex="-1"></a>        <span class="dv">2</span> <span class="op">*</span> x foo <span class="op">*</span> bar <span class="op">/</span> <span class="dv">5</span></span></code></pre></div>
<p>My style (pretty much complete):</p>
<div class="sourceCode" id="cb14"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a>foo <span class="ot">=</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">do</span> <span class="fu">print</span> <span class="st">&quot;OK, go&quot;</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>     foo (foo bar)</span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>         (<span class="kw">if</span> bar</span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>             <span class="kw">then</span> bob</span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>             <span class="kw">else</span> pif)</span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a>         (<span class="kw">case</span> mu <span class="co">{- cool -}</span> zot <span class="kw">of</span></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a>            <span class="dt">Just</span> x <span class="ot">-&gt;</span> <span class="fu">return</span> ()</span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a>            <span class="dt">Nothing</span> <span class="ot">-&gt;</span></span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a>              <span class="kw">do</span> <span class="fu">putStrLn</span> <span class="st">&quot;yay&quot;</span></span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a>                 <span class="fu">return</span> (<span class="dv">1</span>,<span class="dv">2</span>))</span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a>         bill <span class="co">-- Etc</span></span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">where</span> potato <span class="dt">Cakes</span>{} <span class="ot">=</span> <span class="dv">2</span> <span class="op">*</span> x foo <span class="op">*</span> bar <span class="op">/</span> <span class="dv">5</span></span></code></pre></div>
<p>The styles are part of the <a
href="http://chrisdone.github.io/hindent/">module hierarchy of the
package</a>.</p>
<h2 id="write-your-own-style">Write your own style!</h2>
<p>I welcome anyone to write their own style. All styles are based upon
the fundamental style, which should never change, by extending it. You
can base yours off of another style, or start from scratch. While you
can keep your style locally, like your XMonad configuration, it’s
encouraged to contribute your style as a module.</p>
<p>My style and Johan’s are quite different. But yours may be similar
with small tweaks. Another distinctly different style is Simon Peyton
Jones’s with explicit braces. This is a style you can implement if you
want it.</p>
<p>See <a
href="https://github.com/chrisdone/hindent#contributing-your-own-printer-style">the
contributing section</a> of the README for more info.</p>
<h2 id="preserving-meaning">Preserving meaning</h2>
<p>A recommendation is to preserve the meaning of the code. Don’t make
AST changes. Like removing parentheses, changing $ into parens, moving
lets into wheres, etc. You can do it, but the results might surprise
you.</p>
<h2 id="editing-advantages">Editing advantages</h2>
<p>Having implemented <a
href="https://github.com/chrisdone/hindent#emacs">Emacs support</a>, I
have been using this for a few weeks on my own code. It’s amazing. I’ve
all but stopped manually making style changes. I just write code and
then hit <code>C-c i</code> and it almost always does exactly what I
want.</p>
<p>It can’t always do what I want. It has simple, predictable
heuristics. But even when it doesn’t do what I want, I’ve so far been
okay with the results. The advantages vastly outweigh that.</p>
<h2 id="remaining-problems">Remaining problems</h2>
<p>I need to write a test suite for the fundamental style (and maybe the
others). This isn’t hard, it’s just a bit laborious so I haven’t gotten
round to it yet.</p>
<p>There’re some parts of the AST I haven’t finished filling out. You
can <a
href="https://github.com/chrisdone/hindent/blob/master/src/HIndent/Pretty.hs">see
them</a> which are marked by FIXME’s. This just means if you try to
format a node type it doesn’t know how to print, you’ll get a message
saying so. Your code won’t be touched.</p>
<p>Comment re-insertion is a little bit of a challenge. I have a decent
implementation that generally preserves comments well. There’re some
corner cases that I’ve noticed, but I’m confident I have the right
change to make to clear that up.</p>
<p>The fundamental printer is fast. My personal <code>ChrisDone</code>
style is slower, due to its heuristics of deciding when to layout a
certain way. It took 6s to layout a complex and large declaration. I
updated my style and brought it down to 2s. That’s okay for now. There
are always speed tricks that can be done.</p>
<p>There are of course issues like whether HSE can parse your code,
whether you have #ifdef CPP pragmas in your code, and things like that.
That’s just part of the general problem space of tools like this.</p>
<h2 id="remaining-ideas">Remaining ideas</h2>
<p>Currently you can only reformat a declaration. I don’t yet trust
(any) Haskell printer with my whole file. I invoke it on a
per-declaration basis and I see the result. That’s good for me at the
moment. But in the future I might extend it to support whole
modules.</p>
<p>Implement some operator-specific layouts. There are some operators
that can really only be laid out in a certain way. Control.Applicative
operators spring to mind:</p>
<div class="sourceCode" id="cb15"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Foo</span> <span class="op">&lt;$&gt;</span> foo</span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>    <span class="op">&lt;*&gt;</span> bar</span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">&lt;*&gt;</span> mu</span></code></pre></div>
<p>This can easily be handled as part of a style. Other considerations
might be strings of lens operators. I’ve noticed that people tend not to
put spaces around them, like:<a href="#fn4" class="footnote-ref"
id="fnref4" role="doc-noteref"><sup>4</sup></a></p>
<div class="sourceCode" id="cb16"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a>foo<span class="op">^.</span>bar<span class="op">.^</span>mu<span class="op">.~</span>blah</span></code></pre></div>
<p>There’s also alignment, which is another possibility and easily
implemented. The challenge will be deciding when alignment will look
good versus making the code too wide and whitespacey. In my own style I
personally haven’t implemented any alignment as it’s not that important
to me, but I might one day.</p>
<h2 id="summary">Summary</h2>
<p>Hopefully I’ve motivated the case that style is important, that
formalizing style is important, and that automating it is practical and
something we should solve and then move on, redirect our energy that was
wasted on manually laying things out and debating.</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Granted, this isn’t a technical
consideration. But it’s a real one.<a href="#fnref1"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p>Both of these are referring to
conventions other than simple layout, but I don’t think that detracts
the point.<a href="#fnref2" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn3" role="doc-endnote"><p>Both of these are referring to
conventions other than simple layout, but I don’t think that detracts
the point.<a href="#fnref3" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn4" role="doc-endnote"><p>I don’t know lens’s operators so that
might not be real code, but the point is that could be a style to
implement.<a href="#fnref4" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2014-09-20 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sat, 20 Sep 2014 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Formatting in Haskell]]></title><link>https://chrisdone.com/posts/formatting</link><guid>https://chrisdone.com/posts/formatting</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Formatting in Haskell</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Formatting in Haskell</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>This post is about the <a
href="http://hackage.haskell.org/package/formatting">formatting</a>
package.</p>
<h2 id="whats-wrong-with-printf">What’s wrong with printf?</h2>
<p>The <code>Text.Printf</code> module is problematic simply because
it’s not type-safe:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="kw">import</span> <span class="dt">Text.Printf</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> printf <span class="st">&quot;&quot;</span> <span class="dv">2</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="op">***</span> <span class="dt">Exception</span><span class="op">:</span> printf<span class="op">:</span> formatting string ended prematurely</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> printf <span class="st">&quot;%s&quot;</span> <span class="dv">2</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="op">***</span> <span class="dt">Exception</span><span class="op">:</span> printf<span class="op">:</span> bad formatting char <span class="ch">&#39;s&#39;</span></span></code></pre></div>
<p>And it’s not extensible in the argument type. The <a
href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Text-Printf.html#t:PrintfType">PrintfType</a>
class does not export its methods.</p>
<p>And it’s not extensible in the formatting. You can’t add a “%K”
syntax to it to print a value in Kelvins, for example.</p>
<p>And it’s implicit. You can’t just use your normal API searching
facilities to search how to print a <code>Day</code>.</p>
<h2 id="holy-moly">Holy Moly!</h2>
<p>A while ago I was inspired by the <a
href="http://hackage.haskell.org/package/HoleyMonoid">HoleyMonoid</a>
package to use that mechanism to make a general replacement for <a
href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Text-Printf.html"><code>printf</code></a>.</p>
<p>It’s a continuation-based way of building up monoidal functions by
composition with the ability to insert constants in-between.
Example:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span> holey <span class="ot">=</span> now <span class="st">&quot;x = &quot;</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>          <span class="op">.</span> later <span class="fu">show</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>          <span class="op">.</span> now <span class="st">&quot;, y = &quot;</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>          <span class="op">.</span> later <span class="fu">show</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> run holey <span class="dv">3</span> <span class="dv">5</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;x = 3, y = 5&quot;</span></span></code></pre></div>
<p>The <code>now</code> function inserts a monoidal value directly into
the composition. So</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>run (now x <span class="op">.</span> now y)</span></code></pre></div>
<p>is equivalent to</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>x <span class="op">&lt;&gt;</span> y</span></code></pre></div>
<p>And</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>run (later <span class="fu">show</span> <span class="op">.</span> now x <span class="op">.</span> later <span class="fu">show</span> <span class="op">.</span> now y)</span></code></pre></div>
<p>is equivalent to</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>\a b <span class="ot">-&gt;</span> <span class="fu">show</span> a <span class="op">&lt;&gt;</span> x <span class="op">&lt;&gt;</span> <span class="fu">show</span> b <span class="op">&lt;&gt;</span> y</span></code></pre></div>
<h2 id="the-formatting-package">The Formatting package</h2>
<p>The package is available on Hackage as <a
href="http://hackage.haskell.org/package/formatting">formatting</a>.</p>
<h3 id="comparison-with-other-formatters">Comparison with other
formatters</h3>
<p>Example:</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>format (<span class="st">&quot;Person&#39;s name is &quot;</span> <span class="op">%</span> text <span class="op">%</span>  <span class="st">&quot;, age is &quot;</span> <span class="op">%</span> hex) <span class="st">&quot;Dave&quot;</span> <span class="dv">54</span></span></code></pre></div>
<p>or with short-names:</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>format (<span class="st">&quot;Person&#39;s name is &quot;</span> <span class="op">%</span> t <span class="op">%</span> <span class="st">&quot;, age is &quot;</span> <span class="op">%</span> x) <span class="st">&quot;Dave&quot;</span> <span class="dv">54</span></span></code></pre></div>
<p>Similar to C’s <code>printf</code>:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>printf<span class="op">(</span><span class="st">&quot;Person&#39;s name is %s, age is %x&quot;</span><span class="op">,</span><span class="st">&quot;Dave&quot;</span><span class="op">,</span><span class="dv">54</span><span class="op">);</span></span></code></pre></div>
<p>and Common Lisp’s <code>FORMAT</code>:</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode lisp"><code class="sourceCode commonlisp"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>(<span class="kw">format</span> <span class="kw">nil</span> <span class="st">&quot;Person&#39;s name is ~a, age is ~x&quot;</span> <span class="st">&quot;Dave&quot;</span> <span class="dv">54</span>)</span></code></pre></div>
<h3 id="the-holey-type">The Holey type</h3>
<div class="sourceCode" id="cb11"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">HoleyT</span> r a m <span class="ot">=</span> <span class="dt">Holey</span> {<span class="ot"> runHM ::</span> (m <span class="ot">-&gt;</span> r) <span class="ot">-&gt;</span> a }</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Holey</span> m r a <span class="ot">=</span> <span class="dt">HoleyT</span> r a m</span></code></pre></div>
<p>This is my version of the <code>HoleyMonoid</code>. To make this into
a useful package I changed a few things.</p>
<p>The <code>Category</code> instance implied a name conflict burden
with <code>(.)</code>, so I changed that to <code>(%)</code>:</p>
<div class="sourceCode" id="cb12"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="ot">(%) ::</span> <span class="dt">Monoid</span> n <span class="ot">=&gt;</span> <span class="dt">Holey</span> n b c <span class="ot">-&gt;</span> <span class="dt">Holey</span> n b1 b <span class="ot">-&gt;</span> <span class="dt">Holey</span> n b1 c</span></code></pre></div>
<p>Rather than have the name-conflicting <code>map</code> function, I
flipped the type arguments of the type and made it an instance of
<code>Functor</code>.</p>
<h3 id="printers">Printers</h3>
<p>There is an array of top-level printing functions for various output
types:</p>
<div class="sourceCode" id="cb13"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- | Run the formatter and return a lazy &#39;Text&#39; value.</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="ot">format ::</span> <span class="dt">Holey</span> <span class="dt">Builder</span> <span class="dt">Text</span> a <span class="ot">-&gt;</span> a</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a><span class="co">-- | Run the formatter and return a strict &#39;S.Text&#39; value.</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a><span class="ot">sformat ::</span> <span class="dt">Holey</span> <span class="dt">Builder</span> <span class="dt">S.Text</span> a <span class="ot">-&gt;</span> a</span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a><span class="co">-- | Run the formatter and return a &#39;Builder&#39; value.</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a><span class="ot">bprint ::</span> <span class="dt">Holey</span> <span class="dt">Builder</span> <span class="dt">Builder</span> a <span class="ot">-&gt;</span> a</span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a><span class="co">-- | Run the formatter and print out the text to stdout.</span></span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a><span class="ot">fprint ::</span> <span class="dt">Holey</span> <span class="dt">Builder</span> (<span class="dt">IO</span> ()) a <span class="ot">-&gt;</span> a</span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a><span class="co">-- | Run the formatter and put the output onto the given &#39;Handle&#39;.</span></span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a><span class="ot">hprint ::</span> <span class="dt">Handle</span> <span class="ot">-&gt;</span> <span class="dt">Holey</span> <span class="dt">Builder</span> (<span class="dt">IO</span> ()) a <span class="ot">-&gt;</span> a</span></code></pre></div>
<p>All the combinators work on a lazy text <a
href="http://hackage.haskell.org/package/text-1.1.1.3/docs/Data-Text-Lazy-Builder.html">Builder</a>
which has good appending complexity and can output to a handle in
chunks.</p>
<h3 id="the-format-type">The Format type</h3>
<p>There is a short-hand type for any formatter:</p>
<div class="sourceCode" id="cb14"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Format</span> a <span class="ot">=</span> <span class="kw">forall</span> r<span class="op">.</span> <span class="dt">Holey</span> <span class="dt">Builder</span> r (a <span class="ot">-&gt;</span> r)</span></code></pre></div>
<p>All formatters are written in terms of <code>now</code> or
<code>later</code>.</p>
<h3 id="formatters">Formatters</h3>
<p>There is a standard set of formatters in <a
href="http://hackage.haskell.org/package/formatting-5.2/docs/Formatting-Formatters.html">Formatting.Formatters</a>,
for example:</p>
<div class="sourceCode" id="cb15"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="ot">text ::</span> <span class="dt">Format</span> <span class="dt">Text</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a><span class="ot">int ::</span> <span class="dt">Integral</span> a <span class="ot">=&gt;</span> <span class="dt">Format</span> a</span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a><span class="ot">sci ::</span> <span class="dt">Format</span> <span class="dt">Scientific</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a><span class="ot">hex ::</span> <span class="dt">Integral</span> a <span class="ot">=&gt;</span> <span class="dt">Format</span> a</span></code></pre></div>
<p>Finally, there is a general <code>build</code> function that will
build anything that is an instance of the <code>Build</code> class from
the <code>text-format</code> package:</p>
<div class="sourceCode" id="cb16"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="ot">build ::</span> <span class="dt">Buildable</span> a <span class="ot">=&gt;</span> <span class="dt">Format</span> a</span></code></pre></div>
<p>For which there are a bunch of instances. See <a
href="https://github.com/chrisdone/formatting#hello-world-texts">the
README</a> for a full set of examples.</p>
<h3 id="composing-formatters">Composing formatters</h3>
<p><code>%.</code> is like <code>%</code> but feeds one formatter into
another:</p>
<div class="sourceCode" id="cb17"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> format (left <span class="dv">2</span> <span class="ch">&#39;0&#39;</span> <span class="op">%.</span> hex) <span class="dv">10</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;0a&quot;</span></span></code></pre></div>
<h2 id="extension">Extension</h2>
<p>You can include things verbatim in the formatter:</p>
<div class="sourceCode" id="cb18"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> format (now <span class="st">&quot;This is printed now.&quot;</span>)</span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;This is printed now.&quot;</span></span></code></pre></div>
<p>Although with <code>OverloadedStrings</code> you can just use string
literals:</p>
<div class="sourceCode" id="cb19"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> format <span class="st">&quot;This is printed now.&quot;</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;This is printed now.&quot;</span></span></code></pre></div>
<p>You can handle things later which makes the formatter accept
arguments:</p>
<div class="sourceCode" id="cb20"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> format (later (<span class="fu">const</span> <span class="st">&quot;This is printed later.&quot;</span>)) ()</span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;This is printed later.&quot;</span></span></code></pre></div>
<p>The type of the function passed to <code>later</code> should return
an instance of <code>Monoid</code>.</p>
<div class="sourceCode" id="cb21"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="ot">later ::</span> (a <span class="ot">-&gt;</span> m) <span class="ot">-&gt;</span> <span class="dt">Holey</span> m r (a <span class="ot">-&gt;</span> r)</span></code></pre></div>
<p>The function you format with (<code>format</code>,
<code>bprint</code>, etc.) will determine the monoid of choice. In the
case of this library, the top-level formating functions expect you to
build a text <code>Builder</code>:</p>
<div class="sourceCode" id="cb22"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="ot">format ::</span> <span class="dt">Holey</span> <span class="dt">Builder</span> <span class="dt">Text</span> a <span class="ot">-&gt;</span> a</span></code></pre></div>
<p>Because builders are efficient generators.</p>
<p>So in this case we will be expected to produce Builders from
arguments:</p>
<div class="sourceCode" id="cb23"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a>format <span class="op">.</span><span class="ot"> later ::</span> (a <span class="ot">-&gt;</span> <span class="dt">Builder</span>) <span class="ot">-&gt;</span> a <span class="ot">-&gt;</span> <span class="dt">Text</span></span></code></pre></div>
<p>To do that for common types you can just re-use the formatting
library and use bprint:</p>
<div class="sourceCode" id="cb24"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a> <span class="op">&gt;</span> <span class="op">:</span>t bprint</span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a><span class="ot">bprint ::</span> <span class="dt">Holey</span> <span class="dt">Builder</span> <span class="dt">Builder</span> a <span class="ot">-&gt;</span> a</span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> <span class="op">:</span>t bprint int <span class="dv">23</span></span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a>bprint int <span class="dv">23</span><span class="ot"> ::</span> <span class="dt">Builder</span></span></code></pre></div>
<p>Coming back to <code>later</code>, we can now use it to build our own
printer combinators:</p>
<div class="sourceCode" id="cb25"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> <span class="kw">let</span> mint <span class="ot">=</span> later (<span class="fu">maybe</span> <span class="st">&quot;&quot;</span> (bprint int))</span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> <span class="op">:</span>t mint</span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a><span class="ot">mint ::</span> <span class="dt">Holey</span> <span class="dt">Builder</span> r (<span class="dt">Maybe</span> <span class="dt">Integer</span> <span class="ot">-&gt;</span> r)</span></code></pre></div>
<p>Now <code>mint</code> is a formatter to show
<code>Maybe Integer</code>:</p>
<div class="sourceCode" id="cb26"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> format mint (readMaybe <span class="st">&quot;23&quot;</span>)</span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;23&quot;</span></span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> format mint (readMaybe <span class="st">&quot;foo&quot;</span>)</span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;&quot;</span></span></code></pre></div>
<p>Although a better, more general combinator might be:</p>
<div class="sourceCode" id="cb27"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> <span class="kw">let</span> mfmt x f <span class="ot">=</span> later (<span class="fu">maybe</span> x (bprint f))</span></code></pre></div>
<p>Now you can use it to maybe format things:</p>
<div class="sourceCode" id="cb28"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> format (mfmt <span class="st">&quot;Nope!&quot;</span> int) (readMaybe <span class="st">&quot;foo&quot;</span>)</span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;Nope!&quot;</span></span></code></pre></div>
<h2 id="retrospective">Retrospective</h2>
<p>I’ve been using <code>formatting</code> in a bunch of projects since
writing it. Happily, its API has been stable since releasing with some
additions.</p>
<p>It has the same advantages as <code>Parsec</code>. It’s a
combinator-based mini-language with all the same benefits.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2014-09-20 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sat, 20 Sep 2014 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Teaching: A good (and bad) example]]></title><link>https://chrisdone.com/posts/teaching</link><guid>https://chrisdone.com/posts/teaching</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Teaching: A good (and bad) example</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Teaching: A good (and bad) example</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Rather than write a bunch of prose about how I think teaching should
be done, this time I’ll simply comment an existing example. Needless to
say, I am a proponent of <a
href="http://en.wikipedia.org/wiki/Socratic_method">the Socratic
method</a>. As I begin more work in the area of education, I’ll refer
back to this page.</p>
<p>One day, a newbie asked on an IRC channel a Haskell question. Here is
a highly editorialized and commentaried version of the conversation,
correcting typos and patching out the names. I tried to also group
conversations so they’re a bit less interleaved.</p>
<p>It doesn’t really matter who is who, but I wanted to include a real
log to show that there are real examples of this all the time. It
demonstrates some points about teaching that I think are important. I’ve
used names for some philosophers I admire. There isn’t (really) any
meaning to the assignments.</p>
<h1 id="the-dialogue">The Dialogue</h1>
<p>The play starts out with an unknown person joining the channel and
asking for help:</p>
<blockquote>
<ul>
<li><strong>Huizi</strong>: Hey guys, quick question for you. I am
working on expanding my Haskell skills by doing some challenges at
https://www.hackerrank.com, and I am having issues with one thing that I
think has got to be much easier than I am making it.</li>
<li><strong>Huizi</strong>: Reading and parsing <code>STDIN</code>.</li>
</ul>
</blockquote>
<p>The canvas is prepared. It’s not clear what exactly they are having
trouble with. What’s the first thing you should do? Ask them
questions.</p>
<blockquote>
<ul>
<li><strong>Socrates</strong>: Do you want to avoid direct
spoilers?</li>
<li><strong>Aristophanes</strong>: Huizi: Sure, can you give a specific
example of something you’d like to do?</li>
</ul>
</blockquote>
<p>Questions begin. This is a good start.</p>
<blockquote>
<ul>
<li><strong>Huizi</strong>: So, say I am expecting a string of
<code>"2 3"</code>, how would I convert that to a
<code>[Int]</code>?</li>
</ul>
</blockquote>
<p>A very specific, easy to investigate question is proposed. What’s the
best approach to proceed? First, establish the person’s experience.</p>
<blockquote>
<ul>
<li><strong>Aristophanes</strong>: <code>map read . lines</code></li>
<li><strong>Aristophanes</strong>: Err.</li>
<li><strong>Laozi</strong>:
<code>map read . words &lt;$&gt; readLine</code></li>
<li><strong>Confucius</strong>: You mean <code>words</code>.</li>
<li><strong>Confucius</strong>: And <code>getLine</code>, not
<code>readLine</code>.</li>
<li><strong>Socrates</strong>: Huizi, scratch that question about direct
spoilers. The answer’s been given verbatim.</li>
</ul>
</blockquote>
<p>Sadly, the response is not helpful. It is unempathic, presumptuous
and muddled. Naturally, the learner is confused by this noise.</p>
<blockquote>
<ul>
<li><strong>Huizi</strong>: What is the <code>.</code> in there
for?</li>
</ul>
</blockquote>
<p>And their struggle continues:</p>
<blockquote>
<ul>
<li><strong>Confucius</strong>: Huizi: Function composition.</li>
<li><strong>Laozi</strong>: <code>:t (.)</code></li>
<li><strong>Minerva</strong>:
<code>(b -&gt; c) -&gt; (a -&gt; b) -&gt; a -&gt; c</code></li>
</ul>
</blockquote>
<p>So far, the poor learner has been subjected to line noise. But it
doesn’t go unnoticed:</p>
<blockquote>
<ul>
<li><strong>Socrates</strong>: Hmm, newbie handling in here isn’t as
awesome as back in 2008. Rather clumsy. [winking]</li>
<li><strong>Socrates</strong>: Huizi, how much Haskell do you know
already?</li>
</ul>
</blockquote>
<p>Amusingly, nor does the criticism, starting a separate
meta-discussion:</p>
<blockquote>
<ul>
<li><strong>Laozi</strong>: Socrates: What exactly is not satisfactory
to you?</li>
<li><strong>Confucius</strong>: Socrates: I doubt this is actually the
puzzle Huizi is trying to solve. [tongue in cheek]</li>
</ul>
</blockquote>
<p>The important reply of the earlier question comes:</p>
<blockquote>
<ul>
<li><strong>Huizi</strong>: I have ran through a lot of sample projects,
involving list manipulation.</li>
<li><strong>Huizi</strong>: So, I would still consider myself a
noob.</li>
</ul>
</blockquote>
<p>In other words, this is a complete Haskell newbie who needs to read
more material, or, if they are to be taught here, it should be done with
care and patience.</p>
<blockquote>
<ul>
<li><strong>Confucius</strong>: Huizi: Another way is to write something
like
<code>main = do xs &lt;- getLine; let ns = map read (words xs); …</code>
use <code>ns</code> here …</li>
</ul>
</blockquote>
<p>Oddly, the spoilering continues. The learner has already stated that
they’re going through exercises. The channel is persisting in trying to
spoil the learning process and it does so clumsily. The meta-discussion
continues:</p>
<blockquote>
<ul>
<li><strong>Socrates</strong>: Laozi, the part where you give a complete
newbie some spoiler code that mixes function composition with
<code>Applicative</code> operators? [wink]</li>
<li><strong>Confucius</strong>: Yeah, if I was going to use
<code>fmap</code>, I’d just write <code>fmap</code> here.</li>
<li><strong>Confucius</strong>: I only ever use <code>&lt;$&gt;</code>
if I’m also using <code>&lt;*&gt;</code>.</li>
</ul>
</blockquote>
<p>The learner expresses bad insights typical of someone unfamiliar with
a topic:</p>
<blockquote>
<ul>
<li><strong>Huizi</strong>: But I can work with the language. Just
anything with reading input or output just feels unnatural in the
language.</li>
<li><strong>Huizi</strong>: But that’s likely because it is unnatural
for functional programming languages.</li>
<li><strong>Confucius</strong>: Huizi: Eh, it’s not so bad, you just
need to get used to it.</li>
</ul>
</blockquote>
<p>A strange selfish approach to teaching is expressed in reply to
criticism in the meta-discussion:</p>
<blockquote>
<ul>
<li><strong>Laozi</strong>: Socrates: They are free to ask for more
help, I don’t like starting off assuming no knowledge, it’s too much
work for me.</li>
<li><strong>Socrates</strong>: Laozi, you make it sound like an
occupation. [smile]</li>
<li><strong>Laozi</strong>: Socrates: 0K starting. [money job joke]</li>
</ul>
</blockquote>
<p>Amusingly, the shoot-first-ask-questions-later practitioner
second-guesses themself:</p>
<blockquote>
<ul>
<li><strong>Laozi</strong>: Also, is it spoiler code? Is the actual task
to parse in some numbers?</li>
<li><strong>Confucius</strong>: Huizi: Have a look at the code that I
wrote.</li>
</ul>
</blockquote>
<p>Incensed by the learner’s bad learner insights, a
pure-functional-vs-state lecture begins:</p>
<blockquote>
<ul>
<li><strong>Aristophanes</strong>: Huizi: It’s only “unnatural” in the
sense that it’s a different approach than imperative languages, and
that’s the approach you already know.</li>
<li><strong>Huizi</strong>: No, its unnatural in the sense that
functional programming languages have this sense of no outside state…
reading from <code>STDIN</code> kind of “breaks” that whole
ideology.</li>
</ul>
</blockquote>
<p>Meanwhile, an interaction with the learner is resumed:</p>
<blockquote>
<ul>
<li><strong>Socrates</strong>: Huizi, are you just going off the reading
material on that challenge site so far?</li>
<li><strong>Nasreddin</strong>: Huizi: FWIW, parsing numbers from
strings is explained on page 400 in Real World Haskell:
http://book.realworldhaskell.org/read/</li>
<li><strong>Huizi</strong>: Socrates: No, I was using ‘learnhaskell’
sites.</li>
</ul>
</blockquote>
<p>The lecture continues:</p>
<blockquote>
<ul>
<li><strong>Confucius</strong>: Huizi: A do-block can be used to glue a
bunch of IO actions together into a larger one. Inside a do-block,
<code>v &lt;- x</code> means “execute the action <code>x</code>, and
call its result v”. If <code>x</code> has type <code>IO t</code>, then
<code>v</code> will have type <code>t</code>.</li>
<li><strong>Aristophanes</strong>: Huizi: The whole “no sense of outside
state” thing is basically a myth.</li>
<li><strong>Confucius</strong>: Huizi: In the end, main will be one of
these IO actions, and will be executed in a compiled Haskell
program.</li>
</ul>
</blockquote>
<p>The learner soldiers on trying to solve their actual problem:</p>
<blockquote>
<ul>
<li><strong>Huizi</strong>: Yeah, I was trying to use <code>read</code>,
I just kept getting errors.</li>
</ul>
</blockquote>
<p>More lecturing:</p>
<blockquote>
<ul>
<li><strong>Confucius</strong>: <code>getLine :: IO String</code> is an
IO action which when executed, will request a line of text from
<code>stdin</code>, and produce that as its result.</li>
</ul>
</blockquote>
<p>Actual interaction with the learner tries to make some headway:</p>
<blockquote>
<ul>
<li><strong>Socrates</strong>: Huizi, what was your use of
<code>read</code> like? You can type small Haskell expressions in here
by prefixing it with “&gt;”.</li>
<li><strong>Socrates</strong>: &gt; <code>1 + 2</code></li>
<li><strong>Minerva</strong>: <code>3</code></li>
</ul>
</blockquote>
<p>Lecture <em>still</em> continues:</p>
<blockquote>
<ul>
<li><strong>Confucius</strong>: Huizi: It’s important to distinguish
execution (of IO actions) from evaluation, which is the process of
reducing expressions to values in order to be able to match them against
patterns.</li>
<li><strong>Confucius</strong>: When people say that Haskell is pure or
referentially transparent or stateless or whatever, they’re talking
about evaluation.</li>
</ul>
</blockquote>
<p>The learner is now trying to diagnose their problem and voicing their
discoveries:</p>
<blockquote>
<ul>
<li><strong>Huizi</strong>: Looks like the main issue I was having is
that I was using <code>splitOn ' '</code>, instead of words.</li>
</ul>
</blockquote>
<p>This is the first obvious clue to a misstep the newbie has made. Can
you see their mistake? If not, you’ll learn something, too. Now the task
is to help them realize it. Meanwhile, a little bit more meta
discussion:</p>
<blockquote>
<ul>
<li><strong>Socrates</strong>: Confucius, does your approach of throwing
stuff at people and seeing what sticks without any feedback normally
work? It seems strange to me.</li>
<li><strong>Confucius</strong>: Socrates: I am hoping for feedback
here.</li>
</ul>
</blockquote>
<p>The learner is starting to reason through the issue more:</p>
<blockquote>
<ul>
<li><strong>Huizi</strong>: <code>splitOn</code> must have a different
output type.</li>
<li><strong>Socrates</strong>: Huizi, what’s the type of
<code>splitOn</code>? Is that from <code>Data.List.Split</code>?</li>
<li><strong>Huizi</strong>: Yeah.</li>
<li><strong>Socrates</strong>: <code>:t splitOn</code> <em>– Does
lambdabot have it in scope?</em></li>
<li><strong>Minerva</strong>:
<code>Eq a =&gt; [a] -&gt; [a] -&gt; [[a]]</code></li>
<li><strong>Socrates</strong>: Aha!</li>
</ul>
</blockquote>
<p>A strange lecture-only perspective is professed, which I’ll address
later:</p>
<blockquote>
<ul>
<li><strong>Confucius</strong>: Socrates: But I figure I might as well
put everything on the table even if I get none.</li>
<li><strong>Confucius</strong>: Huizi: Does that stuff make sense?</li>
</ul>
</blockquote>
<p>Attempting to continue with the issue at hand, a play is made to try
to help the learner see what’s wrong:</p>
<blockquote>
<ul>
<li><strong>Socrates</strong>: Huizi, you can still use
<code>splitOn</code> for this problem (even though <code>words</code>
might be more convenient), can you see the change to make in your
call?</li>
<li><strong>Huizi</strong>: <code>:t words</code></li>
<li><strong>Minerva</strong>: <code>String -&gt; [String]</code></li>
<li><strong>Socrates</strong>: Huizi, check this out:</li>
<li><strong>Socrates</strong>: <code>:t ' '</code></li>
<li><strong>Minerva</strong>: <code>Char</code></li>
<li><strong>Socrates</strong>: <code>:t " "</code></li>
<li><strong>Minerva</strong>: <code>[Char]</code></li>
</ul>
</blockquote>
<p>But the learner’s still confused, but asking questions, which is
good:</p>
<blockquote>
<ul>
<li><strong>Huizi</strong>: So basically I end up with an output of
<code>[[Char]]</code> with words, and <code>[[a]]</code> with
<code>splitOn</code>. Right?</li>
<li><strong>Huizi</strong>: But since the input to <code>splitOn</code>
is from the <code>getLine</code>, does it not consider itself a
<code>[Char]</code> type?</li>
<li><strong>Socrates</strong>: Huizi, that’s right, <code>splitOn</code>
returns a list of lists of anything <code>[a]</code>, <code>words</code>
returns a list of lists of characters <code>[Char]</code>.</li>
<li><strong>Nasreddin</strong>: Huizi: <code>splitOn</code> would give
<code>[[Char]]</code> if it was fed <code>[Char]</code></li>
</ul>
</blockquote>
<p>Leading the learner isn’t working yet, so it’s time to show the
issue:</p>
<blockquote>
<ul>
<li><strong>Socrates</strong>: Huizi, it does – I think the
<em>first</em> argument to <code>splitOn</code> is your problem here,
right? Is this the error message you got?</li>
<li><strong>Socrates</strong>:
<code>&gt; splitOn ' ' "hello world"</code></li>
<li><strong>Minerva</strong>: Couldn’t match expected type ‘[Char]’ with
actual type ‘Char’</li>
<li><strong>Confucius</strong>:
<code>&gt; splitOn " " "hello world"</code></li>
<li><strong>Minerva</strong>: <code>["hello","world"]</code></li>
</ul>
</blockquote>
<p>Here comes the epiphany!</p>
<blockquote>
<ul>
<li><strong>Huizi</strong>: Ohhhhhh.</li>
<li><strong>Socrates</strong>: [smile]</li>
<li><strong>Huizi</strong>: I feel silly.</li>
</ul>
</blockquote>
<p>Then they try it out:</p>
<blockquote>
<ul>
<li><strong>Huizi</strong>:
<code>&gt; splitOn "o w" "hello world"</code></li>
<li><strong>Minerva</strong>: <code>["hell","orld"]</code></li>
</ul>
</blockquote>
<p>Now they describe the problem they had with full understanding:</p>
<blockquote>
<ul>
<li><strong>Huizi</strong>: Ok, so I am splitting the list wherever it
finds the sequence in that list.</li>
<li><strong>Socrates</strong>: Yup.</li>
<li><strong>Huizi</strong>:
<code>&gt; splitOn [2,3] [1,2,3,4,5,6]</code></li>
<li><strong>Minerva</strong>: <code>[[1],[4,5,6]]</code></li>
<li><strong>Huizi</strong>: Perfect, thanks guys.</li>
<li><strong>Socrates</strong>: Welcome!</li>
</ul>
</blockquote>
<p>End of conversation.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2014-07-19 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sat, 19 Jul 2014 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[An alternative Haskell home page]]></title><link>https://chrisdone.com/posts/haskell-lang</link><guid>https://chrisdone.com/posts/haskell-lang</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>An alternative Haskell home page</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>An alternative Haskell home page</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<h2 id="update-2020-05-24">Update 2020-05-24</h2>
<p>The web site has since been through various iterations and changes,
therefore I include some screenshots below for posterity (because my
design is much more beautiful than what is now online ;-).</p>
<p><img src="../../images/blog/Screen Shot 2020-05-10 at 12.08.59 PM.png"></p>
<p><img src="../../images/blog/Screen Shot 2020-05-10 at 12.09.04 PM.png"></p>
<p><img src="../../images/blog/Screen Shot 2020-05-10 at 12.09.06 PM.png"></p>
<h2 id="an-alternative-haskell-home-page">An alternative Haskell home
page</h2>
<p>I started a couple months back an alternative home page for Haskell.
It is a work in progress, but as I work on it every so often I push
changes to it.</p>
<h2 id="whats-wrong-with-haskell.org">What’s wrong with
haskell.org?</h2>
<p>haskell.org isn’t doing a satisfactory job for me as a place to
impress people with Haskell and to guide them into using it.</p>
<ul>
<li>Its design is broken or just strangely put together and it’s not
responsive.<a href="#fn1" class="footnote-ref" id="fnref1"
role="doc-noteref"><sup>1</sup></a></li>
<li>There are too many links on one page which indicates indecision
about priorities and a lack of user story or particular target audience.
Who’s this site targeting? Where are they supposed to go next? Is it
answering the right questions?</li>
<li>Also, the uncoordinated effort of the wiki <a
href="http://stackoverflow.com/questions/23848648/text-html-vs-blaze-html">misleads
people</a> and pages begin to bitrot. There are too many to vet.</li>
</ul>
<h2 id="why-not-fix-haskell.org">Why not fix haskell.org?</h2>
<p>The current home page is historically resistant to change,
technologically and socially. My relationship to haskell.org over the
years has been one of stonewalling when requesting access, of slow
replies, and of bike-shedding and nitpicking when proposing designs. A
camel is a horse designed by committee and haskell.org is such a
horse.</p>
<h2 id="so-your-plan-is">So your plan is?</h2>
<p>The plan goes like this:</p>
<ul>
<li>The first part of the plan was to survey existing programming
language web sites.</li>
<li>Decide on an audience.</li>
<li>Decide on a theme.</li>
<li>Decide on user stories.</li>
<li>Implement.</li>
<li>Yay, shiny web site.</li>
</ul>
<h2
id="what-do-all-language-sites-have-and-what-should-they-all-have">What
do all language sites have and what should they all have?</h2>
<p>I looked at the following web sites:</p>
<ul>
<li><a href="http://fsharp.org/">http://fsharp.org/</a></li>
<li><a href="http://ruby-lang.org/">http://ruby-lang.org/</a></li>
<li><a href="https://www.python.org/">https://www.python.org/</a></li>
<li><a
href="http://www.rust-lang.org/">http://www.rust-lang.org/</a></li>
<li><a href="http://ocaml.org/">http://ocaml.org/</a></li>
<li><a href="http://golang.org/">http://golang.org/</a></li>
<li><a href="http://www.perl.org/">http://www.perl.org/</a></li>
<li><a href="http://scala-lang.org/">http://scala-lang.org/</a></li>
<li><a href="http://clojure.org/">http://clojure.org/</a></li>
</ul>
<p>There are good points and bad points for each one, but I came up with
a set of things that are common among all, and a couple additional
points I came up with:</p>
<ul>
<li>A theme</li>
<li>Logo</li>
<li>Menu
<ul>
<li>Download</li>
<li>Community</li>
<li>Documentation</li>
<li>News</li>
</ul></li>
<li>Visual things
<ul>
<li>Opening paragraph</li>
<li>Code sample</li>
<li>Thumbnails of videos</li>
<li>Pictures of community stuff; human beings</li>
<li>Screenshots</li>
<li>Selling points</li>
<li>News</li>
<li>Twitter/feeds</li>
<li>Supporters / sponsoring companies</li>
</ul></li>
<li>Other links
<ul>
<li>Application areas / success stories</li>
<li>Language options (locale; Japanese, German, etc.)</li>
</ul></li>
</ul>
<h2 id="existing-crop-of-language-home-pages">Existing crop of language
home pages</h2>
<p>If you’re interested in my review of each home page, here’s what I
wrote:</p>
<ul>
<li>F#’s is boring, it has no character, features no code samples. But
it does have a bunch of company backing logos.</li>
<li>Ruby’s is among the best. It has character. It has two navigations,
which is bad,<a href="#fn2" class="footnote-ref" id="fnref2"
role="doc-noteref"><sup>2</sup></a> but otherwise it’s perfect.
Otherwise, my only criticism is that it overemphasizes news which most
new people don’t care about and which Rubyists get via other
sources.</li>
<li>Python’s, like Ruby’s, is good. It has character. It has code
samples. But it’s worse than Ruby in that it has four areas of
navigation. The top bar, the second bar, the third call to action
section, and finally the footer. Each of which has a different subset of
total places of interest. Again, it uses space presenting news items.
However, I particularly like the section which shows Web Programming,
GUI Development, etc. and then next to each the library one would use to
accomplish that task. That’s very practical and speaks positively about
the language and community.</li>
<li>OCaml’s is not bad either. It has a deserty theme giving it its own
character. It suffers from link overload, which implies it might’ve been
copying Haskell’s or Python’s home pages.</li>
<li>Go’s home page is notable for its embedded try feature, something
which I’ve wanted Haskell’s home page to have for a long time. It’s also
got a very simple and straight-forward navigation. The logo/mascot is in
there, giving the whole page a bit of fun character, too. While not much
to look at, unresponsive to device, clearly written by a pragmatist
systems person, it has a lot going for it and is in my mind among the
best I’ve looked at.</li>
<li>For Perl’s homepage, I’ll echo similar complaints as before. Link
overload. It’s a rather lazy way to make a home page. Let’s throw in as
many links as we can and hope people read it all and by chance find what
they’re looking for. Oh and to fill out the page, let’s add recent
uploads (who cares?) and news items (again, who cares?). Finally, it has
no character whatsoever. It has the awful O’Reilly pen drawing of a
random animal that’s supposed to embody the character of the language,
but is meaningless. I probably dislike this one the most, a close tie
with F#’s.</li>
<li>Scala’s is very trendy and pretty. It’s got a lot of events and
training info which, along with the header mountains, gives it a very
communal and active fresh feel. Again, echoing the praise of Go’s page,
it has very simple navigation. One navigation at the top, and then two
big buttons for the most common tasks. After that, like Python’s home
page, there’s a good review of features of the language that make this
language more interesting than the next language. I give credit to this
page for visual inspiration.</li>
<li>Clojure suffers a little bit from linkitis, too. It has three menus
and then a page full of links. It has zero code samples on the first
page you land on. But it is clean and has a certain character to
it.</li>
</ul>
<p>Generally, I’m not sure why sites bother with search boxes. Unless
they’re implementing code-aware searches, Google will be faster and more
accurate every time. As Joel Spolsky says of his StackOverflow, Google
is the user interface to SO.</p>
<p>Regarding linkitis, I will quote <a
href="http://en.wikipedia.org/wiki/Don&#39;t_Make_Me_Think">Don’t Make
Me Think</a> that a user will happily click three links to narrow down
what they want, than to have to think and search around a page to find
what they want, if they have the patience for it.</p>
<h2 id="the-audience">The audience</h2>
<p>The audience is newbies. People who use Haskell don’t go to
haskell.org. They go to Hackage, or they google search and find wiki
entries, or the GHC manual. A home page shouldn’t cater to Haskellers,
it should cater to would-be Haskellers.</p>
<p>Naysayers for an attractive home page say things like “we don’t want
superficial people joining the community” (as if they could just learn
Haskell on a whim!), but forget that people live insular lives. There
are millions of people out there who’ve never heard of Haskell. If a
random web user stumbles upon it and is taken by the look of it, what
are they going to do with it? Share it. How did you first hear of
Haskell? I was told about it by a friend.</p>
<p>To decide on the kinds of things I want to see on a landing page when
I first look at a language I’m unfamiliar with I ask a bunch of common
questions. I’ve condensed them all in the user stories section.</p>
<h2 id="the-theme">The theme</h2>
<p>I’ve always liked the purple and green of the old Haskell logo. I
don’t know why gray/sky blue ended up being used for the new logo. So I
decided I’d keep that purple theme and made some mockups. Purple is <a
href="http://en.wikipedia.org/wiki/Purple#Vanity.2C_extravagance.2C_individualism">a
cool color</a>.</p>
<h2 id="user-stories">User stories</h2>
<p>The user stories I’ve identified have been encoded in the main
navigation:</p>
<ul>
<li>A user just wants to try Haskell. They scroll to ‘Try it’ and, well,
try it. There can be links to further sites like Try Haskell, School of
Haskell, Code Pad, Lambdabot, services like that.</li>
<li>A user wants to download Haskell. They click ‘Downloads’. What
particular file they want to download doesn’t matter. It could be GHC,
it could be the Haskell Platform, it could be some packages. If they
want to download something, they go to Downloads.</li>
<li>A user wants to interact with/find community. They click
‘Community’. On that page is a list of various community places of
interest, which may itself be expanded with videos and things like
that.</li>
<li>A user wants to get information. They click ‘Documentation’. That
means books, reports, papers, tutorials.</li>
<li>A user wants to catch up with what’s new in general, with Haskell.
They click ‘News’ and there can be an RSS feed available on that page.
Haskell News is mostly suitable to this task.</li>
</ul>
<h2 id="ahoy-ye-olde-mockup">Ahoy, ye olde mockup!</h2>
<p>I synthesized all this together into a comp in Inkscape.</p>
<p>I think it answers the following questions:</p>
<ul>
<li>Any particular brand/logo? [header]</li>
<li>In a few words, what is this thing? [header]</li>
<li>What does it look like? I want to see code immediately.
[header]</li>
<li>Can I try it right now? [try haskell section]</li>
<li>I’m still interested. Is anyone using this thing? [community &amp;
videos, events section]</li>
<li>What are the selling points, over, say, ML or C#? [features
section]</li>
<li>Where do I download stuff/find community/docs/news? [the main menu
at the top]</li>
</ul>
<p>I made a mockup for the subsite, but that’s uninteresting.</p>
<h2 id="implementation">Implementation</h2>
<p>I’ve implemented a starting prototype here at <a
href="http://haskell-lang.org/">haskell-lang.org</a>. At the time of
writing it doesn’t yet fully flesh out all the things planned in the
mockup.</p>
<p>There are a few half-done pages in the navigation, fleshed out just
enough to satisfy my plan and to motivate for further work.</p>
<p>Here’s a quick comparison of the two sites now:</p>
<p>To illustrate, here’re the sites on various devices:</p>
<ul>
<li><a
href="http://ami.responsivedesign.is/?url=http%3A%2F%2Fhaskell.org">haskell.org</a></li>
<li><a
href="http://ami.responsivedesign.is/?url=http%3A%2F%2Fhaskell-lang.org">haskell-lang.org</a></li>
</ul>
<p>I’ve also made a little page to render wiki pages from haskell.org.
There is a simple request sent to haskell.org for <code>/wiki/*</code>
pages, it parses the Wiki syntax with pandoc and renders it to HTML, at
least for the pages that MediaWiki is kind enough to serve. Example: <a
href="http://www.haskell.org/haskellwiki/Handling_errors_in_Haskell">Handling
errors in Haskell</a></p>
<p><a href="/images/archives/2024-haskell-lang-wiki-example.png">Here is
the above wiki page</a> with a cleaned up presentation.</p>
<p>Note that MediaWiki is a bit stunted in the data it exposes for use.
Some pages just aren’t available, others produce invalid XML, etc. This
is why the wiki is not exposed in the navigation.</p>
<p>I’m not sure about exposing the wiki directly, but rather some
selected vetted pages, perhaps.</p>
<h2 id="going-forward">Going forward</h2>
<p>I still have to:</p>
<ul>
<li><del>Fill in the Try support</del></li>
<li><del>The features copy</del></li>
<li>Examples for each of said features</li>
<li><del>A list of video thumbnails to appear under the community banner
(as in the comp)</del></li>
<li>Upcoming/past events</li>
<li>At least 5 examples for the header code</li>
<li><del>Add books &amp; manuals to the Documentation tab</del></li>
</ul>
<p>I’m happy with the look and feel and organization. Now is the matter
of filling it with useful things. That’ll take about a month, by
weekend/spare-time development. Once that’s done, it will be ready to
link to newbies. I’ll have a link to be proud of when people bring up
Haskell.</p>
<p>I could solicit the community for contributions via pull requests. It
depends on people approving of the project and my approach. So if you’re
reading this and you accept my design and organization<a href="#fn3"
class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a> and
would like to contribute content (content pages are written in
markdown), then pull requests to <a
href="http://github.com/haskell-infra/hl">the github repo</a> would be
most handy. I will merge your changes and redeploy with relative
speed.</p>
<p>In particular, content in wanting which is not straight-forward for
me to produce:</p>
<ul>
<li>About 5 examples of concise, short Haskell code which can sit in the
header. Ideally, each example can be clicked and it will take you to a
markdown page under an Examples hierarchy that explains how the code
works.</li>
<li>The features section needs to be filled out with content. I’m not
entirely sure that the headers are decent, but I’m pretty sure they’re a
good start.<a href="#fn4" class="footnote-ref" id="fnref4"
role="doc-noteref"><sup>4</sup></a> Pages for each of those which
contain example code of real problems that are solved are needed.</li>
</ul>
<p>I won’t be able to actively work on this for a few days, but I can do
bits and bobs here and there on the weekend and I always have time to
merge straight-forward changes.</p>
<p>Questions/comments, feel free to email me: <a
href="mailto:blog@chrisdone.com">blog@chrisdone.com</a> Put a note in
the email if you wish to be CC’d with other people in the
discussion.</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>When I open haskell.org on my phone,
I see the tablet-sized layout with tiny text. The layout goes wonky on
the tablet version.<a href="#fnref1" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p>Having two navigations leads to <a
href="http://en.wikipedia.org/wiki/The_Paradox_of_Choice">arbitrary
choice.</a><a href="#fnref2" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn3" role="doc-endnote"><p>That means that you won’t nitpick
design decisions, bike shed about the theme, organization, choice of
picture in the landing page, etc.<a href="#fnref3" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn4" role="doc-endnote"><p>Maybe type-classes and monads might
be of interest because both where pioneered by Haskell and, at least in
their native support, are both peculiar to Haskell.<a href="#fnref4"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2014-05-29 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Thu, 29 May 2014 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Presentations update]]></title><link>https://chrisdone.com/posts/presentations-update</link><guid>https://chrisdone.com/posts/presentations-update</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Presentations update</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Presentations update</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Just a small update. I took 15 mins and updated the haskell-mode
printer a bit so that everything is indented by default, and lists are
expanded as <code>[1,2,…]</code> rather than <code>1:(2:…)</code>.</p>
<p><a href="https://www.youtube.com/watch?v=oJhIvHtflbI">Video
demonstration!</a></p>
<p>Andrew Gibiansky contacted me about getting a front-end added for <a
href="https://github.com/gibiansky/IHaskell">IHaskell</a>, which would
be lovely! I designed the <a
href="https://github.com/chrisdone/present">present</a> package
specifically aimed at working on Emacs or the browser or wherever. So I
sent him back an excessively long email about how to integrate it.</p>
<p>It might also be worth adding to tryhaskell, too. It’d be rather easy
and helpful to newbies.</p>
<p>Also, update to the loeb example:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="op">:</span>present loeb (<span class="fu">map</span> (\i l <span class="ot">-&gt;</span> <span class="dt">Node</span> i (<span class="fu">map</span> (<span class="fu">fmap</span> (<span class="op">+</span><span class="dv">1</span>)) l)) [<span class="dv">1</span><span class="op">..</span><span class="dv">3</span>])</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>[<span class="dt">Node</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>   <span class="dv">1</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>   [<span class="dt">Tree</span> <span class="dt">Integer</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>   ,<span class="dt">Node</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>      <span class="dv">3</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>      [<span class="dt">Node</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>         <span class="dv">3</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>         [<span class="dt">Tree</span> <span class="dt">Integer</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>         ,<span class="dt">Tree</span> <span class="dt">Integer</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>         ,<span class="dt">Node</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>            <span class="dv">6</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>            [<span class="dt">Node</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>               <span class="dv">5</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>               [<span class="dt">Node</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>                  <span class="dv">6</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>                  [<span class="dt">Tree</span> <span class="dt">Integer</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>                  ,[<span class="dt">Tree</span> <span class="dt">Integer</span>]]</span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>               ,[<span class="dt">Tree</span> <span class="dt">Integer</span>]]</span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>            ,[<span class="dt">Tree</span> <span class="dt">Integer</span>]]]</span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>      ,[<span class="dt">Tree</span> <span class="dt">Integer</span>]]</span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>   ,<span class="dt">Tree</span> <span class="dt">Integer</span>]</span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>,<span class="dt">Tree</span> <span class="dt">Integer</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>,<span class="dt">Tree</span> <span class="dt">Integer</span>]</span></code></pre></div>
<p>You can really drill down into those structures!</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2014-04-30 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Wed, 30 Apr 2014 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[The Identity monad trick]]></title><link>https://chrisdone.com/posts/identity-monad</link><guid>https://chrisdone.com/posts/identity-monad</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>The Identity monad trick</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>The Identity monad trick</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p><em><strong>Update:</strong> Got the link! <a
href="http://blog.sigfpe.com/2007/04/trivial-monad.html">The Trivial
Monad</a>. Thanks, John. Naturally, all interesting Haskell things
eventually lead back to Dan Piponi.</em></p>
<p>I heard about this from John Wiegley a while ago, but every time I
recall it, I can’t remember how it goes, so I thought I’d write it down
for myself. I think there’s a paper about it, but I can’t find it.
Hopefully I’m recalling it correctly.</p>
<p>The Identity monad trick: Let’s say I want to expose an API that lets
you work with a data structure. I want you to be able to keep hold of
that data structure and pass it back into my library, and I’ll give it
back to you later and we can go back and forth.</p>
<p><strong>But</strong> I don’t want you to actually <em>give you</em>
the data structure freely so you can go and give it to your friends. So
instead I force you into the Identity monad, via a newtype wrapper that
only <em>I</em> can unpack.</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">Secret</span> a <span class="ot">=</span> <span class="dt">Secret</span> {<span class="ot"> unSecret ::</span> <span class="dt">Identity</span> a }</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">deriving</span> (<span class="dt">Monad</span>,<span class="dt">Functor</span>,<span class="dt">Applicative</span>)</span></code></pre></div>
<p>And I have some function exposing it like:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ot">getSecret ::</span> <span class="dt">Foo</span> <span class="ot">-&gt;</span> <span class="dt">Secret</span> <span class="dt">Text</span></span></code></pre></div>
<p>Here, use that. What can you do with it? You can’t extract the value
out, you can only compose it with more functor or monad stuff:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="fu">fmap</span> (<span class="fu">map</span> T.toUpper) (getSecret foo)</span></code></pre></div>
<p>Or:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">do</span> text <span class="ot">&lt;-</span> getSecret foo</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>   <span class="kw">if</span> <span class="fu">all</span> T.isUpper text</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>      <span class="kw">then</span> <span class="fu">return</span> (T.reverse text)</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>      <span class="kw">else</span> <span class="fu">return</span> text</span></code></pre></div>
<p>Note that the whole type of this expression is
<code>Secret Text</code>. You still don’t have the secret, you’ve got a
computation over it.</p>
<p>You’ve used the value, but it never escaped<a href="#fn1"
class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> the
actual Identity monad. It’s like I’m giving you the value, but I’m also
not giving you the value.</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>As always, there’s a difference
between “secure against your own stupidity” and “secure against
attackers.” For the former, this is satisfied.</p>
<p>For the latter, bottom complicates it, so you should force it in the
IO monad and catch any exceptions e.g.</p>
<p><code>extract :: Secret a -&gt; IO (Maybe a)</code></p>
<p>This prevents people from using</p>
<p><code>(v &gt;&gt;= \a -&gt; error ("The value is " ++ show a))</code></p>
<p>To try to get around it.</p>
<p><code>unsafePerformIO</code> and other non-standard Haskell can get
around it, but if you’re defending against developers, you probably have
control over the environment, so you can just white-list the imports and
extensions and there’s nothing they can do. This is what tryhaskell (via
mueval) does.<a href="#fnref1" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2014-04-29 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Tue, 29 Apr 2014 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[The printer Haskell deserves]]></title><link>https://chrisdone.com/posts/the-printer-haskell-deserves</link><guid>https://chrisdone.com/posts/the-printer-haskell-deserves</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>The printer Haskell deserves</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>The printer Haskell deserves</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Friday night project ahoy!</p>
<h2 id="problem">Problem</h2>
<p>I was working with haskell-names the other day. Its data types are
nice enough, but are rather unweildly to read in the REPL when debugging
and inspecting. This got me thinking about inspection and printers for
Haskell data structures again.</p>
<p>I’ve made several approaches for to haskell-mode in the past.</p>
<ul>
<li>One which requires parsing the output of Show with Haskell and then
printing that to s-expressions for Emacs to consume. This is generally
unreliable and hacky.</li>
<li>Then I settled with making the REPL just syntax highlight the
output. That generally works flawlessly and is an okay solution.</li>
<li>Then I really wanted collapsing support again, so I implemented one
based on Emacs’s awareness of expression boundaries (of ( ) and { } and
” ” etc.). Simple. Kind of reliable.</li>
</ul>
<p>Today I implement yet another one, but this one I like best. I’ve
always wanted to have a Haskell printer that can evaluate on demand,
piece-wise, taking care not to evaluate the whole structure too eagerly.
I should be able to type <code>[1..]</code> into my REPL and not be
spammed by numbers, but rather to expand it at my leisure.</p>
<h2 id="implementation">Implementation</h2>
<p>My plan was to use the <a
href="http://chrisdone/posts/data-typeable">Data.Data API</a> to
traverse data structures breadth-first, display to the user something
like <code>Just …</code> and then allow the user to continue evaluating
on request by clicking the <code>…</code> slot.</p>
<p>I chatted with <a href="https://github.com/mgsloan">Michael Sloan</a>
about it and we came up with a simple experimental design and thought it
would be a nice idea. We hypothesized a nice class-based way to provide
custom presenters for your types, so that e.g. a <code>Diagram</code>
could be rendered as a bitmap inline with the rest of the data
structure, but that needs more thinking about.</p>
<p>I’ve implemented a basic version of it in the <a
href="http://hackage.haskell.org/package/present-0.0.0">present</a>
package (a la “presentations” in <a
href="http://bauhh.dyndns.org:8000/clim-spec/23-1.html#_1125">CLIM</a>)
and implemented a usable front-end for it in Emacs. There’s some
information about the implementation <a
href="https://github.com/chrisdone/present">in the README</a> which you
can read on Github.</p>
<h2 id="result">Result</h2>
<p>Yes! It works. <a href="http://youtu.be/4rcPfZveGZc">Here is a
demonstration video.</a> Concept proven. This is definitely my favourite
way so far. I will probably write a simple algorithm in Emacs to format
things on separate lines, which would make it much easier to read, and I
want to make strings expand to fill the screen width, but no further.
But this is already an improvement.</p>
<p>I’ll trial it for a while, if I end up using it more often than not,
I’ll make the option to make :present implicit for all REPL
evaluations.</p>
<h2 id="example">Example</h2>
<p>For kicks, here’s the output for</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>loeb (<span class="fu">map</span> (\i l <span class="ot">-&gt;</span> <span class="dt">Node</span> i (<span class="fu">map</span> (<span class="fu">fmap</span> (<span class="op">+</span><span class="dv">1</span>)) l)) [<span class="dv">1</span><span class="op">..</span><span class="dv">3</span>])</span></code></pre></div>
<p>Normally you would get:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>[<span class="dt">Node</span> {rootLabel <span class="ot">=</span> <span class="dv">1</span>, subForest <span class="ot">=</span> [<span class="dt">Node</span> {rootLabel <span class="ot">=</span> <span class="dv">2</span>, subForest <span class="ot">=</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a> [<span class="dt">Node</span> {rootLabel <span class="ot">=</span> <span class="dv">3</span>, subForest <span class="ot">=</span> [<span class="dt">Node</span> {rootLabel <span class="ot">=</span> <span class="dv">4</span>, subForest <span class="ot">=</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>  [<span class="dt">Node</span> {rootLabel <span class="ot">=</span> <span class="dv">5</span>, subForest <span class="ot">=</span> [<span class="dt">Node</span> {rootLabel <span class="ot">=</span> <span class="dv">6</span>, subForest <span class="ot">=</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>   [<span class="dt">Node</span> {rootLabel <span class="ot">=</span> <span class="dv">7</span>, subForest <span class="ot">=</span> [<span class="dt">Node</span> {rootLabel <span class="ot">=</span> <span class="dv">8</span>, subForest <span class="ot">=</span></span></code></pre></div>
<p>Ad infinitum! With presentation, you get:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="op">:</span>present loeb (<span class="fu">map</span> (\i l <span class="ot">-&gt;</span> <span class="dt">Node</span> i (<span class="fu">map</span> (<span class="fu">fmap</span> (<span class="op">+</span><span class="dv">1</span>)) l)) [<span class="dv">1</span><span class="op">..</span><span class="dv">3</span>])</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Tree</span> <span class="dt">Integer</span><span class="op">:</span>[<span class="dt">Tree</span> <span class="dt">Integer</span>]</span></code></pre></div>
<p>If you click <code>Tree Integer</code> on the left, you get:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>(<span class="dt">Node</span> <span class="dv">1</span> [<span class="dt">Tree</span> <span class="dt">Integer</span>])<span class="op">:</span>[<span class="dt">Tree</span> <span class="dt">Integer</span>]</span></code></pre></div>
<p>Click the new one on the left:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>(<span class="dt">Node</span> <span class="dv">1</span> (<span class="dt">Tree</span> <span class="dt">Integer</span><span class="op">:</span>[<span class="dt">Tree</span> <span class="dt">Integer</span>]))<span class="op">:</span>[<span class="dt">Tree</span> <span class="dt">Integer</span>]</span></code></pre></div>
<p>Et cetera:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>(<span class="dt">Node</span> <span class="dv">1</span> ((<span class="dt">Node</span> <span class="dv">2</span> [<span class="dt">Tree</span> <span class="dt">Integer</span>])<span class="op">:</span>[<span class="dt">Tree</span> <span class="dt">Integer</span>]))<span class="op">:</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>((<span class="dt">Node</span> <span class="dv">2</span> [<span class="dt">Tree</span> <span class="dt">Integer</span>])<span class="op">:</span>[<span class="dt">Tree</span> <span class="dt">Integer</span>])</span></code></pre></div>
<p>In other words, every <code>[Tree Integer]</code> is a placeholder
that you can click to get more output.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2014-04-26 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sat, 26 Apr 2014 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Typeable and Data in Haskell]]></title><link>https://chrisdone.com/posts/data-typeable</link><guid>https://chrisdone.com/posts/data-typeable</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Typeable and Data in Haskell</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Typeable and Data in Haskell</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p><a
href="https://hackage.haskell.org/package/base-4.6.0.1/docs/Data-Typeable.html">Data.Typeable</a>
and <a
href="http://hackage.haskell.org/package/base-4.6.0.1/docs/Data-Data.html">Data.Data</a>
are rather mysterious. Starting out as a Haskell newbie you see them
once in a while and wonder what use they are. Their Haddock pages are
pretty opaque and scary in places. Here’s a quick rundown I thought I’d
write to get people up to speed nice and quick so that they can start
using it.<a href="#fn1" class="footnote-ref" id="fnref1"
role="doc-noteref"><sup>1</sup></a></p>
<p>It’s really rather beautiful as a way to do generic programming in
Haskell. The general approach is that you don’t know what data types are
being given to you, but you want to work upon them almost as if you did.
The technique is simple when broken down.</p>
<h2 id="requirements">Requirements</h2>
<p>First, there is a class exported by each module. The class
<code>Typeable</code> and the class <code>Data</code>. Your data types
have to be instances of these if you want to use the generic programming
methods on them.</p>
<p>Happily, we don’t have to write these instances ourselves (and in GHC
7.8 it is actually not possible to do so): GHC provides the extension
<code>DeriveDataTypeable</code>, which you can enable by adding
<code>{-# LANGUAGE DeriveDataTypeable #-}</code> to the top of your
file, or providing <code>-XDeriveDataTypeable</code> to
<code>ghc</code>.</p>
<p>Now you can derive instances of both:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">X</span> <span class="ot">=</span> <span class="dt">X</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">deriving</span> (<span class="dt">Data</span>,<span class="dt">Typeable</span>)</span></code></pre></div>
<p>Now we can start doing generic operations upon <code>X</code>.</p>
<h2 id="the-typeable-class">The Typeable class</h2>
<p>As a simple starter, we can trivially print the type of any instance
of <code>Typeable</code>. What are some existing instances of
<code>Typeable</code>? Let’s ask GHCi:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="op">:</span>i <span class="dt">Typeable</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> <span class="dt">Typeable</span> a <span class="kw">where</span><span class="ot"> typeOf ::</span> a <span class="ot">-&gt;</span> <span class="dt">TypeRep</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> [overlap ok] (<span class="dt">Typeable1</span> s, <span class="dt">Typeable</span> a) <span class="ot">=&gt;</span> <span class="dt">Typeable</span> (s a)</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> [overlap ok] <span class="dt">Typeable</span> <span class="dt">TypeRep</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> [overlap ok] <span class="dt">Typeable</span> <span class="dt">TyCon</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> [overlap ok] <span class="dt">Typeable</span> <span class="dt">Ordering</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> [overlap ok] <span class="dt">Typeable</span> <span class="dt">Integer</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> [overlap ok] <span class="dt">Typeable</span> <span class="dt">Int</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> [overlap ok] <span class="dt">Typeable</span> <span class="dt">Float</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> [overlap ok] <span class="dt">Typeable</span> <span class="dt">Double</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> [overlap ok] <span class="dt">Typeable</span> <span class="dt">Char</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> [overlap ok] <span class="dt">Typeable</span> <span class="dt">Bool</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> [overlap ok] <span class="dt">Typeable</span> ()</span></code></pre></div>
<p>That’s the basic Prelude types and the Typeable library’s own
types.</p>
<p>There’s only one method in the <code>Typeable</code> class:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ot">typeOf ::</span> a <span class="ot">-&gt;</span> <span class="dt">TypeRep</span></span></code></pre></div>
<p>The <code>TypeRep</code> value has some useful normal instances:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="op">:</span>i <span class="dt">TypeRep</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> [overlap ok] <span class="dt">Eq</span> <span class="dt">TypeRep</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> [overlap ok] <span class="dt">Ord</span> <span class="dt">TypeRep</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> [overlap ok] <span class="dt">Show</span> <span class="dt">TypeRep</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> [overlap ok] <span class="dt">Typeable</span> <span class="dt">TypeRep</span></span></code></pre></div>
<h2 id="use-case-1-print-the-type-of-something">Use-case 1: Print the
type of something</h2>
<p>So we can use this function on a <code>Char</code> value, for
example, and GHCi can print it:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="op">:</span>t typeOf <span class="ch">&#39;a&#39;</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>typeOf <span class="ch">&#39;a&#39;</span><span class="ot"> ::</span> <span class="dt">TypeRep</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> typeOf <span class="ch">&#39;a&#39;</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="dt">Char</span></span></code></pre></div>
<p>This is mostly useful for debugging, but can also be useful when
writing generic encoders or any tool which needs an identifier to be
associated with some generic value.</p>
<h2 id="use-case-2-compare-the-types-of-two-things">Use-case 2: Compare
the types of two things</h2>
<p>We can also compare two type representations:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> typeOf <span class="ch">&#39;a&#39;</span> <span class="op">==</span> typeOf <span class="ch">&#39;b&#39;</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="dt">True</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> typeOf <span class="ch">&#39;a&#39;</span> <span class="op">==</span> typeOf ()</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="dt">False</span></span></code></pre></div>
<p>Any code which needs to allow any old type to be passed into it, but
which has some interest in sometimes enforcing or triggering on a
specific type can use this to compare them.</p>
<h2 id="use-case-3-reifying-from-generic-to-concrete">Use-case 3:
Reifying from generic to concrete</h2>
<p>A common thing to need to do is when given a generic value, is to
sometimes, if the type is right, actually work with the value as the
concrete type, not a polymorphic type. For example, a printing
function:</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="ot">char ::</span> <span class="dt">Typeable</span> a <span class="ot">=&gt;</span> a <span class="ot">-&gt;</span> <span class="dt">String</span></span></code></pre></div>
<p>The specification for this function is: if given an
<code>Char</code>, return its string representation, otherwise, return
<code>"unknown"</code>. To do this, we need a function that will convert
from a polymorphic value to a concrete one:</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ot">cast ::</span> (<span class="dt">Typeable</span> a, <span class="dt">Typeable</span> b) <span class="ot">=&gt;</span> a <span class="ot">-&gt;</span> <span class="dt">Maybe</span> b</span></code></pre></div>
<p>This function from <code>Data.Typeable</code> will do just that. Now
we can implement <code>char</code>:</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="kw">let</span> char x <span class="ot">=</span> <span class="kw">case</span> cast x <span class="kw">of</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>                  <span class="dt">Just</span> (<span class="ot">x ::</span> <span class="dt">Char</span>) <span class="ot">-&gt;</span> <span class="fu">show</span> x</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>                  <span class="dt">Nothing</span> <span class="ot">-&gt;</span> <span class="st">&quot;unknown&quot;</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> char <span class="ch">&#39;a&#39;</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;&#39;a&#39;&quot;</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> char <span class="dv">5</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;unknown&quot;</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> char ()</span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;unknown&quot;</span></span></code></pre></div>
<h2 id="the-data-class">The Data class</h2>
<p>That’s more or less where the interesting practical applications of
the <code>Typeable</code> class ends. But it becomes more interesting
once you have that, the <code>Data</code> class can take advantage of
it. The <code>Data</code> class is much more interesting. The point is
to be able to look into a data type’s constructors, its fields and
traverse across or fold over them. Let’s take a look at the class.</p>
<p>Again, there are some basic instances provided:</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Data</span> a <span class="ot">=&gt;</span> <span class="dt">Data</span> [a]</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Data</span> <span class="dt">Ordering</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Data</span> a <span class="ot">=&gt;</span> <span class="dt">Data</span> (<span class="dt">Maybe</span> a)</span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Data</span> <span class="dt">Integer</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Data</span> <span class="dt">Int</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Data</span> <span class="dt">Float</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> (<span class="dt">Data</span> a, <span class="dt">Data</span> b) <span class="ot">=&gt;</span> <span class="dt">Data</span> (<span class="dt">Either</span> a b)</span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Data</span> <span class="dt">Double</span></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Data</span> <span class="dt">Char</span></span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Data</span> <span class="dt">Bool</span></span></code></pre></div>
<p>It’s a rather big class, so I’ll just cover some methods that
demonstrate the key use-cases.</p>
<h2 id="use-case-1-get-the-data-type">Use-case 1: Get the data type</h2>
<p>Similar to the <code>TypeRep</code>, you can use
<code>dataTypeOf</code> to get a unique representation of a data
type:</p>
<div class="sourceCode" id="cb11"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="ot">dataTypeOf ::</span> <span class="dt">Data</span> a <span class="ot">=&gt;</span> a <span class="ot">-&gt;</span> <span class="dt">DataType</span></span></code></pre></div>
<p>For example:</p>
<div class="sourceCode" id="cb12"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> dataTypeOf (<span class="dt">Just</span> <span class="ch">&#39;a&#39;</span>)</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="dt">DataType</span> {tycon <span class="ot">=</span> <span class="st">&quot;Prelude.Maybe&quot;</span>, datarep <span class="ot">=</span> <span class="dt">AlgRep</span> [<span class="dt">Nothing</span>,<span class="dt">Just</span>]}</span></code></pre></div>
<p>There aren’t any other interesting instances for this type, but we’ll
look at uses for this type later. Representations (so-called
<code>FooRep</code>) tend to be references from which you can reify into
more concrete values.</p>
<h2 id="use-case-2-inspecting-a-data-type">Use-case 2: Inspecting a data
type</h2>
<p>The most common thing to want to do is to get a list of constructors
that a type contains. So, the <code>Maybe</code> type contains two.</p>
<div class="sourceCode" id="cb13"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="op">:</span>t dataTypeConstrs</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="ot">dataTypeConstrs ::</span> <span class="dt">DataType</span> <span class="ot">-&gt;</span> [<span class="dt">Constr</span>]</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> dataTypeConstrs (dataTypeOf (<span class="dt">Nothing</span><span class="ot"> ::</span> <span class="dt">Maybe</span> ()))</span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>[<span class="dt">Nothing</span>,<span class="dt">Just</span>]</span></code></pre></div>
<p>We’ll look at what we can do with constructors later.</p>
<p>It’s also surprisingly common to want to see what the constructor is
at a particular index. We could write this function ourself, but there’s
already one provided:</p>
<div class="sourceCode" id="cb14"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> indexConstr (dataTypeOf (<span class="dt">Nothing</span><span class="ot"> ::</span> <span class="dt">Maybe</span> ())) <span class="dv">2</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Just</span></span></code></pre></div>
<p>Sometimes you want to know whether a data type is algebraic (in other
words, does it have constructors and is it not one of the built-in types
like Int/Float/etc)?</p>
<div class="sourceCode" id="cb15"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> isAlgType (dataTypeOf (<span class="dt">Just</span> <span class="ch">&#39;a&#39;</span>))</span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a><span class="dt">True</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> isAlgType (dataTypeOf <span class="ch">&#39;a&#39;</span>)</span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a><span class="dt">False</span></span></code></pre></div>
<h2 id="use-case-3-get-the-constructor-of-a-value">Use-case 3: Get the
constructor of a value</h2>
<p>We have the method</p>
<div class="sourceCode" id="cb16"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="ot">toConstr ::</span> a <span class="ot">-&gt;</span> <span class="dt">Constr</span></span></code></pre></div>
<p>Which given any instance of <code>Data</code> will yield a
constructor.</p>
<div class="sourceCode" id="cb17"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="op">:</span>i <span class="dt">Constr</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Constr</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Eq</span> <span class="dt">Constr</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Show</span> <span class="dt">Constr</span></span></code></pre></div>
<p>You can’t do much with a constructor as-is, but compare and print
it:</p>
<div class="sourceCode" id="cb18"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> toConstr (<span class="dt">Just</span> <span class="ch">&#39;a&#39;</span>)</span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Just</span></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> toConstr (<span class="dt">Just</span> <span class="ch">&#39;a&#39;</span>) <span class="op">==</span> toConstr (<span class="dt">Nothing</span><span class="ot"> ::</span> <span class="dt">Maybe</span> <span class="dt">Char</span>)</span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a><span class="dt">False</span></span></code></pre></div>
<p>However, those operations by themselves can be useful.</p>
<p>By the way, we can also get back the <code>DataRep</code> of a
constructor:</p>
<div class="sourceCode" id="cb19"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> constrType (toConstr (<span class="dt">Just</span> <span class="ch">&#39;a&#39;</span>))</span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a><span class="dt">DataType</span> {tycon <span class="ot">=</span> <span class="st">&quot;Prelude.Maybe&quot;</span>, datarep <span class="ot">=</span> <span class="dt">AlgRep</span> [<span class="dt">Nothing</span>,<span class="dt">Just</span>]}</span></code></pre></div>
<h2 id="use-case-4-get-fields-of-a-constructor">Use-case 4: Get fields
of a constructor</h2>
<p>Another typical thing to want to do is to use the field names of a
constructor. So for example:</p>
<div class="sourceCode" id="cb20"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="kw">data</span> <span class="dt">X</span> <span class="ot">=</span> <span class="dt">X</span> {<span class="ot"> foo ::</span> <span class="dt">Int</span>,<span class="ot"> bar ::</span> <span class="dt">Char</span> } <span class="kw">deriving</span> (<span class="dt">Typeable</span>,<span class="dt">Data</span>)</span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> toConstr (<span class="dt">X</span> <span class="dv">0</span> <span class="ch">&#39;a&#39;</span>)</span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a><span class="dt">X</span></span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> constrFields (toConstr (<span class="dt">X</span> <span class="dv">0</span> <span class="ch">&#39;a&#39;</span>))</span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a>[<span class="st">&quot;foo&quot;</span>,<span class="st">&quot;bar&quot;</span>]</span></code></pre></div>
<p>It’s a good use-case for serializing and debugging.</p>
<h2 id="use-case-5-make-a-real-value-from-its-constructor">Use-case 5:
Make a real value from its constructor</h2>
<p>It’s actually possible to produce a value from its constructor. We
have this function</p>
<div class="sourceCode" id="cb21"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="ot">fromConstr ::</span> <span class="dt">Data</span> a <span class="ot">=&gt;</span> <span class="dt">Constr</span> <span class="ot">-&gt;</span> a</span></code></pre></div>
<p>Example:</p>
<div class="sourceCode" id="cb22"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> fromConstr (toConstr (<span class="dt">Nothing</span><span class="ot"> ::</span> <span class="dt">Maybe</span> ()))<span class="ot"> ::</span> <span class="dt">Maybe</span> ()</span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Nothing</span></span></code></pre></div>
<p>But what do you do when the constructor has fields? No sweat. We have
this function:</p>
<div class="sourceCode" id="cb23"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="ot">fromConstrB ::</span> <span class="kw">forall</span> a<span class="op">.</span> <span class="dt">Data</span> a</span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>            <span class="ot">=&gt;</span> (<span class="kw">forall</span> d<span class="op">.</span> <span class="dt">Data</span> d <span class="ot">=&gt;</span> d) <span class="ot">-&gt;</span> <span class="dt">Constr</span> <span class="ot">-&gt;</span> a</span></code></pre></div>
<p>Haskell beginners: Don’t fear the rank-N type. What it’s saying is
merely that the <code>fromConstrB</code> function determines what the
type of <code>d</code> will be by itself, by looking at
<code>Constr</code>. It’s not provided externally by the caller, as it
would be if the <code>forall d.</code> were at the same level as the
<code>a</code>. Think of it like scope.
<code>let a = d in let d = …</code> doesn’t make sense: the
<code>d</code> is in a lower scope. That means we can’t just write:</p>
<div class="sourceCode" id="cb24"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a>fromConstrB (<span class="dv">5</span><span class="ot"> ::</span> <span class="dt">Int</span>) (toConstr (<span class="dt">Just</span> <span class="dv">1</span><span class="ot"> ::</span> <span class="dt">Maybe</span> <span class="dt">Int</span>))<span class="ot"> ::</span> <span class="dt">Maybe</span> <span class="dt">Int</span></span></code></pre></div>
<p>The <code>Int</code> cannot unify with the <code>d</code> because the
quantification is one level lower. It basically doesn’t exist outside of
the <code>(forall d. Data d =&gt; d)</code> (nor can it escape). That’s
okay, though. There is a type-class constraint which lets us be generic.
We already have a function producing a value of that type:</p>
<div class="sourceCode" id="cb25"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="op">:</span>t fromConstr (toConstr (<span class="dv">1</span><span class="ot"> ::</span> <span class="dt">Int</span>))</span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a>fromConstr (toConstr (<span class="dv">1</span><span class="ot"> ::</span> <span class="dt">Int</span>))<span class="ot"> ::</span> <span class="dt">Data</span> a <span class="ot">=&gt;</span> a</span></code></pre></div>
<p>So we can just use that:</p>
<div class="sourceCode" id="cb26"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> fromConstrB (fromConstr (toConstr (<span class="dv">1</span><span class="ot"> ::</span> <span class="dt">Int</span>)))</span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a>               (toConstr (<span class="dt">Just</span> <span class="dv">1</span><span class="ot"> ::</span> <span class="dt">Maybe</span> <span class="dt">Int</span>))<span class="ot"> ::</span> <span class="dt">Maybe</span> <span class="dt">Int</span></span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a><span class="dt">Just</span> <span class="dv">1</span></span></code></pre></div>
<p>Tada! But wait… What if there’re <em>more</em> fields? How do we
provide more than one, and of different types?</p>
<p>Enter <code>fromConstrM</code>:</p>
<div class="sourceCode" id="cb27"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="ot">fromConstrM ::</span> <span class="kw">forall</span> m a<span class="op">.</span> (<span class="dt">Monad</span> m, <span class="dt">Data</span> a)</span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a>            <span class="ot">=&gt;</span> (<span class="kw">forall</span> d<span class="op">.</span> <span class="dt">Data</span> d <span class="ot">=&gt;</span> m d) <span class="ot">-&gt;</span> <span class="dt">Constr</span> <span class="ot">-&gt;</span> m a</span></code></pre></div>
<p>Because it’s monadic we can use a state monad to keep an index!
Observe:</p>
<div class="sourceCode" id="cb28"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="op">:</span>t execState</span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a><span class="ot">execState ::</span> <span class="dt">State</span> s a <span class="ot">-&gt;</span> s <span class="ot">-&gt;</span> s</span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="op">:</span>t execState (modify (<span class="op">+</span><span class="dv">1</span>))</span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a>execState (modify (<span class="op">+</span><span class="dv">1</span>))<span class="ot"> ::</span> <span class="dt">Num</span> s <span class="ot">=&gt;</span> s <span class="ot">-&gt;</span> s</span>
<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="op">:</span>t execState (forM_ [<span class="dv">1</span><span class="op">..</span><span class="dv">5</span>] (<span class="fu">const</span> (modify (<span class="op">+</span><span class="dv">1</span>))))</span>
<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a>execState (forM_ [<span class="dv">1</span><span class="op">..</span><span class="dv">5</span>] (<span class="fu">const</span> (modify (<span class="op">+</span><span class="dv">1</span>))))<span class="ot"> ::</span> <span class="dt">Num</span> s <span class="ot">=&gt;</span> s<span class="ot">-&gt;</span> s</span>
<span id="cb28-7"><a href="#cb28-7" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> execState (forM_ [<span class="dv">1</span><span class="op">..</span><span class="dv">5</span>] (<span class="fu">const</span> (modify (<span class="op">+</span><span class="dv">1</span>)))) <span class="dv">5</span></span>
<span id="cb28-8"><a href="#cb28-8" aria-hidden="true" tabindex="-1"></a><span class="dv">10</span></span></code></pre></div>
<p>Let’s put this to use with <code>fromConstrM</code>:</p>
<div class="sourceCode" id="cb29"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> evalState</span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a>     (fromConstrM</span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a>       (<span class="kw">do</span> i <span class="ot">&lt;-</span> get</span>
<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a>           modify (<span class="op">+</span><span class="dv">1</span>)</span>
<span id="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a>           <span class="fu">return</span></span>
<span id="cb29-6"><a href="#cb29-6" aria-hidden="true" tabindex="-1"></a>             (<span class="kw">case</span> i <span class="kw">of</span></span>
<span id="cb29-7"><a href="#cb29-7" aria-hidden="true" tabindex="-1"></a>               <span class="dv">0</span> <span class="ot">-&gt;</span> fromConstr (toConstr (<span class="dv">5</span><span class="ot">::</span><span class="dt">Int</span>))</span>
<span id="cb29-8"><a href="#cb29-8" aria-hidden="true" tabindex="-1"></a>               <span class="dv">1</span> <span class="ot">-&gt;</span> fromConstr (toConstr <span class="ch">&#39;b&#39;</span>)))</span>
<span id="cb29-9"><a href="#cb29-9" aria-hidden="true" tabindex="-1"></a>       (toConstr (<span class="dt">Foo</span> <span class="dv">4</span> <span class="ch">&#39;a&#39;</span>)))</span>
<span id="cb29-10"><a href="#cb29-10" aria-hidden="true" tabindex="-1"></a>     <span class="dv">0</span><span class="ot"> ::</span> <span class="dt">Foo</span></span>
<span id="cb29-11"><a href="#cb29-11" aria-hidden="true" tabindex="-1"></a><span class="dt">Foo</span> <span class="dv">5</span> <span class="ch">&#39;b&#39;</span></span>
<span id="cb29-12"><a href="#cb29-12" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span></span></code></pre></div>
<p>In other words, keep an index starting at 0. Increase it each
iteration that <code>fromConstrM</code> does. When we’re at index 0,
return an <code>Int</code>, when we’re at index 1, return a
<code>Char</code>. Easy! Right?</p>
<h2 id="use-case-6-mapping-over-data-structures-generically">Use-case 6:
mapping over data structures generically</h2>
<p>A common thing to want is to map over a value in a
structure-preserving way, but changing its values. For that we have
<code>gmapT</code>:</p>
<div class="sourceCode" id="cb30"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="ot">gmapT ::</span> <span class="kw">forall</span> a<span class="op">.</span> <span class="dt">Data</span> a</span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a>      <span class="ot">=&gt;</span> (<span class="kw">forall</span> b<span class="op">.</span> <span class="dt">Data</span> b <span class="ot">=&gt;</span> b <span class="ot">-&gt;</span> b) <span class="ot">-&gt;</span> a <span class="ot">-&gt;</span> a</span></code></pre></div>
<p>Similar to <code>fromConstr*</code>, there is a rank-n type
<code>b</code> that refers to each type in the constructor of type
<code>a</code>. It’s easy enough to use:</p>
<div class="sourceCode" id="cb31"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> gmapT</span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a>     (\d <span class="ot">-&gt;</span></span>
<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a>        <span class="kw">case</span> cast d <span class="kw">of</span></span>
<span id="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a>          <span class="dt">Nothing</span> <span class="ot">-&gt;</span> d</span>
<span id="cb31-5"><a href="#cb31-5" aria-hidden="true" tabindex="-1"></a>          <span class="dt">Just</span> x <span class="ot">-&gt;</span></span>
<span id="cb31-6"><a href="#cb31-6" aria-hidden="true" tabindex="-1"></a>            fromJust (cast (<span class="kw">if</span> <span class="fu">isUpper</span> x <span class="kw">then</span> <span class="ch">&#39;!&#39;</span> <span class="kw">else</span> x)))</span>
<span id="cb31-7"><a href="#cb31-7" aria-hidden="true" tabindex="-1"></a>     (<span class="dt">Foo</span> <span class="dv">4</span> <span class="ch">&#39;a&#39;</span>)</span>
<span id="cb31-8"><a href="#cb31-8" aria-hidden="true" tabindex="-1"></a><span class="dt">Foo</span> <span class="dv">4</span> <span class="ch">&#39;a&#39;</span></span>
<span id="cb31-9"><a href="#cb31-9" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> gmapT</span>
<span id="cb31-10"><a href="#cb31-10" aria-hidden="true" tabindex="-1"></a>     (\d <span class="ot">-&gt;</span></span>
<span id="cb31-11"><a href="#cb31-11" aria-hidden="true" tabindex="-1"></a>        <span class="kw">case</span> cast d <span class="kw">of</span></span>
<span id="cb31-12"><a href="#cb31-12" aria-hidden="true" tabindex="-1"></a>          <span class="dt">Nothing</span> <span class="ot">-&gt;</span> d</span>
<span id="cb31-13"><a href="#cb31-13" aria-hidden="true" tabindex="-1"></a>          <span class="dt">Just</span> x <span class="ot">-&gt;</span></span>
<span id="cb31-14"><a href="#cb31-14" aria-hidden="true" tabindex="-1"></a>            fromJust (cast (<span class="kw">if</span> <span class="fu">isUpper</span> x <span class="kw">then</span> <span class="ch">&#39;!&#39;</span> <span class="kw">else</span> x)))</span>
<span id="cb31-15"><a href="#cb31-15" aria-hidden="true" tabindex="-1"></a>     (<span class="dt">Foo</span> <span class="dv">4</span> <span class="ch">&#39;A&#39;</span>)</span>
<span id="cb31-16"><a href="#cb31-16" aria-hidden="true" tabindex="-1"></a><span class="dt">Foo</span> <span class="dv">4</span> <span class="ch">&#39;!&#39;</span></span></code></pre></div>
<p>Here I’m doing a little check on any field in the constructor of type
<code>Char</code> and if it’s upper case, replacing it with
<code>!</code>, otherwise leaving it as-is. The first trick is to use
the <code>cast</code> function we used earlier to reify the generic
<code>d</code> into something real (<code>Char</code>). The second trick
is to cast our concrete <code>Char</code> back into a generic
<code>d</code> type.</p>
<p>Just like <code>fromConstrM</code> earlier, if you want to operate on
exact indices of the constructor rather than going by type, you can use
<code>gmapM</code> and use a state monad to do the same thing as we did
before.</p>
<h2 id="use-case-7-generating-from-data-structures-generically">Use-case
7: generating from data structures generically</h2>
<p>Another slightly different use-case is to walk over the values of a
data structure, collecting the result. You can do this with
<code>gmapM</code> and a state monad or a writer, but there’s a handy
function already to do this:</p>
<div class="sourceCode" id="cb32"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a><span class="ot">gmapQ ::</span> <span class="kw">forall</span> a<span class="op">.</span> <span class="dt">Data</span> a <span class="ot">=&gt;</span> (<span class="kw">forall</span> d<span class="op">.</span> <span class="dt">Data</span> d <span class="ot">=&gt;</span> d <span class="ot">-&gt;</span> u) <span class="ot">-&gt;</span> a <span class="ot">-&gt;</span> [u]</span></code></pre></div>
<p>Trivial example:</p>
<div class="sourceCode" id="cb33"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> gmapQ (\d <span class="ot">-&gt;</span> toConstr d) (<span class="dt">Foo</span> <span class="dv">5</span> <span class="ch">&#39;a&#39;</span>)</span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a>[<span class="dv">5</span>,<span class="ch">&#39;a&#39;</span>]</span></code></pre></div>
<p>A more useful example can be found in <a
href="https://github.com/chrisdone/structured-haskell-mode/blob/18c011978acfca30bac800d0ac0e9e31e653c440/src/Main.hs#L96">structured-haskell-mode</a>
which walks over the Haskell syntax tree and collects source spans into
a flat list. Another decent example is in <a
href="https://github.com/chrisdone/present/blob/master/src/Present.hs#L75">the
present package</a>. There’s also an example in <a
href="https://github.com/faylang/fay/blob/master/src/Fay/Convert.hs#L54">Fay</a>
to encode types to JSON with a specific Fay-runtime-specific
encoding.</p>
<h2 id="printer-example">Printer example</h2>
<p>Here’s a trivial (not very good, but something I wrote once) generic
printer:</p>
<div class="sourceCode" id="cb34"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a><span class="ot">gshows ::</span> <span class="dt">Data</span> a <span class="ot">=&gt;</span> a <span class="ot">-&gt;</span> <span class="dt">ShowS</span></span>
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a>gshows <span class="ot">=</span> render <span class="ot">`extQ`</span> (<span class="fu">shows</span><span class="ot"> ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">ShowS</span>) <span class="kw">where</span></span>
<span id="cb34-3"><a href="#cb34-3" aria-hidden="true" tabindex="-1"></a>  render t</span>
<span id="cb34-4"><a href="#cb34-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">|</span> isTuple <span class="ot">=</span> <span class="fu">showChar</span> <span class="ch">&#39;(&#39;</span></span>
<span id="cb34-5"><a href="#cb34-5" aria-hidden="true" tabindex="-1"></a>              <span class="op">.</span> <span class="fu">drop</span> <span class="dv">1</span></span>
<span id="cb34-6"><a href="#cb34-6" aria-hidden="true" tabindex="-1"></a>              <span class="op">.</span> commaSlots</span>
<span id="cb34-7"><a href="#cb34-7" aria-hidden="true" tabindex="-1"></a>              <span class="op">.</span> <span class="fu">showChar</span> <span class="ch">&#39;)&#39;</span></span>
<span id="cb34-8"><a href="#cb34-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">|</span> isNull <span class="ot">=</span> <span class="fu">showString</span> <span class="st">&quot;[]&quot;</span></span>
<span id="cb34-9"><a href="#cb34-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">|</span> isList <span class="ot">=</span> <span class="fu">showChar</span> <span class="ch">&#39;[&#39;</span></span>
<span id="cb34-10"><a href="#cb34-10" aria-hidden="true" tabindex="-1"></a>             <span class="op">.</span> <span class="fu">drop</span> <span class="dv">1</span></span>
<span id="cb34-11"><a href="#cb34-11" aria-hidden="true" tabindex="-1"></a>             <span class="op">.</span> listSlots</span>
<span id="cb34-12"><a href="#cb34-12" aria-hidden="true" tabindex="-1"></a>             <span class="op">.</span> <span class="fu">showChar</span> <span class="ch">&#39;]&#39;</span></span>
<span id="cb34-13"><a href="#cb34-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">|</span> <span class="fu">otherwise</span> <span class="ot">=</span> <span class="fu">showChar</span> <span class="ch">&#39;(&#39;</span></span>
<span id="cb34-14"><a href="#cb34-14" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span> constructor</span>
<span id="cb34-15"><a href="#cb34-15" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span> slots</span>
<span id="cb34-16"><a href="#cb34-16" aria-hidden="true" tabindex="-1"></a>                <span class="op">.</span> <span class="fu">showChar</span> <span class="ch">&#39;)&#39;</span></span>
<span id="cb34-17"><a href="#cb34-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb34-18"><a href="#cb34-18" aria-hidden="true" tabindex="-1"></a>    <span class="kw">where</span> constructor <span class="ot">=</span> <span class="fu">showString</span> <span class="op">.</span> showConstr <span class="op">.</span> toConstr <span class="op">$</span> t</span>
<span id="cb34-19"><a href="#cb34-19" aria-hidden="true" tabindex="-1"></a>          slots <span class="ot">=</span> <span class="fu">foldr</span> (<span class="op">.</span>) <span class="fu">id</span> <span class="op">.</span> gmapQ ((<span class="fu">showChar</span> <span class="ch">&#39; &#39;</span> <span class="op">.</span>) <span class="op">.</span> gshows) <span class="op">$</span> t</span>
<span id="cb34-20"><a href="#cb34-20" aria-hidden="true" tabindex="-1"></a>          commaSlots <span class="ot">=</span> <span class="fu">foldr</span> (<span class="op">.</span>) <span class="fu">id</span> <span class="op">.</span> gmapQ ((<span class="fu">showChar</span> <span class="ch">&#39;,&#39;</span> <span class="op">.</span>) <span class="op">.</span> gshows) <span class="op">$</span> t</span>
<span id="cb34-21"><a href="#cb34-21" aria-hidden="true" tabindex="-1"></a>          listSlots <span class="ot">=</span> <span class="fu">foldr</span> (<span class="op">.</span>) <span class="fu">id</span> <span class="op">.</span> <span class="fu">init</span> <span class="op">.</span> gmapQ ((<span class="fu">showChar</span> <span class="ch">&#39;,&#39;</span> <span class="op">.</span>) <span class="op">.</span> gshows) <span class="op">$</span> t</span>
<span id="cb34-22"><a href="#cb34-22" aria-hidden="true" tabindex="-1"></a>          isTuple <span class="ot">=</span> <span class="fu">all</span> (<span class="op">==</span><span class="ch">&#39;,&#39;</span>) (<span class="fu">filter</span> (<span class="fu">not</span> <span class="op">.</span> <span class="fu">flip</span> <span class="fu">elem</span> <span class="st">&quot;()&quot;</span>) (constructor <span class="st">&quot;&quot;</span>))</span>
<span id="cb34-23"><a href="#cb34-23" aria-hidden="true" tabindex="-1"></a>          isNull <span class="ot">=</span> <span class="fu">null</span> (<span class="fu">filter</span> (<span class="fu">not</span> <span class="op">.</span> <span class="fu">flip</span> <span class="fu">elem</span> <span class="st">&quot;[]&quot;</span>) (constructor <span class="st">&quot;&quot;</span>))</span>
<span id="cb34-24"><a href="#cb34-24" aria-hidden="true" tabindex="-1"></a>          isList <span class="ot">=</span> constructor <span class="st">&quot;&quot;</span> <span class="op">==</span> <span class="st">&quot;(:)&quot;</span></span></code></pre></div>
<p>I wrote it because the GHC API doesn’t have <code>Show</code>
instances for most of its data types, so it’s rather hard to actually
inspect <em>any</em> data types that you’re working with in the REPL. It
has instances for pretty printing, but pretty printing confuses
presentation with data.</p>
<p>Example:</p>
<div class="sourceCode" id="cb35"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="kw">data</span> <span class="dt">Foo</span> <span class="ot">=</span> <span class="dt">Foo</span> <span class="dt">Char</span> <span class="dt">Int</span> <span class="kw">deriving</span> (<span class="dt">Data</span>,<span class="dt">Typeable</span>)</span>
<span id="cb35-2"><a href="#cb35-2" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> gshow ([<span class="dt">Just</span> <span class="dv">2</span>],<span class="ch">&#39;c&#39;</span>,<span class="dt">Foo</span> <span class="ch">&#39;a&#39;</span> <span class="dv">5</span>)</span>
<span id="cb35-3"><a href="#cb35-3" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;([(Just (2))],(&#39;c&#39;),(Foo (&#39;a&#39;) (5)))&quot;</span></span></code></pre></div>
<p>Note: no <code>Show</code> instance for <code>Foo</code>.</p>
<h2 id="summary">Summary</h2>
<p>We’ve briefly covered how to query types, how to cast them, how to
walk over them or generate from them. There’re other things one can do,
but those are the main things. The real trick is understanding how to
make the types work and that comes with a bit of experience. Fiddle
around with the concepts above and you should gain an intution for what
is possible with this library. See also: <a
href="http://hackage.haskell.org/package/syb-0.4.1/docs/Data-Generics-Aliases.html">Data.Generics.Aliases</a>.</p>
<p>Hope it helps!</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>I’ll migrate this to the HaskellWiki
when it doesn’t look so, uh, shall we say, unattractive.<a
href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2014-04-22 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Tue, 22 Apr 2014 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Haskell structured diffs]]></title><link>https://chrisdone.com/posts/haskell-diff</link><guid>https://chrisdone.com/posts/haskell-diff</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Haskell structured diffs</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Haskell structured diffs</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Project-request: someone please implement a program that will diff
Haskell in a cleverer way than lines.</p>
<p>In an effort to reign in my incessant work on Haskell tooling<a
href="#fn1" class="footnote-ref" id="fnref1"
role="doc-noteref"><sup>1</sup></a>, I’m outlining a tool that I’d
personally like and welcome people to implement it. Otherwise it serves
as a motivating problem description for the next time I come around to
it myself with free time.</p>
<p>Before anyone emails me saying “lines/words are simple, other things
are hard, that’s why it’s not been done yet. People undervalue the
simple solution …” with a long lecture, spare me!</p>
<h2 id="the-concrete-diff">The concrete diff</h2>
<p>The concrete diff is the line-based, and sometimes character-based,
diff that we all know and love. There’s no reason to throw this away.
You will need to keep this as an optional backend for when you are
unable to parse a Haskell file.</p>
<p>Pros: simple to implement. You produce the necessary lines to delete
and insert to create the change from A to B.</p>
<p>Cons: doesn’t know about syntactic redundancy where some changes
don’t mean anything, and where the actual important change occurs. For
example:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span> <span class="fu">putStrLn</span> <span class="st">&quot;Write your name!&quot;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>          name <span class="ot">&lt;-</span> <span class="fu">getLine</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>          <span class="fu">print</span> name</span></code></pre></div>
<p>Now you change this to:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span> args <span class="ot">&lt;-</span> getArgs</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>          <span class="kw">case</span> args <span class="kw">of</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>            [] <span class="ot">-&gt;</span> <span class="kw">do</span> <span class="fu">putStrLn</span> <span class="st">&quot;Write your name!&quot;</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>                     name <span class="ot">&lt;-</span> <span class="fu">getLine</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>                     <span class="fu">print</span> name</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>            _ <span class="ot">-&gt;</span> runWithArgs args</span></code></pre></div>
<p>The diff will look like this:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode diff"><code class="sourceCode diff"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="dt">@@ -5,3 +5,6 @@ module Main where</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="st">-main = do putStrLn &quot;Write your name!&quot;</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="st">-          name &lt;- getLine</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="st">-          print name</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="va">+main = do args &lt;- getArgs</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="va">+          case args of</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="va">+            [] -&gt; do putStrLn &quot;Write your name!&quot;</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a><span class="va">+                     name &lt;- getLine</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a><span class="va">+                     print name</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a><span class="va">+            _ -&gt; runWithArgs args</span></span></code></pre></div>
<p>But it’s clear to observe that this is not the change we made in
spirit, it’s just one line-based way to achieve it. In actual fact, our
<code>do putStrLn …</code> was moved into a <code>case</code>,
un-changed. At this size, it’s not a big deal. When the code is more
interesting, it’s important to know what was really changed, and what
remains the same.</p>
<h2 id="the-abstract-syntax-diff">The abstract syntax diff</h2>
<p>Enter the syntactic diff. We show the difference between two
syntactic trees. How this is to be achieved in a readable way is the
rub, but here are some ideas.</p>
<p>Take our example above, one approach can be to label nodes.</p>
<p>Before:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>¹{main <span class="ot">=</span> ²{<span class="kw">do</span> <span class="fu">putStrLn</span> <span class="st">&quot;Write your name!&quot;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>              name <span class="ot">&lt;-</span> <span class="fu">getLine</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>              <span class="fu">print</span> name}}</span></code></pre></div>
<p>After:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>¹{main <span class="ot">=</span> <span class="kw">do</span> args <span class="ot">&lt;-</span> getArgs</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>            <span class="kw">case</span> args <span class="kw">of</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>              [] <span class="ot">-&gt;</span> ²{<span class="kw">do</span> <span class="fu">putStrLn</span> <span class="st">&quot;Write your name!&quot;</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>                         name <span class="ot">&lt;-</span> <span class="fu">getLine</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>                         <span class="fu">print</span> name}</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>              _ <span class="ot">-&gt;</span> runWithArgs args}</span></code></pre></div>
<p>Now, at least at a superficial glance, you don’t even need this
explained to you. You can see exactly what has happened: The code before
has changed to the code after, but we can see that node<sub>2</sub> has
just moved to inside the case.</p>
<p>Where the trickiness arises is taking this to its logical conclusion
and applying it generally. What’s displayed if you also change the
string in the <code>putStrLn</code>? Good question. Here’s an idea:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>¹{main <span class="ot">=</span> ²{<span class="kw">do</span> <span class="fu">putStrLn</span> <span class="op">-</span>{<span class="st">&quot;Write your name!&quot;</span>}</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>              name <span class="ot">&lt;-</span> <span class="fu">getLine</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>              <span class="fu">print</span> name}}</span></code></pre></div>
<p>Because the node <code>"Write your name"</code> has now been lost, we
don’t need to reference it any longer. So one way to show that it has
been removed could be to put <code>-{…}</code>. And then to show what
replaced it, put in <code>+{…}</code>, a la classic diffs:</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>¹{main <span class="ot">=</span> <span class="op">+</span>{<span class="kw">do</span> args <span class="ot">&lt;-</span> getArgs</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>              <span class="kw">case</span> args <span class="kw">of</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>                [] <span class="ot">-&gt;</span> ²{<span class="kw">do</span> <span class="fu">putStrLn</span> <span class="op">+</span>{<span class="st">&quot;Hello!&quot;</span>}</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>                           name <span class="ot">&lt;-</span> <span class="fu">getLine</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>                           <span class="fu">print</span> name}</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>                _ <span class="ot">-&gt;</span> runWithArgs args}}</span></code></pre></div>
<p>In reality this rule would insert more <code>-{…}</code> and
<code>+{…}</code> than I’ve written here, but I’m writing these examples
manually so take them with a grain of salt. Let’s take it further and
say that the string has actually been moved. Then we should indeed give
it a number to reference it later:</p>
<p>Before:</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>¹{main <span class="ot">=</span> ²{<span class="kw">do</span> <span class="fu">putStrLn</span> ³{<span class="st">&quot;Write your name!&quot;</span>}</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>              name <span class="ot">&lt;-</span> <span class="fu">getLine</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>              <span class="fu">print</span> name}}</span></code></pre></div>
<p>After:</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>¹{main <span class="ot">=</span> <span class="op">+</span>{<span class="kw">do</span> args <span class="ot">&lt;-</span> getArgs</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>              <span class="kw">case</span> args <span class="kw">of</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>                [] <span class="ot">-&gt;</span> ²{<span class="kw">do</span> <span class="fu">putStrLn</span> <span class="op">+</span>{greeting}</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>                           name <span class="ot">&lt;-</span> <span class="fu">getLine</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>                           <span class="fu">print</span> name}</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>                _ <span class="ot">-&gt;</span> runWithArgs args}</span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">+</span>{<span class="kw">where</span> greeting <span class="ot">=</span> ³{<span class="st">&quot;Write your name!&quot;</span>}}}</span></code></pre></div>
<p>Again, I don’t think anybody is going to find this confusing. The
node<sub>3</sub> has moved into a <code>where</code> clause, which has
been named <code>greeting</code> and referenced in place of its original
place.</p>
<p>Am I making obvious sense, here? It’s not a particularly novel
display, it states what happened syntactically, precisely. With a UI,
you could expand/collapse nodes in a nested fashion or “explode” all the
pieces into a flat list of numbered or +’d or -’d nodes, or just narrow
down to one specific interesting expression, like</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>²{<span class="kw">do</span> <span class="fu">putStrLn</span> <span class="op">+</span>{greeting}</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>     name <span class="ot">&lt;-</span> <span class="fu">getLine</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>     <span class="fu">print</span> name}</span></code></pre></div>
<p>If you’re sufficiently nerd-sniped to find this interesting and
do-able, then I invite you to go ahead and give it a go. I’d love to see
a prototype. I don’t plan on implementing this in the near or distant
future, so we won’t be toe stepping.</p>
<h2 id="the-reduced-semantic-diff">The reduced semantic diff</h2>
<p>If you’re still reading by this point, let me try to entice you with
ambitious ideas. Take the above approach, everything we just laid out,
but let’s put an additional step in there: instead of diffing Haskell’s
abstract syntax tree, diff the Core.</p>
<p>If you compile the below with GHC,</p>
<div class="sourceCode" id="cb11"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">case</span> <span class="dt">Just</span> () <span class="kw">of</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>         <span class="dt">Just</span> () <span class="ot">-&gt;</span> <span class="fu">print</span> <span class="st">&quot;Hey!&quot;</span></span></code></pre></div>
<p>The external core is:</p>
<div class="sourceCode" id="cb12"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="op">%</span><span class="kw">module</span> main<span class="op">:</span><span class="dt">Main</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>  main<span class="op">:</span><span class="ot">main5 ::</span> (<span class="dt">ZMZN</span> <span class="dt">Char</span>) <span class="ot">=</span> unpackCStringzh (<span class="st">&quot;Hey!&quot;</span><span class="ot">::</span><span class="dt">Addrzh</span>);</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>  main<span class="op">:</span><span class="ot">main4 ::</span> (<span class="dt">ZMZN</span> <span class="dt">Char</span>) <span class="ot">=</span> <span class="dt">ZC</span> <span class="op">@</span> <span class="dt">Char</span> base<span class="op">:</span>zdfShowChar1 (<span class="dt">ZMZN</span> <span class="op">@</span> <span class="dt">Char</span>);</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>  main<span class="op">:</span><span class="ot">main3 ::</span> (<span class="dt">ZMZN</span> <span class="dt">Char</span>) <span class="ot">=</span> base<span class="op">:</span>showLitString main<span class="op">:</span>main5 main<span class="op">:</span>main4;</span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>  main<span class="op">:</span><span class="ot">main2 ::</span> (<span class="dt">ZMZN</span> <span class="dt">Char</span>) <span class="ot">=</span> <span class="dt">ZC</span> <span class="op">@</span> <span class="dt">Char</span> base<span class="op">:</span>zdfShowChar1 main<span class="op">:</span>main3;</span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>  main<span class="op">:</span><span class="ot">main1 ::</span> (<span class="dt">Statezh</span> <span class="dt">RealWorld</span>) <span class="ot">-&gt;</span> (<span class="dt">Z2H</span> ((<span class="dt">Statezh</span> <span class="dt">RealWorld</span>)) <span class="dt">Z0T</span>) <span class="ot">=</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a>    \ (<span class="ot">etaB1::</span>(<span class="dt">Statezh</span> <span class="dt">RealWorld</span>)) <span class="ot">-&gt;</span></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a>      base<span class="op">:</span>hPutStr2 base<span class="op">:</span>stdout main<span class="op">:</span>main2 <span class="dt">True</span> etaB1;</span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>  main<span class="op">:</span><span class="ot">main ::</span> (<span class="dt">IO</span> <span class="dt">Z0T</span>) <span class="ot">=</span> <span class="op">%</span>cast (main<span class="op">:</span>main1) (<span class="op">%</span>sym ((<span class="dt">NTCoZCIO</span> <span class="dt">Z0T</span>)));</span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a>  main<span class="op">:</span><span class="ot">main6 ::</span> (<span class="dt">Statezh</span> <span class="dt">RealWorld</span>) <span class="ot">-&gt;</span> (<span class="dt">Z2H</span> ((<span class="dt">Statezh</span> <span class="dt">RealWorld</span>)) <span class="dt">Z0T</span>) <span class="ot">=</span></span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a>    \ (<span class="ot">etaXb::</span>(<span class="dt">Statezh</span> <span class="dt">RealWorld</span>)) <span class="ot">-&gt;</span></span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true" tabindex="-1"></a>      base<span class="op">:</span>runMainIO1 <span class="op">@</span> <span class="dt">Z0T</span> (<span class="op">%</span>cast (main<span class="op">:</span>main1) (<span class="op">%</span>sym ((<span class="dt">NTCoZCIO</span> <span class="dt">Z0T</span>))))</span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true" tabindex="-1"></a>                       etaXb;</span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true" tabindex="-1"></a>  main<span class="op">:</span><span class="dt">ZCmain</span><span class="ot"> ::</span> (<span class="dt">IO</span> <span class="dt">Z0T</span>) <span class="ot">=</span> <span class="op">%</span>cast (main<span class="op">:</span>main6) (<span class="op">%</span>sym ((<span class="dt">NTCoZCIO</span> <span class="dt">Z0T</span>)));</span></code></pre></div>
<p>You can see that the pointless <code>case</code> has been removed.
This is the bread and butter of Core simplification. But if I remove the
case myself, the Core is exactly the same. This is redundant semantic
content, which is why GHC removed it.</p>
<p>If someone made a change like this in a real codebase which removed
some redundant <em>semantic</em> content, not just syntactical
redundancy, your diff could show it like that. In other words, nothing
important semantically actually happened here.</p>
<p>In fact, if I refactored a bunch of code, re-organized a bit, does my
next colleague really want to read through all the syntax tree just to
see the crux of what changed? Sometimes, but not always. Sometimes, they
just want to see the precise thing that will change at runtime.</p>
<p>It might actually be insane, with big blow ups in code difference for
minute high-level changes, or it might be great for teams caring about
performance. Difficult to know until you try it. You can also do a
source-mapping back to the original Haskell source, for a more
interesting display.</p>
<p>If you want to implement this, I would love to see any results.</p>
<h2 id="the-typed-diff">The typed diff</h2>
<p>Okay, you’re still reading so you’re pretty easily nerd sniped. Let’s
continue with the ideas. Another type of difference between two sources
is the types of expressions in there. Consider:</p>
<div class="sourceCode" id="cb13"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">let</span> x <span class="ot">=</span> [<span class="dv">1</span>,<span class="dv">2</span>,<span class="dv">3</span>]</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>       <span class="kw">in</span> <span class="fu">print</span> (x <span class="op">&lt;&gt;</span> x)</span></code></pre></div>
<p>Now you change the code to:</p>
<div class="sourceCode" id="cb14"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">let</span> x <span class="ot">=</span> myFancyMonoid</span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>       <span class="kw">in</span> <span class="fu">print</span> (x <span class="op">&lt;&gt;</span> x)</span></code></pre></div>
<p>Our structural diff laid out earlier will show this:</p>
<div class="sourceCode" id="cb15"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">let</span> x <span class="ot">=</span> <span class="op">-</span>{[<span class="dv">1</span>,<span class="dv">2</span>,<span class="dv">3</span>]}</span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>       <span class="kw">in</span> <span class="fu">print</span> (x <span class="op">&lt;&gt;</span> x)</span></code></pre></div>
<p>After:</p>
<div class="sourceCode" id="cb16"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">let</span> x <span class="ot">=</span> <span class="op">+</span>{myFancyMonoid}</span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>       <span class="kw">in</span> <span class="fu">print</span> (x <span class="op">&lt;&gt;</span> x)</span></code></pre></div>
<p>But actually, more things have changed here. As a result of the
different monoid instance, the <code>print (x &lt;&gt; x)</code> will do
something different. Maybe it’s a <code>*</code> rather than
<code>+</code>, maybe it’s a number, whatever. Maybe that expression is
used in a more interesting way than merely printing it. What’s the real
diff?</p>
<div class="sourceCode" id="cb17"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">let</span> {<span class="ot">x::</span>[<span class="dt">Integer</span>]} <span class="ot">=</span> <span class="op">-</span>{[<span class="dv">1</span>,<span class="dv">2</span>,<span class="dv">3</span>]}</span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>       <span class="kw">in</span> <span class="fu">print</span> {{(x <span class="op">&lt;&gt;</span> x)}<span class="ot">::</span>[<span class="dt">Integer</span>]}</span></code></pre></div>
<p>After:</p>
<div class="sourceCode" id="cb18"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">let</span> {<span class="ot">x::</span><span class="dt">MyFancyMonoid</span>} <span class="ot">=</span> <span class="op">+</span>{myFancyMonoid}</span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>       <span class="kw">in</span> <span class="fu">print</span> {(x <span class="op">&lt;&gt;</span> x)}<span class="ot">::</span><span class="dt">MyFancyMonoid</span>}</span></code></pre></div>
<p>Or something like that. I’m being hand-wavey in the display, here.
The real difference is that we’ve changed the type of <code>x</code>.
It’s an important change, which has semantic meaning. My ideas are more
vague here. I haven’t thought through many scenarios of how to represent
this. But one thing is clear: a diff of types can actually be useful and
interesting.</p>
<h2 id="the-editing-diff">The editing diff</h2>
<p>The diffs above are all examples of “cold” diffs. Calculating the
difference between two files as-is. If you’re in a structured editor
like <a href="http://peaker.github.io/lamdu/">Lamdu</a>, then you don’t
have to do cold diffs and figure out and guess at what happened. You
know exactly what happened. This node was raised here, this variable was
renamed there, etc. But if you want to work on that, you pretty much
have to work on Lamdu.</p>
<h2 id="summary">Summary</h2>
<p>In summary I’ve intentionally listed increasingly more wacky diff
ideas, from the familiar to the fairly novel. My general approach to
tooling is progressive: start with the simplest working implementation
then step up. Structured-haskell-mode is an example of this. It’s no
Lamdu, and it’s no vanilla text-based mode. It’s a stepping stone
inbetween. The impedance to try SHM is lower.</p>
<p>In the same way, maybe we can start with the abstract syntax diff,
let people become acclimatized to it, let it stabilize, get it
integrated into things like Git, and then work our way up from
there.</p>
<p>If nobody bothers trying out these ideas, I’ll probably end up doing
them myself eventually, but I thought I’d put the suggestion out there
first.</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>In favour of writing programs that
concern themselves with things other than Haskell for once!<a
href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2014-04-01 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Tue, 01 Apr 2014 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Reloading running code in GHCi]]></title><link>https://chrisdone.com/posts/ghci-reload</link><guid>https://chrisdone.com/posts/ghci-reload</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Reloading running code in GHCi</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Reloading running code in GHCi</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Something I’ve been using over the past couple weeks in a personal
Yesod web site is a way to reload the code while the server is still
running in GHCi. I saw in <a
href="http://www.yesodweb.com/blog/2014/03/gsoc-proposals">Greg
Weber’s</a> blog post about a “reload mode” for web servers and thought
I’d share my approach. GHCi already supports reloading of code, it just
doesn’t know it.</p>
<p>The problem with doing this in GHCi is always that the
<code>:load</code> and <code>:reload</code> commands will clear out any
bindings made in the REPL. This means that even if you start your web
server in a separate thread—and it will stay running between reloads—you
have no way to <em>update</em> or <em>talk</em> to it directly.</p>
<p>That’s why I wrote a package called <a
href="http://hackage.haskell.org/package/foreign-store">foreign-store</a>.
Its purpose is to make a stable pointer to some Haskell value and store
it at an index, and then keep hold of it in C. Later, it can provide
that stable pointer by that index. That’s its whole purpose. Because the
C code is unaffected by GHCi’s reloads, the pointers are retained, and
they are not garbage collected, because that is the point of a stable
pointer.</p>
<p>Now, with that created, it’s possible to run a web server, keep hold
of the thread id, reload some code in GHCi, kill that thread and restart
it. Another option is to keep an <code>IORef</code> of the web handler
itself, and then update the <code>IORef</code> instead. In my use of it
so far, this has worked flawlessly.</p>
<p>I made <a href="https://github.com/chrisdone/ghci-reload-demo">a demo
project</a> with a README explaining the (simple) approach. The short of
it is that I can make some change to a Haskell module in my web project,
hit a key (F12), and instantaneously see the browser page refresh with
the new update. This is pretty much optimal for me.</p>
<p>It doesn’t end at web servers, of course. Any kind of long-running
program that you would like to keep running while developing is fair
game. For example, an IRC server. Why not run the server and also
inspect the innards of its state while it’s running, and also update the
message handler? I’ve done this with my <a
href="https://github.com/chrisdone/hulk">Hulk</a> IRC server before. You
can inspect the data structures, query the types of things, etc. all
from the REPL.<a href="#fn1" class="footnote-ref" id="fnref1"
role="doc-noteref"><sup>1</sup></a></p>
<p>If you want to get really funky, you can try using the continuation
monad to implement <a
href="http://www.gigamonkeys.com/book/beyond-exception-handling-conditions-and-restarts.html">Common
Lisp’s restarts.</a> Restarts are especially handy for when you’re
running some long IO process and it bails out. You want to be able to
correct the code and the continue from where you left off. Restarts let
you do that.</p>
<p>I shouldn’t have to tell anyone this but just in case: <em>don’t use
this in production</em>.</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Of course, there aren’t many of us
Haskellers who live in the REPL like Smalltalkers and Lispers do. Many
Haskellers never even launch GHCi while developing.<a href="#fnref1"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2014-03-16 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sun, 16 Mar 2014 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Attempto Controlled English]]></title><link>https://chrisdone.com/posts/attempto-controlled-english</link><guid>https://chrisdone.com/posts/attempto-controlled-english</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Attempto Controlled English</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Attempto Controlled English</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p><a
href="http://en.wikipedia.org/wiki/Attempto_Controlled_English">Attempto
Controlled English</a> is a formally defined unambiguous language which
is a subset of the English language. It’s pretty sweet.</p>
<p>I’ve known about it for some time, but I never fiddled with it
because the standard implementation setup is rather elaborate. I wanted
a nice, simple package in Haskell which would define a parser and a
printer only, much like haskell-src-exts does. That way I can use ACE to
parse some simple English for all sorts of purposes<a href="#fn1"
class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a>,
with a simple familiar API that I can peruse on Hackage. Partly it’s
also a good learning experience.</p>
<p>So I went through the paper The Syntax of Attempto Controlled English
to see whether it was comprehensive enough to write a parsec parser out
of. It was! I first wrote a <a
href="https://github.com/chrisdone/ace/blob/master/src/ACE/Tokenizer.hs">tokenizer</a>
in with Attoparsec and <a
href="https://github.com/chrisdone/ace/blob/master/test/Main.hs#L39">wrote
some tests</a>. From those tokens I produced a set of <a
href="https://github.com/chrisdone/ace/blob/master/src/ACE/Combinators.hs">combinators</a>
for Parsec, then I wrote a <a
href="https://github.com/chrisdone/ace/blob/master/src/ACE/Parsers.hs">parser</a>.
While writing the parser I produced a set of <a
href="https://github.com/chrisdone/ace/blob/master/test/Main.hs#L67">test-cases</a>
for each grammar production. Finally, I wrote a <a
href="https://github.com/chrisdone/ace/blob/master/src/ACE/Pretty.hs">pretty
printer</a>, and <a
href="https://github.com/chrisdone/ace/blob/master/test/Main.hs#L599">wrote
some tests</a> to check that
<code>print . parse . print . parse = id</code>.</p>
<p>Newbies to Haskell parsing might find it an interesting use-case
because it tokenizes with <a
href="http://hackage.haskell.org/package/attoparsec">Attoparsec</a>
(from Text) and then parses its own token type (<a
href="http://hackage.haskell.org/package/ace-0.3/docs/ACE-Types-Tokens.html">Token</a>)
with <a href="http://hackage.haskell.org/package/parsec">Parsec</a>. A
common difficulty is to avoid parsing from <code>String</code> in
Parsec, which most tutorials use as their demonstration.</p>
<p>The Hackage package is <a
href="http://hackage.haskell.org/package/ace">here</a>. I find the
documentation interesting to browse. I tried to include helpful examples
for the production rules. You shouldn’t have to know syntax theory to
use this library.</p>
<p>Here is an ACE sample. We can parse the sentence “a &lt;noun&gt;
&lt;intrans-verb&gt;” like this:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> parsed specification <span class="st">&quot;a &lt;noun&gt; &lt;intrans-verb&gt;.&quot;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Right</span> (<span class="dt">Specification</span> (<span class="dt">SentenceCoord</span> (<span class="dt">SentenceCoord_1</span> (<span class="dt">SentenceCoord_2</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>(<span class="dt">SentenceCoord_3</span> (<span class="dt">TopicalizedSentenceComposite</span> (<span class="dt">CompositeSentence</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>(<span class="dt">Sentence</span> (<span class="dt">NPCoordUnmarked</span> (<span class="dt">UnmarkedNPCoord</span> (<span class="dt">NP</span> (<span class="dt">SpecifyDeterminer</span> <span class="dt">A</span>)</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>(<span class="dt">N&#39;</span> <span class="dt">Nothing</span> (<span class="dt">N</span> <span class="st">&quot;&lt;noun&gt;&quot;</span>) <span class="dt">Nothing</span> <span class="dt">Nothing</span> <span class="dt">Nothing</span>)) <span class="dt">Nothing</span>))</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>(<span class="dt">VPCoordVP</span> (<span class="dt">VP</span> (<span class="dt">V&#39;</span> <span class="dt">Nothing</span> (<span class="dt">ComplVIV</span> (<span class="dt">IntransitiveV</span> <span class="st">&quot;&lt;intrans-verb&gt;&quot;</span>))</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>[])))))) <span class="dt">Nothing</span>) <span class="dt">Nothing</span>) <span class="dt">Nothing</span>) <span class="dt">Nothing</span>) <span class="dt">Nothing</span>)</span></code></pre></div>
<p>Anything to do with vocabulary is written as
<code>&lt;foo&gt;</code>. The parser actually takes <a
href="http://hackage.haskell.org/package/ace-0.3/docs/ACE-Parsers.html#t:ACEParser">a
record of parsers</a> so that you can provide your own parsers for each
type of word. These words are not of interest to the grammar, and your
particular domain might support different types of words.</p>
<p>If we pretty print the parsed phrase, we get:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="fu">fmap</span> pretty (parsed specification <span class="st">&quot;a &lt;noun&gt; &lt;intrans-verb&gt;.&quot;</span>)</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Right</span> <span class="st">&quot;a &lt;noun&gt; &lt;intrans-verb&gt;.&quot;</span></span></code></pre></div>
<p>I.e. we get back what we put in. I also wrote a HTML printer. A more
complicated sentence demonstrates the output:</p>
<blockquote>
<p>for each &lt;noun&gt; &lt;var&gt; if a &lt;noun&gt; that
&lt;trans-verb&gt; some &lt;noun&gt; and &lt;proper-name&gt;’s
&lt;noun&gt; &lt;trans-verb&gt; 2 &lt;noun&gt; then some &lt;noun&gt;
&lt;intrans-verb&gt; and some &lt;noun&gt; &lt;distrans-verb&gt; a
&lt;intrans-adj&gt; &lt;noun&gt; &lt;proper-name&gt;’s &lt;noun&gt;
&lt;adverb&gt;.</p>
</blockquote>
<p>Can be printed with</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="fu">fmap</span> (renderHtml <span class="op">.</span> toMarkup) <span class="op">.</span> parsed specification</span></code></pre></div>
<p>and the output is:</p>
<blockquote>
<p>
<span class="ace-specification" title="specification"><span
class="ace-sentence-or" title="sentence-or"><span
class="ace-sentence-and" title="sentence-and"><span
class="ace-sentence-or" title="sentence-or"><span
class="ace-sentence-and" title="sentence-and"><span
class="ace-universal-topic" title="universal-topic"><span
class="ace-universal-quantor" title="universal-quantor"><span
class="ace-universal-quantor" title="universal-quantor">for
each</span></span> <span class="ace-n_" title="n_"><span class="ace-n"
title="n">&lt;noun&gt;</span> <span class="ace-appos-coord"
title="appos-coord"><span class="ace-apposition"
title="apposition"><span class="ace-variable"
title="variable">&lt;var&gt;</span></span></span></span></span> <span
class="ace-sentence-or" title="sentence-or"><span
class="ace-sentence-and" title="sentence-and"><span
class="ace-sentence-or" title="sentence-or"><span
class="ace-sentence-and" title="sentence-and"><span
class="ace-conditional" title="conditional"><span class="ace-if-if"
title="if-if">if </span><span class="ace-sentence-or"
title="sentence-or"><span class="ace-sentence-and"
title="sentence-and"><span class="ace-sentence-or"
title="sentence-or"><span class="ace-sentence-and"
title="sentence-and"><span class="ace-sentence" title="sentence"><span
class="ace-npcoord" title="npcoord"><span class="ace-np"
title="np"><span class="ace-specifier" title="specifier"><span
class="ace-determiner" title="determiner">a</span></span> <span
class="ace-n_" title="n_"><span class="ace-n"
title="n">&lt;noun&gt;</span> <span class="ace-relative-clause-coord"
title="relative-clause-coord"><span class="ace-relative-clause"
title="relative-clause"><span class="ace-relative-clause-that"
title="relative-clause-that">that </span><span class="ace-vp-coord"
title="vp-coord"><span class="ace-vp" title="vp"><span class="ace-v_"
title="v_"><span class="ace-compl-v" title="compl-v"><span
class="ace-transitive-v" title="transitive-v">&lt;trans-verb&gt;</span>
<span class="ace-npcoord" title="npcoord"><span class="ace-np"
title="np"><span class="ace-specifier" title="specifier"><span
class="ace-determiner" title="determiner">some</span></span> <span
class="ace-n_" title="n_"><span class="ace-n"
title="n">&lt;noun&gt;</span></span></span><span
class="ace-unmarked-npcoord-and" title="unmarked-npcoord-and"> and
</span><span class="ace-np" title="np"><span class="ace-specifier"
title="specifier"><span class="ace-possessive-np-coord"
title="possessive-np-coord"><span class="ace-proper-name"
title="proper-name">&lt;proper-name&gt;</span><span
class="ace-genitive-tail" title="genitive-tail"><span
class="ace-genitive-tail" title="genitive-tail"><span
class="ace-saxon-genitive-marker"
title="saxon-genitive-marker">'s</span></span></span></span></span>
<span class="ace-n_" title="n_"><span class="ace-n"
title="n">&lt;noun&gt;</span></span></span></span></span></span></span></span></span></span></span></span></span>
<span class="ace-vp-coord" title="vp-coord"><span class="ace-vp"
title="vp"><span class="ace-v_" title="v_"><span class="ace-compl-v"
title="compl-v"><span class="ace-transitive-v"
title="transitive-v">&lt;trans-verb&gt;</span> <span class="ace-npcoord"
title="npcoord"><span class="ace-np" title="np"><span
class="ace-specifier" title="specifier"><span class="ace-number-p"
title="number-p">2</span></span> <span class="ace-n_" title="n_"><span
class="ace-n"
title="n">&lt;noun&gt;</span></span></span></span></span></span></span></span></span></span></span></span></span><span
class="ace-if-then" title="if-then"> then </span><span
class="ace-sentence-or" title="sentence-or"><span
class="ace-sentence-and" title="sentence-and"><span
class="ace-sentence-or" title="sentence-or"><span
class="ace-sentence-and" title="sentence-and"><span class="ace-sentence"
title="sentence"><span class="ace-npcoord" title="npcoord"><span
class="ace-np" title="np"><span class="ace-specifier"
title="specifier"><span class="ace-determiner"
title="determiner">some</span></span> <span class="ace-n_"
title="n_"><span class="ace-n"
title="n">&lt;noun&gt;</span></span></span></span> <span
class="ace-vp-coord" title="vp-coord"><span class="ace-vp"
title="vp"><span class="ace-v_" title="v_"><span class="ace-compl-v"
title="compl-v"><span class="ace-intransitive-v"
title="intransitive-v">&lt;intrans-verb&gt;</span></span></span></span></span></span><span
class="ace-sentence-op" title="sentence-op"> and </span><span
class="ace-sentence-and" title="sentence-and"><span class="ace-sentence"
title="sentence"><span class="ace-npcoord" title="npcoord"><span
class="ace-np" title="np"><span class="ace-specifier"
title="specifier"><span class="ace-determiner"
title="determiner">some</span></span> <span class="ace-n_"
title="n_"><span class="ace-n"
title="n">&lt;noun&gt;</span></span></span></span> <span
class="ace-vp-coord" title="vp-coord"><span class="ace-vp"
title="vp"><span class="ace-v_" title="v_"><span class="ace-compl-v"
title="compl-v"><span class="ace-distransitive-v"
title="distransitive-v">&lt;distrans-verb&gt;</span> <span
class="ace-npcoord" title="npcoord"><span class="ace-np"
title="np"><span class="ace-specifier" title="specifier"><span
class="ace-determiner" title="determiner">a</span></span> <span
class="ace-n_" title="n_"><span class="ace-adjective-coord"
title="adjective-coord"><span class="ace-intransitive-adjective"
title="intransitive-adjective">&lt;intrans-adj&gt;</span></span> <span
class="ace-n" title="n">&lt;noun&gt;</span></span></span></span> <span
class="ace-npcoord" title="npcoord"><span class="ace-np"
title="np"><span class="ace-specifier" title="specifier"><span
class="ace-possessive-np-coord" title="possessive-np-coord"><span
class="ace-proper-name"
title="proper-name">&lt;proper-name&gt;</span><span
class="ace-genitive-tail" title="genitive-tail"><span
class="ace-genitive-tail" title="genitive-tail"><span
class="ace-saxon-genitive-marker"
title="saxon-genitive-marker">'s</span></span></span></span></span>
<span class="ace-n_" title="n_"><span class="ace-n"
title="n">&lt;noun&gt;</span></span></span></span></span> <span
class="ace-v-modifier" title="v-modifier"><span class="ace-adverb-coord"
title="adverb-coord"><span class="ace-adverb"
title="adverb">&lt;adverb&gt;</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span
class="ace-period" title="period">.</span></span>
</p>
</blockquote>
<p>The colors and parenthesizing embellishments are just to demonstrate
what can be done. I’m not sure this output would actually be readable in
reality.</p>
<p>This is a good start. I’m going to leave it for now and come back to
it later. The next steps are: (1) write more tests, (2) add feature
restrictions and related type information in the AST, (3) add a couple
sample vocabularies, (4) implement the interrogative (useful for query
programs) and imperative moods (useful for writing instructions,
e.g. text-based games).</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Specifically, I want to use this to
experiment with translating it to logic-language databases and queries,
and from that produce interactive tutorials, and perhaps experiment with
a MUD-like game that utilizes it.<a href="#fnref1" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2014-02-24 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Mon, 24 Feb 2014 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Emacs, Notmuch and Offlineimap]]></title><link>https://chrisdone.com/posts/emacs-mail</link><guid>https://chrisdone.com/posts/emacs-mail</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Emacs, Notmuch and Offlineimap</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Emacs, Notmuch and Offlineimap</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>I kind of hate writing in anything other than Emacs. Especially
email. Writing email in Emacs with <code>message-mode</code> is lovely.
I get all my editing facilities and any key bindings that I want. More
than that, generally managing my mail in Emacs rather than relying on
what’s available in the GMail UI is desirable.</p>
<p>So I moved my email reading to Emacs. Here’s how I did it.</p>
<h1 id="offlineimap">Offlineimap</h1>
<p>First, I installed offlineimap. Second, I made a
<code>~/.offlineimaprc</code> configuration file:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode python"><code class="sourceCode python"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>[general]</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>accounts <span class="op">=</span> ChrisGmail</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>[Account ChrisGmail]</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>localrepository <span class="op">=</span> Local</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>remoterepository <span class="op">=</span> ChrisDoneGmail</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>[Repository Local]</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="bu">type</span> <span class="op">=</span> Maildir</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>localfolders <span class="op">=</span> <span class="op">~/</span>Mail</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>[Repository ChrisDoneGmail]</span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a><span class="bu">type</span> <span class="op">=</span> Gmail</span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>maxconnections<span class="op">=</span><span class="dv">1</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>remoteuser <span class="op">=</span> blog<span class="op">@</span>chrisdone.com</span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>realdelete<span class="op">=</span>no</span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>folderfilter <span class="op">=</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>  <span class="kw">lambda</span> foldername:</span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>    foldername <span class="kw">in</span> [<span class="st">&#39;[Google Mail]/All Mail&#39;</span>,</span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>                   <span class="st">&#39;[Google Mail]/Sent Mail&#39;</span>]</span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>nametrans <span class="op">=</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>  <span class="kw">lambda</span> foldername:</span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>    re.sub(<span class="st">&#39;^\[Google Mail\]/All Mail$&#39;</span>, <span class="st">&#39;all&#39;</span>,</span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>       re.sub(<span class="st">&#39;^\[Google Mail\]/Sent Mail$&#39;</span>, <span class="st">&#39;sent&#39;</span>,</span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a>         foldername))</span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a>sslcacertfile <span class="op">=</span> <span class="op">/</span>etc<span class="op">/</span>ssl<span class="op">/</span>certs<span class="op">/</span>ca<span class="op">-</span>certificates.crt</span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a>remotepass <span class="op">=</span> <span class="op">&lt;</span>my password here<span class="op">&gt;</span></span></code></pre></div>
<p><em>Note: if you’re copy-pasting this file, you will need to put the
<code>folderfilter</code> and <code>nametrans</code> on one line. Python
doesn’t like multi-line lambdas.</em></p>
<p>I ran</p>
<pre><code>$ offlineimap</code></pre>
<p>I let that run for 10 hours to download all 19K messages from my 8~
year old GMail account.</p>
<h1 id="notmuch">Notmuch</h1>
<p>To index, tag and search that mail, I installed Notmuch. I configured
it using <code>notmuch config</code> and followed the guide.</p>
<p>My current configuration (<code>~/.notmuch-config</code>)
contains:</p>
<pre><code>[database]
path=/home/chris/Mail

[new]
tags=unread;inbox
ignore=

[search]
exclude_tags=deleted;spam</code></pre>
<p>I ran</p>
<pre><code>$ notmuch new</code></pre>
<p>to import all new mail from my database, which was the 19K messages.
I think that took about 5 minutes.</p>
<h1 id="post-sync-hook">Post-sync hook</h1>
<p>Rather than manually running <code>offlineimap</code> and
<code>notmuch new</code> all the time, instead you can put</p>
<pre><code>autorefresh = 1</code></pre>
<p>under your <code>[Account]</code> setting in
<code>.offlineimaprc</code>. That will make Offlineimap run in one
continuous process. I run it in screen for now, but I will probably add
it as a system script when I’m feeling masochistic.</p>
<p>Another thing you can add to the <code>[Account]</code> section is a
<code>postsynchook</code>:</p>
<pre><code>postsynchook = /usr/bin/offlineimap-postsync</code></pre>
<p>That path points to my post-sync script. It contains:</p>
<pre><code>notmuch new</code></pre>
<p>And then a bunch of tagging commands.</p>
<h1 id="tagging">Tagging</h1>
<p>In GMail I would organize everything with filters and tags. I like
this approach, so I took the same with Notmuch. First, mailing lists
skip the inbox and are tagged. For example:</p>
<pre><code>notmuch tag -inbox +ghc-devs to:ghc-devs@haskell.org tag:inbox
notmuch tag -inbox +ghc-users to:glasgow-haskell-users@haskell.org tag:inbox
notmuch tag -inbox +haskell-cafe to:haskell-cafe@haskell.org tag:inbox
notmuch tag -inbox +haskell-beginners to:beginners@haskell.org tag:inbox</code></pre>
<p>In other words, “remove the <code>inbox</code> tag, and add the
<code>ghc-devs</code> tag for all messages addressed to
<code>ghc-devs@haskell.org</code> in my inbox.”</p>
<p>When I receive an electric bill I tag it and flag it:</p>
<pre><code>notmuch tag +flagged +bill from:serviziweb@trenta.it tag:inbox</code></pre>
<p>I also have some inbox skipping filters from lists or people I don’t
have interest in seeing in my inbox.</p>
<p>Then I have 69 deletion filters on various mailing lists I never
signed up for and am unable to unsubscribe from.</p>
<p>In all I have about 130 filters. I copied them from my GMail account
and ran some keyboard macros to conver them to Notmuch’s tagging
style.</p>
<h1 id="emacs">Emacs</h1>
<p>Once you have Notmuch setup, you can use notmuch.el and it works out
of the box for reading and searching mail. The mode has some strange
choices for its defaults, so I copied <a
href="https://github.com/chrisdone/notmuch">the repo</a> with full
intention for patching it heavily in the future, and I made some further
configurations <a
href="https://github.com/chrisdone/chrisdone-emacs/blob/master/config/notmuch.el">in
a separate file</a>.</p>
<p>The mode is pretty self-explanatory, it just has very silly
keybindings. Otherwise it works very well.</p>
<h1 id="sending-email">Sending email</h1>
<p>One thing that doesn’t work out of the box is sending mail. For this
I configured my mail user agent:</p>
<pre><code>(setq mail-user-agent &#39;message-user-agent)</code></pre>
<p>Set my default sending details:</p>
<pre><code>(setq user-mail-address &quot;blog@chrisdone.com&quot;
      user-full-name &quot;Chris Done&quot;)</code></pre>
<p>Configured the SMTP server info for GMail:</p>
<pre><code>(setq smtpmail-stream-type &#39;ssl
      smtpmail-smtp-server &quot;smtp.gmail.com&quot;
      smtpmail-smtp-service 465)</code></pre>
<p>Then I made a <code>~/.authinfo</code> file and put in:</p>
<pre><code>machine smtp.gmail.com login chrisdone port 465 password &quot;&lt;password here&gt;&quot;</code></pre>
<h1 id="suave-desktop-panel">Suave desktop panel</h1>
<p>I also <a
href="https://github.com/chrisdone/chrisdone-xmonad/blob/b097b98ac044fc1cfa0f2bccd9abe9803b6ac8c4/src/XMonad/Suave/Window.hs#L69">added
the current inbox status to my Suave XMonad desktop panel</a>. There’s a
screenshot <a href="http://chrisdone.com/suave-1.png">here</a>. The
inbox display is in the centre.</p>
<h1 id="summary">Summary</h1>
<p>In summary I moved the client part of my GMail use from the GMail web
client to Emacs. Now I can read and write mail completely in Emacs, and
I can see when new mail has arrived in my panel.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2014-02-08 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sat, 08 Feb 2014 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Pure IO monad and Try Haskell]]></title><link>https://chrisdone.com/posts/pure-io-tryhaskell</link><guid>https://chrisdone.com/posts/pure-io-tryhaskell</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Pure IO monad and Try Haskell</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Pure IO monad and Try Haskell</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p><strong>tl;dr: <a href="http://tryhaskell.org/">Try Haskell</a> now
has simple I/O built on a pure IO monad.</strong></p>
<p>I wrote Try Haskell in 2010. I didn’t really update the codebase
since. It was rather poor, but had generally been stable enough. Last
week I finally set some time aside to rewrite it from scratch (barring
the tutorial part). In doing so I gave it a fresh design, rewrote the
backend and stopped using my patched version of mueval (faster, but less
stable).</p>
<p>Aside from reproducing the functionality, I afterwards added a new
piece of functionality: typing in a function name (or composition of
functions) will simply show the generalized type of that expression.
This removes the need for an explicit <code>:t</code> and is more
friendly to newbies who would rather see something useful than an
error.<a href="#fn1" class="footnote-ref" id="fnref1"
role="doc-noteref"><sup>1</sup></a></p>
<p>After that, Bob Ippolito requested that some simple IO operations be
made available, like <code>getLine</code>, <code>putStrLn</code>, etc.
People have requested this in the past, but it seemed more complicated
back then. This time, it seemed rather easy to support simple
input/output. The console library already supports continued prompts, so
the question became simply how to do safe IO.</p>
<p>As Haskellers worth their salt know, the IO monad is not special.
Examples of a monad ADT for newbies are available<a href="#fn2"
class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a><a
href="#fn3" class="footnote-ref" id="fnref3"
role="doc-noteref"><sup>3</sup></a>, and we know that pre-monad Haskell
IO was modelled as a request/response system<a href="#fn4"
class="footnote-ref" id="fnref4" role="doc-noteref"><sup>4</sup></a>
before it got updated in Haskell 1.3<a href="#fn5" class="footnote-ref"
id="fnref5" role="doc-noteref"><sup>5</sup></a> Fuelled by the nerdiness
factor of this, and that it was the weekend, I rose to the challenge. I
knew it wouldn’t be hard, but it would be fun with a real use-case (Try
Haskell’s REPL).</p>
<p>My constraints were that it shouldn’t be a continuation-based
library, because I cannot have any state in Try Haskell. The server
evaluates an expression and returns the result. No other context is
kept, no process kept open, and it should return immediately. Given that
it’s rather hard to serialize closures, but rather easy to serialize a
list of inputs and outputs (aka responses/requests), I thought I’d go
that route.</p>
<p>In the end I settled on an <code>ErrorT</code> monad over a
<code>State</code> monad containing <code>Input</code> and an
<code>Output</code>. The inputs would be stdin lines as
<code>[String]</code>. The outputs would be stdout lines and either a
final value, or an interrupt.</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">runIO ::</span> <span class="dt">Input</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> a <span class="ot">-&gt;</span> (<span class="dt">Either</span> <span class="dt">Interrupt</span> a, <span class="dt">Output</span>)</span></code></pre></div>
<p>Whenever the expression being evaluated runs <code>getLine</code>, it
reads from the <code>Input</code> state and pops that line of text off
the stack. When <code>getLine</code> tries to read something and the
stack is empty, it throws an error (of the <code>ErrorT</code> monad),
returning the interrupt <code>InterruptStdin</code>. For example, here
is a return value:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> runIO (<span class="dt">Input</span> <span class="fu">mempty</span> <span class="fu">mempty</span>) (<span class="fu">return</span> ())</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>(<span class="dt">Right</span> ()</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>,<span class="dt">Output</span> {outputStdout <span class="ot">=</span> [], outputFiles <span class="ot">=</span> fromList []})</span></code></pre></div>
<p>Here is an interrupt:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> runIO (<span class="dt">Input</span> <span class="fu">mempty</span> <span class="fu">mempty</span>) (<span class="fu">putStrLn</span> <span class="st">&quot;Name:&quot;</span> <span class="op">&gt;&gt;</span> <span class="fu">getLine</span>)</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>(<span class="dt">Left</span> <span class="dt">InterruptStdin</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>,<span class="dt">Output</span> {outputStdout <span class="ot">=</span> [<span class="st">&quot;Name:\n&quot;</span>],outputFiles <span class="ot">=</span> fromList []})</span></code></pre></div>
<p>As a user of the library it is now my part of the dance to get some
input from the user and then re-call<a href="#fn6" class="footnote-ref"
id="fnref6" role="doc-noteref"><sup>6</sup></a> the same function with
more stdin input:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> runIO (<span class="dt">Input</span> [<span class="st">&quot;Chris&quot;</span>] <span class="fu">mempty</span>) (<span class="fu">putStrLn</span> <span class="st">&quot;Name:&quot;</span> <span class="op">&gt;&gt;</span> <span class="fu">getLine</span>)</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>(<span class="dt">Right</span> <span class="st">&quot;Chris&quot;</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>,<span class="dt">Output</span> {outputStdout <span class="ot">=</span> [<span class="st">&quot;Name:\n&quot;</span>],outputFiles <span class="ot">=</span> fromList []})</span></code></pre></div>
<p>I also implemented trivial exceptions:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> runIO (<span class="dt">Input</span> [<span class="st">&quot;Chris&quot;</span>] <span class="fu">mempty</span>) (throw (<span class="dt">UserError</span> <span class="st">&quot;Woo!&quot;</span>))</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>(<span class="dt">Left</span> (<span class="dt">InterruptException</span> (<span class="dt">UserError</span> <span class="st">&quot;Woo!&quot;</span>))</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>,<span class="dt">Output</span> {outputStdout <span class="ot">=</span> [],outputFiles <span class="ot">=</span> fromList []})</span></code></pre></div>
<p>After that, it was only a matter of time before I implemented some
simple file IO operations:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> runIO (<span class="dt">Input</span> [<span class="st">&quot;Chris&quot;</span>]</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>                (M.fromList [(<span class="st">&quot;/foo.txt&quot;</span>,<span class="st">&quot;Hello, World!&quot;</span>)]))</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>         (<span class="fu">readFile</span> <span class="st">&quot;/foo.txt&quot;</span>)</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>(<span class="dt">Right</span> <span class="st">&quot;Hello, World!&quot;</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>,<span class="dt">Output</span> {outputStdout <span class="ot">=</span> []</span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>        ,outputFiles <span class="ot">=</span> fromList [(<span class="st">&quot;/foo.txt&quot;</span>,<span class="st">&quot;Hello, World!&quot;</span>)]})</span></code></pre></div>
<p>That resulted in the library <a
href="https://hackage.haskell.org/package/pure-io/docs/PureIO.html">pure-io</a>
which <a
href="http://ircbrowse.net/browse/haskell?id=17223900&amp;timestamp=1389386757#t1389386757">some</a>
thought was a joke. It supports enough of the subset of IO operations
for, I think, a newbie to at least feel like they’re doing some
realistic I/O. So I added it to <a href="http://tryhaskell.org/">Try
Haskell!</a> You can now run interactive commands and write/save/list
files. Any file system operations you do will be saved in your browser’s
local storage.</p>
<p>It’s really a rather nice referentially transparent IO service. Even
if you run <code>forever (getLine &gt;&gt;= putStrLn) :: IO ()</code>,
it will run forever, but the server can be restarted inbetween. No state
is stored on the server at all, it’s all in the client. All the client
has to do is pass it back and forth when it communicates with the
server.</p>
<p>I’d recommend Haskell intermediates (perhaps not newbies) to
implement their own IO monad as a free monad, or as an mtl transformer,
partly for the geeky fun of it, and partly for the insights.</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Like “No instance for
<code>(Show (a0 -&gt; a0))</code> arising from a use of …” which is
frankly a useless message to print in a REPL and it’s strange that this
is GHCi’s default behaviour.<a href="#fnref1" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p>Johan Kiviniemi demonstrates <a
href="https://gist.github.com/ion1/7154691">an alternative monad
implementation</a> as an ADT that you interpret.<a href="#fnref2"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn3" role="doc-endnote"><p>Russell O’Connor also talks about
implementing IO as a free monad <a
href="http://r6.ca/blog/20110520T220201Z.html">here</a>.<a
href="#fnref3" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn4" role="doc-endnote"><p><a
href="http://stackoverflow.com/questions/17002119/haskell-pre-monadic-i-o">Request/response
example API on StackOverflow</a>. All shuffling between an actual
interface and the user is left to someone else to deal with.<a
href="#fnref4" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn5" role="doc-endnote"><p>“Monadic I/O has already become the
de-facto standard in the various Haskell systems. We have chosen a
fairly conservative, but extensible basic design (an IO monad with error
handling),” in <a
href="http://www.haskell.org/definition/from12to13.html#monad">the
changes list</a>.<a href="#fnref5" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn6" role="doc-endnote"><p>Yes, that means running the same
computation every time from scratch, like a transaction.<a
href="#fnref6" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2014-01-12 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sun, 12 Jan 2014 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Dijkstra on Haskell and Java]]></title><link>https://chrisdone.com/posts/dijkstra-haskell-java</link><guid>https://chrisdone.com/posts/dijkstra-haskell-java</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Dijkstra on Haskell and Java</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Dijkstra on Haskell and Java</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>In 2001, Edsger W. Dijkstra wrote a letter to the Budget Council of
The University of Texas. A <a
href="http://www.cs.utexas.edu/users/EWD/OtherDocs/To%20the%20Budget%20Council%20concerning%20Haskell.pdf">PDF
is available here</a>, I’ve typed it up so that everyone can read it.
Sadly, <a
href="http://www.cs.utexas.edu/undergraduate-program/courses/312-introduction-programming">the
curriculum was changed to Java</a>. Relatedly, the algorithmic language
Scheme was replaced by Python in MIT’s The Structure and Interpretation
of Computer Programs version <a
href="http://student.mit.edu/catalog/search.cgi?search=6.01">6.01</a>.</p>
<h2 id="to-the-members-of-the-budget-council">To the members of the
Budget Council</h2>
<p>I write to you because of a rumor of efforts to replace the
introductory programming course of our undergraduate curriculum the
functional programming language Haskell by the imperative language Java,
and because I think that in this case the Budget Council has to take
responsibility lest the decision be taken at the wrong level.</p>
<p>You see, it is no minor matter. Colleagues from outside the state
(still!) often wonder how I can survive in a place like Austin, Texas,
automatically assuming that Texas’s solid conservatism guarantees
equally solid mediocrity. My usual answer is something like “Don’t
worry. The CS Department is quite an enlightened place, for instance for
introductory programming we introduce our freshmen to Haskell”; they
react first almost with disbelief, and then with envy —usually it turns
out that their undergraduate curriculum has not recovered from the
transition from Pascal to something like C++ or Java.</p>
<p>A very practical reason for preferring functional programming in a
freshman course is that most students already have a certain familiarity
with imperative programming. Facing them with the novelty of functional
programming immediately drives home the message that there is more to
programming than they thought. And quickly they will observe that
functional programming elegantly admits solutions that are very hard (or
impossible) to formulate with the programming vehicle of their high
school days.</p>
<p>A fundamental reason for the preference is that functional programs
are much more readily appreciated as mathematical objects than
imperative ones, so that you can teach what rigorous reasoning about
programs amounts to. The additional advantage of functional programming
with “lazy evaluation” is that it provides an environment that
discourages operational reasoning<a href="#fn1" class="footnote-ref"
id="fnref1" role="doc-noteref"><sup>1</sup></a><a href="#fn2"
class="footnote-ref" id="fnref2"
role="doc-noteref"><sup>2</sup></a>.</p>
<p>Finally, in the specific comparison of Haskell versus Java, Haskell,
though not perfect, is of a quality that is several orders of magnitude
higher than Java, which is a mess (and needed an extensive advertizing
campaign and aggressive salesmanship for its commercial acceptance). It
is bad enough that, on the whole, industry accepts designs of
well-identified lousiness as “de facto” standards. Personally I think
that the University should keep the healthier alternatives alive.</p>
<p>It is not only the violin that shapes the violinist, we are all
shaped by the tools we train ourselves to use, and in this respect
programming languages have a devious influence: they shape our thinking
habits. This circumstance makes the choice of first programming language
so important. One would like to use the introductory course as a means
of creating a culture that can serve as a basis for computing science
curriculum, rather than be forced to start with a lot of unlearning (if
that is possible at all: what has become our past, forever remains so).
The choice implies a grave responsibility towards our undergraduate
students, and that is why it can not be left to a random chairman of
something but has to be done by the Budget Council. This is not
something that can be left to the civil servants or the politicians;
here statesmen are needed.</p>
<p>Austin, 12 April 2001</p>
<p>Edsger W. Dijkstra</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p><a
href="http://www.cs.utexas.edu/~EWD/transcriptions/EWD10xx/EWD1036.html">On
the cruelty of really teaching computing science</a><a href="#fnref1"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p><a
href="http://www.cs.utexas.edu/~EWD/transcriptions/EWD10xx/EWD1012.html">Real
mathematicians don’t prove</a><a href="#fnref2" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2014-01-08 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Wed, 08 Jan 2014 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Emacs users are like Terry Pratchett’s Igors]]></title><link>https://chrisdone.com/posts/emacs-users-are-like-igor</link><guid>https://chrisdone.com/posts/emacs-users-are-like-igor</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Emacs users are like Terry Pratchett’s Igors</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Emacs users are like Terry Pratchett’s Igors</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Within the constraints of the Emacs environment, there are no limits.
Emacs is built upon this principle; the Lisp principle. Make some small
kernel of features. A substrate. Take care to make this substrate
programmable (in any language, Emacs chooses Lisp), and then build the
system upon it. Let users worry about future features. Some 359,000
lines of C code comprise its kernel, and 1,637,000 lines of Emacs Lisp
take the rest of it.<a href="#fn1" class="footnote-ref" id="fnref1"
role="doc-noteref"><sup>1</sup></a></p>
<p>Similarly, the nature of The <a
href="http://www.winestockwebdesign.com/Essays/Lisp_Curse.html">Lisp
Curse</a> is that what can be written to express any given problem is so
arbitrary and free, that you are spoiled for choice, and every
programmer re-invents solutions to the same problems, uncaring about
sharing a common language with the world outside. The core problem is
that Lisp makes programmers selfish. Giving programmers so much
flexibility is inviting the alienation of other programmers; Lispers
think: how can I express this problem best, for me?</p>
<p>That phenomenon is not a problem for Emacs. Work environments are a
very personal thing. They exist to serve only one person: you. Me-me-me
is a winning attitude when dealing with your environment. Maybe in the
real world, out there, where you have to share programs with other
people, where other people will see or even use your efforts, you have
to care or take consideration about other people. Not in your
environment. Not in your Emacs. It is your virtual home for at least
nine hours of the day, every day.</p>
<p>My road to Emacs love developed slowly. I first came to it due to
Common Lisp. I knew enough Lisp to get by, copy-pasting example
snippets, configuring just enough to edit my environment. It felt a
little bit barebones compared to the IDEs I’d used before it. Little did
I know the world of functionality and configuration waiting beneath my
feet.</p>
<p>Eventually I started patching some things here and there, writing my
own hooks, little things like that. I used Emacs for a long time, just
becoming proficient as a user with the keybindings and window
management, before I ever wrote any Elisp. It hadn’t occured to me that
writing any Elisp would ever be of interest to me. I would often shaft
my .emacs configuration, and everything would break, and I wouldn’t
quite know why.</p>
<p>Finally, I wrote my first mode. I think it was a mode for ASP. It
wasn’t very good, and I didn’t fully understand everything that was
going on. But it gave me some key insights. This thing isn’t just an
editor, it’s really an environment all the way down. I can configure
<em>everything</em> about this mode. And the mode consists of a bunch of
functions and variables. It’s all code.</p>
<p>After that, it was really a sky-rocket of productivity. Eventually I
would write Elisp casually in between programming on work projects. I
would notice that a way of working was repetitive, or that Emacs behaved
in a way I just didn’t quite like, or I simply thought of a nice thing
that I could add. I’d happily spend anywhere from 30 seconds to half an
hour writing some functionality to extend my editing facilities.</p>
<p>And it was extended for good. That amazed me, and still does. My
problems are only problems for as long as I don’t notice them. Once I
do, I write some Elisp to solve it, and then it’s never a problem again.
In typical editors and IDEs, I simply wouldn’t even think of fixing such
things, never mind actually putting my work to one side for a minute,
solving them, and then going back to work again.</p>
<p>I’ve now written a lot of Elisp to support my development, especially
with respect to Haskell. Many times, for many months at a time, over the
years, I’ve been working on an experimental feature, or feature set,
mode, what-have-you, and it’s been very spotty. Mostly working, but
breaking a lot, interrupting my work, but with me persevering, pushing
through, until that work becomes stable and quite robust through sheer
usage and battle testing.</p>
<p>When working recently it occured to me that a lot of the
functionality I depend on presently in Emacs for work is built upon my
own work. I use the session/interactive-mode work for interacting with
Cabal and GHCi, I use structured-haskell-mode in conjunction with that,
and then atop that I use god-mode, my own Emacs input method. At one
time or another in the past they have all been unusable, or flaky as
hell. SHM still has a few growing pains, but is basically there.</p>
<p>This really reminds me of Terry Pratchett’s <a
href="http://en.wikipedia.org/wiki/Igor_%28Discworld%29">Igor</a> clan.
I discovered this amiable race in The Fifth Elephant. Igors are a people
inspired from the typical hunchbacked Igor archetype, but in Discworld,
they are also self-modifiers. Their bodies consist of mixed and matched
and patched and swapped body parts among other members of their clan, of
scars and self-adjustements. They are infinitely self-improving,
self-experimenting. They might end up with a botched job and have to
hobble around for a few days, but in the end it’s always fixable.</p>
<p>And they lisp.</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Though, while Elisp is Emacs’s
programmability language of choice, the particular language doesn’t
matter much. It could be Python, JavaScript, Haskell, whatever. The key
is: if most of your feature set is written in your editor’s programming
language, then that editor is very programmable.<a href="#fnref1"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2013-12-25 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Wed, 25 Dec 2013 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[structured-haskell-mode]]></title><link>https://chrisdone.com/posts/structured-haskell-mode</link><guid>https://chrisdone.com/posts/structured-haskell-mode</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>structured-haskell-mode</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>structured-haskell-mode</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>For about 2 months I’ve been working on and off on an Emacs package
called <a
href="https://github.com/chrisdone/structured-haskell-mode">structured-haskell-mode.</a><a
href="#fn1" class="footnote-ref" id="fnref1"
role="doc-noteref"><sup>1</sup></a> A full explanation and demo of the
features is available on the Github page. In summary, it is a mode that
offers <a
href="https://www.youtube.com/watch?v=D6h5dFyyUX0">paredit-mode</a><a
href="#fn2" class="footnote-ref" id="fnref2"
role="doc-noteref"><sup>2</sup></a> abilities for Haskell code.</p>
<p>I’ve been keeping it to myself in a private Github repo, hoping to
finish fleshing out the feature set<a href="#fn3" class="footnote-ref"
id="fnref3" role="doc-noteref"><sup>3</sup></a> and smooth over
stability issues. In the end I decided I’d put it out there, because the
base functionality is quite reliable and enough to get work done better.
It does actually change how you work.</p>
<p>The key features that enable new ways of working are:</p>
<ol type="1">
<li>Cutting and pasting actually preserves the indentation of the
particular syntactic node. One doesn’t have to think or care about
“re-indenting” or worry about how much nesting is happening for fear of
having to clean it up later. It’s so trivial now.</li>
<li>Typing characters or removing them will “bring along” dependent node
source, meaning that re-indentation is handled automatically. This means
that you can use a nice consistent Lisp style<a href="#fn4"
class="footnote-ref" id="fnref4" role="doc-noteref"><sup>4</sup></a>
without caring about how you’re going to have to manually re-indent it
whenever you make changes.</li>
<li>You now don’t have to think about indentation. You think about
nesting level. To go to the right place, you use the <code>)</code>
keybinding to go further outwards in the node layers, and hit
<code>C-j</code> to start a new sibling at that node level. There is no
“tab cycle”. This style is 100% reliable.</li>
<li>Context-awareness is useful. In strings, the quote character is
escaped. When hitting <code>C-j</code> in a list (of values, or types in
a record, or a list of constructors in a data declaration), it can
automatically add delimiter characters properly indented and spaced out.
Something you don’t want to have to care about doing yourself.</li>
<li>Parentheses are actually good. The Haskell tendency to abuse
<code>$</code> to avoid having to manage parentheses is symptomatic of
having crappy editing facilities. Managing parentheses in Haskell code
is a pain, because editors don’t know about things like Haskell’s case
expressions, or lambdas, or patterns, or whatever, and re-indentation is
a nightmare inside parentheses. Not in this mode. Parentheses make
editing a triviality rather than a chore.</li>
</ol>
<p>The overarching theme to this whole library is to remove redundancy
in your work. Stop thinking so much about layout and syntactic debt<a
href="#fn5" class="footnote-ref" id="fnref5"
role="doc-noteref"><sup>5</sup></a> and appealing to the status quo<a
href="#fn6" class="footnote-ref" id="fnref6"
role="doc-noteref"><sup>6</sup></a>, and start just thinking about the
real work you’re doing, which is plugging together programming
constructs.</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>It is actually a rewrite of a package
I wrote six months ago of the same name. That package was stable, but
the code was not favourable and there were some kinks to be ironed out.
The new version uses Emacs markers so structured operations fail less
often.<a href="#fnref1" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p>Emacs users who’ve written their
share of Elisp will know that paredit-mode is among the most enjoyable
editing experiences out there. Strangers to this editing experience are
simply missing out on the cream of the crop.<a href="#fnref2"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn3" role="doc-endnote"><p>Stealing ideas from paredit-mode
(e.g. slurping, barfing, convoluting) and coming up with my own ideas,
such as operand manipulation, automagic re-indentation.<a href="#fnref3"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn4" role="doc-endnote"><p>Lisp style is:</p>
<pre><code>foo bar
    mu
    (zot bar
         bob)</code></pre>
<a href="#fnref4" class="footnote-back" role="doc-backlink">↩︎</a></li>
<li id="fn5" role="doc-endnote"><p>Syntactic debt is the energy and time
you spend later on for making decisions or choices now. Feel like you’re
nesting your function too deep? Better stop now or you’ll pay for it
later because you’ll have to come back and collapse it down to fit
within 80/120 columns! That’s a real problem when your editor sucks.
When you have much better control over your code, things like that are a
non-issue. Just write the code, worry about layout when you’re done.
Lispers know this.<a href="#fnref5" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn6" role="doc-endnote"><p>The status quo has to debunked
incrementally, I think. The next thing to sort out is diffs. People
waste their time making their code more friendly to diff engines that
only know about lines. Diffs should be smart enough to know better.
Expect further development in this area.<a href="#fnref6"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2013-12-09 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Mon, 09 Dec 2013 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Recording simple GIFs for demos]]></title><link>https://chrisdone.com/posts/recording-small-gifs</link><guid>https://chrisdone.com/posts/recording-small-gifs</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Recording simple GIFs for demos</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Recording simple GIFs for demos</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Sometimes you might like to record little GIF animations of your
screen to demonstrate an Emacs feature you did (hey, some of you
might…). For example, <a
href="https://github.com/chrisdone/structured-haskell-mode#features">these</a>.
I made a wee F9 keybinding for Emacs to run this:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode lisp"><code class="sourceCode commonlisp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>(<span class="kw">defun</span><span class="fu"> screenshot-frame </span>()</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  <span class="st">&quot;Take a screenshot of 400x200 pixels of the Emacs frame.&quot;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  (interactive)</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>  (shell-command-to-string</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>   (concat <span class="st">&quot;sleep 1; &quot;</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>           <span class="st">&quot;import -window 0x3c000a3 &quot;</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>           <span class="st">&quot;-crop 400x200+13+0 +repage /tmp/frames/`date +%s`.png&quot;</span>)))</span></code></pre></div>
<p>Replace the window id with the window id of your target window, which
you can get with <code>xwininfo -display :0</code>.</p>
<p>I would execute <code>screenshot-frame</code> after running a command
or pressing a key (it sounds painful but it’s not, and it allows you to
make mistakes). The <code>sleep</code> call is to ensure that the buffer
has finished updating. I also disabled <code>blink-cursor-mode</code>.
Then to preview the animation so far I would use</p>
<pre><code>animate -delay 35 /tmp/frames/*.png</code></pre>
<p>If some frames were redundant I’d remove them. And then finally to
write out a .gif I’d use</p>
<pre><code>convert -delay 35 /tmp/frames/*.png out.gif</code></pre>
<p>I found the whole thing quite convenient!</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2013-12-09 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Mon, 09 Dec 2013 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Making GHCi scale better and faster]]></title><link>https://chrisdone.com/posts/making-ghci-fast</link><guid>https://chrisdone.com/posts/making-ghci-fast</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Making GHCi scale better and faster</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Making GHCi scale better and faster</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>A common complaint with GHCi is that it doesn’t scale well when the
size of the project gets bigger. Once you hit 20, 30, 50, or 150
modules, it stops being fun anymore and you start wishing you didn’t
have to wait for it to load.</p>
<p>I recommend enabling <code>-fobject-code</code>. You can enable this
by running</p>
<pre><code>$ ghci -fobject-code</code></pre>
<p>Or by setting it in the REPL:</p>
<pre><code>:set -fobject-code</code></pre>
<p>If you want it on all the time, you can put the above line in a
<code>.ghci</code> file either in your home directory or in the
directory of your project.</p>
<p>This makes GHCi compile everything once and then use incremental
recompilation thereafter. You’ll find that you can load 100-module
projects and work with them just fine in this way.</p>
<p>After that, you may notice that loading some modules gives less type
information and general metadata than before. For that, re-enable
byte-compilation temporarily with <code>-fbyte-code</code>
(<code>:set -fbyte-code</code>) and <code>:load</code> that module
again, you now have fast recompilation with complete information,
too.</p>
<p>Another tip is to use <code>-fno-code</code> to have <em>really</em>
fast compilation. This also works in combination with
<code>-fobject-code</code>. But I’d recommend using this only for type
checking, not for getting useful warnings (like pattern match
inexhaustiveness). So I would combine it with <code>-fobject-code</code>
in the same way as above with <code>-fbyte-code</code>, and then once
you’re done hacking, re-enable <code>-fobject-code</code> and rebuild
everything.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2013-11-20 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Wed, 20 Nov 2013 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Twitter waterflow problem and loeb]]></title><link>https://chrisdone.com/posts/twitter-problem-loeb</link><guid>https://chrisdone.com/posts/twitter-problem-loeb</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Twitter waterflow problem and loeb</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Twitter waterflow problem and loeb</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<style>
.g b{background:#888;color:#eee}
.g i{background:#ccc;color:#888}
.g a{background:#1a6e8e;color:#1a6e8e;}
.g u{background:#8f4e8b;color:#fff;text-decoration:none;}
.g s{background:#397460;color:#fff;text-decoration:none;}
.g b,.g i,.g a,.g u,.g s {padding:0.2em;display:block;border-radius:0.1em;width:1em;height:1em;float:left;margin:0.1em;line-height:1em;text-align:center;font-weight:normal;text-shadow:none;}
.g em{clear:both;display:block}
</style>
<h2 id="the-waterflow-problem">The Waterflow Problem</h2>
<p>I recently saw <em><a
href="/pdfs/archives/2013-10-29-i-failed-a-twitter-interview.pdf">I
Failed a Twitter Interview</a></em> which features the following cute
problem. Consider the following picture:</p>
<div class="g">
<p><i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i>
<i></i> <em></em> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i>
<b>7</b> <b>7</b> <i></i> <em></em> <i></i> <i></i> <i></i> <i></i>
<i></i> <i></i> <b></b> <b></b> <b>6</b> <em></em> <i></i> <b>5</b>
<i></i> <i></i> <i></i> <i></i> <b></b> <b></b> <b></b> <em></em>
<i></i> <b></b> <i></i> <i></i> <i></i> <b>4</b> <b></b> <b></b> <b></b>
<em></em> <i></i> <b></b> <i></i> <i></i> <b>3</b> <b></b> <b></b>
<b></b> <b></b> <em></em> <b>2</b> <b></b> <i></i> <b>2</b> <b></b>
<b></b> <b></b> <b></b> <b></b> <em></em> <b></b> <b></b> <b>1</b>
<b></b> <b></b> <b></b> <b></b> <b></b> <b></b> <em></em></p>
</div>
<p><strong><em>Fig. 1</em></strong></p>
<p>In <em>Fig. 1</em>, we have walls of different heights. Such pictures
are represented by an array of integers, where the value at each index
is the height of the wall. <em>Fig. 1</em> is represented with an array
as <code>[2,5,1,2,3,4,7,7,6]</code>.</p>
<p>Now imagine it rains. How much water is going to be accumulated in
puddles between walls? For example, if it rains in <em>Fig 1</em>, the
following puddle will be formed:</p>
<div class="g">
<p><i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i>
<i></i> <em></em> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i>
<b>7</b> <b>7</b> <i></i> <em></em> <i></i> <i></i> <i></i> <i></i>
<i></i> <i></i> <b></b> <b></b> <b>6</b> <em></em> <i></i> <b>5</b>
<a></a> <a></a> <a></a> <a></a> <b></b> <b></b> <b></b> <em></em>
<i></i> <b></b> <a></a> <a></a> <a></a> <b>4</b> <b></b> <b></b> <b></b>
<em></em> <i></i> <b></b> <a></a> <a></a> <b>3</b> <b></b> <b></b>
<b></b> <b></b> <em></em> <b>2</b> <b></b> <a></a> <b>2</b> <b></b>
<b></b> <b></b> <b></b> <b></b> <em></em> <b></b> <b></b> <b>1</b>
<b></b> <b></b> <b></b> <b></b> <b></b> <b></b> <em></em></p>
</div>
<p><strong><em>Fig. 2</em></strong></p>
<p>No puddles are formed at edges of the wall, water is considered to
simply run off the edge.</p>
<p>We count volume in square blocks of 1×1. Thus, we are left with a
puddle between column 1 and column 6 and the volume is 10.</p>
<p>Write a program to return the volume for any array.</p>
<h2 id="my-reaction">My Reaction</h2>
<p>I thought, this looks like a spreadsheet problem, and closed the
page, to get on with my work. Last thing I need right now is nerd
sniping.</p>
<p>A week or so later I saw <em><a
href="/pdfs/archives/2024-03-29-functional-twitter.pdf">A functional
solution to Twitter’s waterflow problem</a></em> which presented a
rather concise and beautiful approach to solving the problem. I present
it here, in the style that I prefer:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">water ::</span> [<span class="dt">Int</span>] <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>water h <span class="ot">=</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  <span class="fu">sum</span> (<span class="fu">zipWith</span> (<span class="op">-</span>)</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>               (<span class="fu">zipWith</span> <span class="fu">min</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>                        (<span class="fu">scanl1</span> <span class="fu">max</span> h)</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>                        (<span class="fu">scanr1</span> <span class="fu">max</span> h))</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>               h)</span></code></pre></div>
<p>This is the second fastest algorithm in this page, clocking in at a
mean 2.624748 ms for a random list of 10000 elements. See <a
href="#benchmarks">Benchmarks</a> for more details.</p>
<p>An efficient algorithm can be achieved with a trivial rewrite of
Michael Kozakov’s <a
href="https://gist.github.com/mkozakov/59af0fd5bddbed1a0399">Java
solution</a> is:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE BangPatterns #-}</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE ViewPatterns #-}</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.Vector</span> <span class="kw">as</span> <span class="dt">V</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Vector</span> ((!),<span class="dt">Vector</span>)</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="ot">water ::</span> <span class="dt">Vector</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>water land <span class="ot">=</span> go <span class="dv">0</span> <span class="dv">0</span> (V.length land <span class="op">-</span> <span class="dv">1</span>) <span class="dv">0</span> <span class="dv">0</span> <span class="kw">where</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>  go <span class="op">!</span>volume <span class="op">!</span>left <span class="op">!</span>right</span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>     (extend left <span class="ot">-&gt;</span> leftMax)</span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>     (extend right <span class="ot">-&gt;</span> rightMax)</span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">|</span> left <span class="op">&lt;</span> right <span class="ot">=</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>      <span class="kw">if</span> leftMax <span class="op">&gt;=</span> rightMax</span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>         <span class="kw">then</span> go (volume <span class="op">+</span> rightMax <span class="op">-</span> land<span class="op">!</span>right)</span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>                 left (right <span class="op">-</span> <span class="dv">1</span>) leftMax rightMax</span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>         <span class="kw">else</span> go (volume <span class="op">+</span> leftMax <span class="op">-</span> land<span class="op">!</span>left)</span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a>                 (left <span class="op">+</span>  <span class="dv">1</span>) right leftMax rightMax</span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">|</span> <span class="fu">otherwise</span> <span class="ot">=</span> volume</span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a>  extend i d <span class="ot">=</span> <span class="kw">if</span> land<span class="op">!</span>i <span class="op">&gt;</span> d <span class="kw">then</span> land<span class="op">!</span>i <span class="kw">else</span> d</span></code></pre></div>
<p>This is expectedly the fastest algorithm in this page, clocking in at
a mean of 128.2953 us for a random vector of 10000 elements.</p>
<p>But I still thought my spreadsheet idea was feasible.</p>
<h2 id="my-approach">My approach</h2>
<p>In a similar way to Philip Nilsson, I can define the problem as it
comes intuitively to me. As I saw it in my head, the problem can be
broken down into “what is the volume that a given column will hold?”
That can be written like this:</p>
<blockquote>
<p>volume<sub>0</sub> = 0</p>
<p>volume<sub>|S|-1</sub> = 0</p>
<p>volume<sub>i</sub> =
min(left<sub>i-1</sub>,right<sub>i+1</sub>)−height<sub>i</sub></p>
</blockquote>
<p>Where <i>left</i> and <i>right</i> are the peak heights to the left
or right:</p>
<blockquote>
<p>left<sub>0</sub> = height<sub>0</sub></p>
<p>left<sub>i</sub> = max(height<sub>i</sub>,left<sub>i-1</sub>)</p>
<p>right<sub>|S|-1</sub> = height<sub>|S|-1</sub></p>
<p>right<sub>i</sub> = max(height<sub>i</sub>,right<sub>i+1</sub>)</p>
</blockquote>
<p>That’s all.</p>
<h2 id="a-visual-example">A visual example</h2>
<p>An example of <code>i</code> is:</p>
<div class="g">
<p><i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i>
<i></i> <em></em> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i>
<b>7</b> <b>7</b> <i></i> <em></em> <i></i> <i></i> <i></i> <i></i>
<i></i> <i></i> <b></b> <b></b> <b>6</b> <em></em> <i></i> <b>5</b>
<i></i> <i></i> <i></i> <i></i> <b></b> <b></b> <b></b> <em></em>
<i></i> <b></b> <i></i> <i></i> <i></i> <b>4</b> <b></b> <b></b> <b></b>
<em></em> <i></i> <b></b> <i></i> <i></i> <b>3</b> <b></b> <b></b>
<b></b> <b></b> <em></em> <b>2</b> <b></b> <i></i> <u>2</u> <b></b>
<b></b> <b></b> <b></b> <b></b> <em></em> <b></b> <b></b> <b>1</b>
<u></u> <b></b> <b></b> <b></b> <b></b> <b></b> <em></em></p>
</div>
<p>We spread out in both directions to find the “peak” of the
columns:</p>
<div class="g">
<p><i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i>
<i></i> <em></em> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i>
<s>7</s> <b>7</b> <i></i> <em></em> <i></i> <i></i> <i></i> <i></i>
<i></i> <i></i> <s></s> <b></b> <b>6</b> <em></em> <i></i> <s>5</s>
<i></i> <i></i> <i></i> <i></i> <s></s> <b></b> <b></b> <em></em>
<i></i> <s></s> <i></i> <i></i> <i></i> <b>4</b> <s></s> <b></b> <b></b>
<em></em> <i></i> <s></s> <i></i> <i></i> <b>3</b> <b></b> <s></s>
<b></b> <b></b> <em></em> <b>2</b> <s></s> <i></i> <u>2</u> <b></b>
<b></b> <s></s> <b></b> <b></b> <em></em> <b></b> <s></s> <b>1</b>
<u></u> <b></b> <b></b> <s></s> <b></b> <b></b> <em></em></p>
</div>
<p>How do we do that? We simply define the volume of a column to be in
terms of our immediate neighbors to the left and to the right:</p>
<div class="g">
<p><i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i>
<i></i> <em></em> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i>
<b>7</b> <b>7</b> <i></i> <em></em> <i></i> <i></i> <i></i> <i></i>
<i></i> <i></i> <b></b> <b></b> <b>6</b> <em></em> <i></i> <b>5</b>
<i></i> <i></i> <i></i> <i></i> <b></b> <b></b> <b></b> <em></em>
<i></i> <b></b> <i></i> <i></i> <i></i> <b>4</b> <b></b> <b></b> <b></b>
<em></em> <i></i> <b></b> <i></i> <i></i> <s>3</s> <b></b> <b></b>
<b></b> <b></b> <em></em> <b>2</b> <b></b> <i></i> <u>2</u> <s></s>
<b></b> <b></b> <b></b> <b></b> <em></em> <b></b> <b></b> <s>1</s>
<u></u> <s></s> <b></b> <b></b> <b></b> <b></b> <em></em> <i></i>
<i></i> <i>A</i> <i>X</i> <i>B</i> <i></i> <i></i> <i></i> <i></i>
<em></em></p>
</div>
<p>X is defined in terms of A and B. A and B are, in turn, are defined
in terms of their immediate neighbors. Until we reach the ends:</p>
<div class="g">
<p><i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i>
<i></i> <em></em> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i>
<b>7</b> <b>7</b> <i></i> <em></em> <i></i> <i></i> <i></i> <i></i>
<i></i> <i></i> <b></b> <b></b> <s>6</s> <em></em> <i></i> <b>5</b>
<i></i> <i></i> <i></i> <i></i> <b></b> <b></b> <s></s> <em></em>
<i></i> <b></b> <i></i> <i></i> <i></i> <b>4</b> <b></b> <b></b> <s></s>
<em></em> <i></i> <b></b> <i></i> <i></i> <b>3</b> <b></b> <b></b>
<b></b> <s></s> <em></em> <s>2</s> <b></b> <i></i> <u>2</u> <b></b>
<b></b> <b></b> <b></b> <s></s> <em></em> <s></s> <b></b> <b>1</b>
<u></u> <b></b> <b></b> <b></b> <b></b> <s></s> <em></em> <i>A</i>
<i>X</i> <i></i> <i></i> <i></i> <i></i> <i></i> <i>Y</i> <i>B</i>
<em></em></p>
</div>
<p>The ends of the wall are the only ones who only have <em>one
side</em> defined in terms of their single neighbor, which makes
complete sense. Their volume is always <code>0</code>. It’s impossible
to have a puddle on the edge. A’s “right” will be defined in terms of X,
and B’s “left” will be defined in terms of Y.</p>
<p>But how does this approach avoid infinite cycles? Easy. Each column
in the spreadsheet contains three values:</p>
<ol type="1">
<li>The peak to the left.</li>
<li>The peak to the right.</li>
<li>My volume.</li>
</ol>
<p>A and B below depend upon eachother, but for different slots. A
depends on the value of B’s “right” peak value, and B depends on the
value of A’s “left” value:</p>
<div class="g">
<p><i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i>
<i></i> <em></em> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i>
<b>7</b> <b>7</b> <i></i> <em></em> <i></i> <i></i> <i></i> <i></i>
<i></i> <i></i> <b></b> <b></b> <b>6</b> <em></em> <i></i> <b>5</b>
<i></i> <i></i> <i></i> <i></i> <b></b> <b></b> <b></b> <em></em>
<i></i> <b></b> <i></i> <i></i> <i></i> <b>4</b> <b></b> <b></b> <b></b>
<em></em> <i></i> <b></b> <i></i> <i></i> <s>3</s> <b></b> <b></b>
<b></b> <b></b> <em></em> <b>2</b> <b></b> <i></i> <u>2</u> <s></s>
<b></b> <b></b> <b></b> <b></b> <em></em> <b></b> <b></b> <b>1</b>
<u></u> <s></s> <b></b> <b></b> <b></b> <b></b> <em></em> <i></i>
<i></i> <i></i> <i>A</i> <i>B</i> <i></i> <i></i> <i></i> <i></i>
<em></em></p>
</div>
<p>The <em>height</em> of the column’s peak will be the smallest of the
two peaks on either side:</p>
<div class="g">
<p><i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i>
<i></i> <em></em> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i>
<b>7</b> <b>7</b> <i></i> <em></em> <i></i> <i></i> <i></i> <i></i>
<i></i> <i></i> <b></b> <b></b> <b>6</b> <em></em> <i></i> <s>5</s>
<i></i> <a></a> <i></i> <i></i> <s></s> <b></b> <b></b> <em></em>
<i></i> <s></s> <i></i> <i></i> <i></i> <b>4</b> <s></s> <b></b> <b></b>
<em></em> <i></i> <s></s> <i></i> <i></i> <b>3</b> <b></b> <s></s>
<b></b> <b></b> <em></em> <b>2</b> <s></s> <i></i> <u>2</u> <b></b>
<b></b> <s></s> <b></b> <b></b> <em></em> <b></b> <s></s> <b>1</b>
<u></u> <b></b> <b></b> <s></s> <b></b> <b></b> <em></em></p>
</div>
<p>And then the <em>volume</em> of the column is simply the height of
the peak minus the column’s height:</p>
<div class="g">
<p><i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i>
<i></i> <em></em> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i>
<b>7</b> <b>7</b> <i></i> <em></em> <i></i> <i></i> <i></i> <i></i>
<i></i> <i></i> <b></b> <b></b> <b>6</b> <em></em> <i></i> <s>5</s>
<i></i> <a></a> <i></i> <i></i> <s></s> <b></b> <b></b> <em></em>
<i></i> <s></s> <i></i> <a></a> <i></i> <b>4</b> <s></s> <b></b> <b></b>
<em></em> <i></i> <s></s> <i></i> <a></a> <b>3</b> <b></b> <s></s>
<b></b> <b></b> <em></em> <b>2</b> <s></s> <i></i> <u>2</u> <b></b>
<b></b> <s></s> <b></b> <b></b> <em></em> <b></b> <s></s> <b>1</b>
<u></u> <b></b> <b></b> <s></s> <b></b> <b></b> <em></em></p>
</div>
<h2 id="enter-loeb">Enter loeb</h2>
<p>I first heard about <code>loeb</code> from Dan Piponi’s <a
href="http://blog.sigfpe.com/2006/11/from-l-theorem-to-spreadsheet.html">From
Löb’s Theorem to Spreadsheet Evaluation</a> some years back, and ever
since I’ve been wanting to use it for a real problem. It lets you easily
define a spreadsheet generator by mapping over a functor containing
functions. To each function in the container, the container itself is
passed to that function.</p>
<p>Here’s <code>loeb</code>:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ot">loeb ::</span> <span class="dt">Functor</span> f <span class="ot">=&gt;</span> f (f b <span class="ot">-&gt;</span> b) <span class="ot">-&gt;</span> f b</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>loeb x <span class="ot">=</span> <span class="fu">fmap</span> (\f <span class="ot">-&gt;</span> f (loeb x)) x</span></code></pre></div>
<p>(Note, there is a <a href="#update-on-loeb">more efficient version
here</a>.)</p>
<p>So as described in the elaboration of how I saw the problem in my
head, the solution takes the vector of numbers, generates a spreadsheet
of triples, defined in terms of their neighbors—exept edges—and then
simply makes a sum total of the third value, the volumes.</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Lens</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.Vector</span> <span class="kw">as</span> <span class="dt">V</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Vector</span> ((!),<span class="dt">Vector</span>)</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="ot">water ::</span> <span class="dt">Vector</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>water <span class="ot">=</span> V.sum <span class="op">.</span> V.map (view _3) <span class="op">.</span> loeb <span class="op">.</span> V.imap cell <span class="kw">where</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>  cell i x xs</span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">|</span> i <span class="op">==</span> <span class="dv">0</span>               <span class="ot">=</span> edge _2</span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">|</span> i <span class="op">==</span> V.length xs <span class="op">-</span> <span class="dv">1</span> <span class="ot">=</span> edge _1</span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">|</span> <span class="fu">otherwise</span>            <span class="ot">=</span> col i x xs</span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">where</span> edge ln <span class="ot">=</span> set l (view l (col i x xs)) (x,x,<span class="dv">0</span>)</span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>            <span class="kw">where</span> l r <span class="ot">=</span> cloneLens ln r</span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>  col i x xs <span class="ot">=</span> (l,r,<span class="fu">min</span> l r <span class="op">-</span> x)</span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">where</span> l <span class="ot">=</span> neighbor _1 (<span class="op">-</span>)</span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a>          r <span class="ot">=</span> neighbor _2 (<span class="op">+</span>)</span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a>          neighbor l o <span class="ot">=</span> <span class="fu">max</span> x (view l (xs <span class="op">!</span> (i <span class="ot">`o`</span> <span class="dv">1</span>)))</span></code></pre></div>
<p>It’s not the most efficient algorithm—it relies on laziness in an
almost perverse way, but I like that I was able to express exactly what
occured to me. And <code>loeb</code> is suave. It clocks in at a mean of
3.512758 ms for a vector of 10000 random elements. That’s not too bad,
compared to the <code>scanr</code>/<code>scanl</code>.</p>
<p>This is was also my first use of <a
href="http://hackage.haskell.org/package/lens">lens</a>, so that was
fun. The <code>cloneLens</code> are required because you can’t pass in
an arbitrary lens and then use it both as a setter and a getter, the
type becomes fixed on one or the other, making it not really a
<em>lens</em> anymore. I find that pretty disappointing. But otherwise
the lenses made the code simpler.</p>
<h2 id="update-with-comonads-pointed-lists">Update with comonads &amp;
pointed lists</h2>
<p>Mel Zuser pointed out another cool insight from <em><a
href="http://blog.sigfpe.com/2007/02/comonads-and-reading-from-future.html?showComment=1171056660000#c2284986681058924897">Comonads
and reading from the future</a></em> (Dan Piponi’s blog is a treasure
trove!) that while <code>loeb</code> lets you look at the <em>whole</em>
container, giving you <em>absolute</em> references, the equivalent
corecursive fix (below <code>wfix</code>) on a comonad gives you
<em>relative</em> references. Mel demonstrates below using Jeff
Wheeler’s <a
href="http://hackage.haskell.org/package/pointedlist-0.4.0.3/docs/Data-List-PointedList.html">pointed
list</a> library and Edward Kmett’s <a
href="http://hackage.haskell.org/package/comonad">comonad</a>
library:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Comonad</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Lens</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.List.PointedList</span> (<span class="dt">PointedList</span>)</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.List.PointedList</span> <span class="kw">as</span> <span class="dt">PE</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Maybe</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Comonad</span> <span class="dt">PointedList</span> <span class="kw">where</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>    extend  <span class="ot">=</span> PE.contextMap</span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>    extract <span class="ot">=</span> PE._focus</span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a><span class="ot">water ::</span> [<span class="dt">Int</span>] <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>water <span class="ot">=</span> view _2 <span class="op">.</span> wfix <span class="op">.</span> <span class="fu">fmap</span> go <span class="op">.</span> fromMaybe (PE.singleton <span class="dv">0</span>) <span class="op">.</span> PE.fromList</span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">where</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a>    go height context <span class="ot">=</span> (lMax, total, rMax)</span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a>      <span class="kw">where</span></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a>        get f <span class="ot">=</span> <span class="fu">maybe</span> (height, <span class="dv">0</span>, height) PE._focus <span class="op">$</span> f context</span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a>        (prevLMax,         _,        _) <span class="ot">=</span> get PE.previous</span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true" tabindex="-1"></a>        (_       , prevTotal, prevRMax) <span class="ot">=</span> get PE.next</span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true" tabindex="-1"></a>        lMax <span class="ot">=</span> <span class="fu">max</span> height prevLMax</span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true" tabindex="-1"></a>        rMax <span class="ot">=</span> <span class="fu">max</span> height prevRMax</span>
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true" tabindex="-1"></a>        total <span class="ot">=</span> prevTotal <span class="op">+</span> <span class="fu">min</span> lMax rMax <span class="op">-</span> height</span></code></pre></div>
<p>I think if I’d’ve heard of this before, this solution would’ve come
to mind instead, it seems entirely natural!</p>
<p>Sadly, this is the slowest algorithm on the page. I’m not sure how to
optimize it to be better.</p>
<p><strong>Update 2022-01-27 sent by Mel:</strong></p>
<blockquote>
<p>I have an addendum as to why the comonad solution is so slow. The
wfix operator doesn’t tie the knot, so it has to do asymptotically more
work than you would expect recalculating results. The way to fix it is
to use the kfix operator which has since been added to Control.Comonad
instead. See also: <a
href="https://www.youtube.com/watch?v=F7F-BzOB670">Kenneth Foner -
Getting a Quick Fix on Comonads</a></p>
</blockquote>
<h2 id="update-on-lens">Update on lens</h2>
<p>Russell O’Connor gave me some hints for reducing the lens verbiage.
First, eta-reducing the locally defined lens <code>l</code> in my code
removes the need for the <code>NoMonomorphismRestriction</code>
extension, so I’ve removed that. Second, a rank-N type can also be used,
but then the type signature is rather large and I’m unable to reduce it
presently without reading more of the lens library.</p>
<h2 id="update-on-loeb">Update on loeb</h2>
<p>On re-reading the comments for <em><a
href="http://blog.sigfpe.com/2006/11/from-l-theorem-to-spreadsheet.html">From
Löb’s Theorem to Spreadsheet Evaluation</a></em> I noticed Edward Kmett
pointed out we can get better laziness sharing with the following
definition of loeb:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="ot">loeb ::</span> <span class="dt">Functor</span> f <span class="ot">=&gt;</span> f (f b <span class="ot">-&gt;</span> b) <span class="ot">-&gt;</span> f b</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>loeb x <span class="ot">=</span> xs</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">where</span> xs <span class="ot">=</span> <span class="fu">fmap</span> (<span class="op">$</span> xs) x</span></code></pre></div>
<p>For my particular <code>water</code> function, this doesn’t make much
of a difference, but there is a difference. See the next section.</p>
<h2 id="time-travelling-solution">Time travelling solution</h2>
<p>Mel Zuser demonstrated a time travelling solution based on <a
href="http://hackage.haskell.org/package/tardis-0.3.0.0/docs/Control-Monad-Tardis.html">the
Tardis monad</a>:</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Monad</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Monad.Tardis</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="ot">water ::</span> [<span class="dt">Int</span>] <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>water <span class="ot">=</span> <span class="fu">flip</span> evalTardis (<span class="fu">minBound</span>, <span class="fu">minBound</span>) <span class="op">.</span> foldM go <span class="dv">0</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">where</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>    go total height <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>        modifyForwards <span class="op">$</span> <span class="fu">max</span> height</span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>        leftmax <span class="ot">&lt;-</span> getPast</span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>        rightmax <span class="ot">&lt;-</span> getFuture</span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a>        modifyBackwards <span class="op">$</span> <span class="fu">max</span> height</span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a>        <span class="fu">return</span> <span class="op">$</span> total <span class="op">+</span> <span class="fu">min</span> leftmax rightmax <span class="op">-</span> height</span></code></pre></div>
<h2 id="fastest">Fastest</h2>
<p>Sami Hangaslammi submitted this fast version (clocks in at 33.80864
us):</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Array</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="ot">waterVolume ::</span> <span class="dt">Array</span> <span class="dt">Int</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>waterVolume arr <span class="ot">=</span> go <span class="dv">0</span> minB maxB <span class="kw">where</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>  (minB,maxB) <span class="ot">=</span> bounds arr</span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>  go <span class="op">!</span>acc lpos rpos</span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">|</span> lpos <span class="op">&gt;=</span> rpos             <span class="ot">=</span> acc</span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">|</span> leftHeight <span class="op">&lt;</span> rightHeight <span class="ot">=</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>      segment leftHeight    <span class="dv">1</span>  acc lpos contLeft</span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">|</span> <span class="fu">otherwise</span>                <span class="ot">=</span></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a>      segment rightHeight (<span class="op">-</span><span class="dv">1</span>) acc rpos contRight</span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">where</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a>        leftHeight          <span class="ot">=</span> arr <span class="op">!</span> lpos</span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a>        rightHeight         <span class="ot">=</span> arr <span class="op">!</span> rpos</span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a>        contLeft  acc&#39; pos&#39; <span class="ot">=</span> go acc&#39; pos&#39; rpos</span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true" tabindex="-1"></a>        contRight acc&#39; pos&#39; <span class="ot">=</span> go acc&#39; lpos pos&#39;</span>
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-19"><a href="#cb8-19" aria-hidden="true" tabindex="-1"></a>  segment limit move <span class="op">!</span>acc&#39; <span class="op">!</span>pos cont</span>
<span id="cb8-20"><a href="#cb8-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">|</span> delta <span class="op">&lt;=</span> <span class="dv">0</span> <span class="ot">=</span> cont acc&#39; pos&#39;</span>
<span id="cb8-21"><a href="#cb8-21" aria-hidden="true" tabindex="-1"></a>    <span class="op">|</span> <span class="fu">otherwise</span>  <span class="ot">=</span> segment limit move (acc&#39; <span class="op">+</span> delta) pos&#39; cont</span>
<span id="cb8-22"><a href="#cb8-22" aria-hidden="true" tabindex="-1"></a>    <span class="kw">where</span></span>
<span id="cb8-23"><a href="#cb8-23" aria-hidden="true" tabindex="-1"></a>        delta <span class="ot">=</span> limit <span class="op">-</span> arr <span class="op">!</span> pos&#39;</span>
<span id="cb8-24"><a href="#cb8-24" aria-hidden="true" tabindex="-1"></a>        pos&#39;  <span class="ot">=</span> pos <span class="op">+</span> move</span></code></pre></div>
<p>Changing the data structure to a vector brings this down to 26.79492
us.</p>
<h2 id="benchmarks">Benchmarks</h2>
<p>Here are benchmarks for all versions presented in this page.</p>
<pre><code>benchmarking water/10000
mean: 2.624748 ms, lb 2.619731 ms, ub 2.630364 ms, ci 0.950
std dev: 85.45235 us, lb 78.33856 us, ub 103.2333 us, ci 0.950
found 54 outliers among 1000 samples (5.4%)
  51 (5.1%) high mild
  3 (0.3%) high severe
variance introduced by outliers: 79.838%
variance is severely inflated by outliers

benchmarking water_loeb/10000
mean: 3.512758 ms, lb 3.508533 ms, ub 3.517332 ms, ci 0.950
std dev: 70.77688 us, lb 65.88087 us, ub 76.97691 us, ci 0.950
found 38 outliers among 1000 samples (3.8%)
  24 (2.4%) high mild
  14 (1.4%) high severe
variance introduced by outliers: 59.949%
variance is severely inflated by outliers

benchmarking water_loeb&#39;/10000
mean: 3.511872 ms, lb 3.507492 ms, ub 3.516778 ms, ci 0.950
std dev: 74.34813 us, lb 67.99334 us, ub 84.56183 us, ci 0.950
found 43 outliers among 1000 samples (4.3%)
  34 (3.4%) high mild
  9 (0.9%) high severe
variance introduced by outliers: 62.285%
variance is severely inflated by outliers

benchmarking water_onepass/10000
mean: 128.2953 us, lb 128.1194 us, ub 128.4774 us, ci 0.950
std dev: 2.864153 us, lb 2.713756 us, ub 3.043611 us, ci 0.950
found 18 outliers among 1000 samples (1.8%)
  17 (1.7%) high mild
  1 (0.1%) high severe
variance introduced by outliers: 64.826%
variance is severely inflated by outliers

benchmarking water_array/10000
mean: 33.80864 us, lb 33.76067 us, ub 33.86597 us, ci 0.950
std dev: 844.9932 ns, lb 731.3158 ns, ub 1.218807 us, ci 0.950
found 29 outliers among 1000 samples (2.9%)
  27 (2.7%) high mild
  2 (0.2%) high severe
variance introduced by outliers: 69.836%
variance is severely inflated by outliers

benchmarking water_vector/10000
mean: 26.79492 us, lb 26.75906 us, ub 26.83274 us, ci 0.950
std dev: 595.1865 ns, lb 559.8929 ns, ub 652.5076 ns, ci 0.950
found 21 outliers among 1000 samples (2.1%)
  18 (1.8%) high mild
  3 (0.3%) high severe
variance introduced by outliers: 64.525%
variance is severely inflated by outliers

benchmarking water_comonad/10000
collecting 1000 samples, 1 iterations each, in estimated 28315.44 s

benchmarking water_tardis/10000
collecting 1000 samples, 1 iterations each, in estimated 28.98788 s</code></pre>
<p>I never bothered waiting around for the comonad or the time traveller
ones to complete. They’re slow, let’s say that.</p>
<p><strong>2022-01-27:</strong> The benchmark sources are no longer
available.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2013-11-14 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Thu, 14 Nov 2013 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[God-mode for Emacs]]></title><link>https://chrisdone.com/posts/god-mode</link><guid>https://chrisdone.com/posts/god-mode</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>God-mode for Emacs</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>God-mode for Emacs</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>A month ago I blogged about ways to reduce strenuous key presses in
my Emacs use. I <a href="/posts/emacs-key-analysis">analyzed my runs of
chords in Emacs</a>, then <a
href="/posts/speculations-on-exclusive-editing">speculated</a> on the
merits of <a href="http://chrisdone.com/posts/modal-editors">exclusive
vs mixed editing</a>. Since then I wrote an Emacs mode called <a
href="https://github.com/chrisdone/god-mode/">god-mode</a>. It’s a mode
that you toggle in and out of, and when you’re in it, all keys are
implicitly prefixed with <code>C-</code> (among other helpful
shortcuts). Over all, it’s been a resounding success. A couple other
people, including the author of multiple mark mode, contributed some
patches. I’ve been using it for a month and have been very
satisfied.</p>
<p>For those interested in the keymapping as of writing, you can <a
href="#the-keymapping">skip to that section below.</a></p>
<h2 id="compared-with-vim">Compared with Vim</h2>
<p>Coming back to the examples I came up with in <a
href="/posts/speculations-on-exclusive-editing">speculations on
exclusive editing</a>, God-mode is on par with Vim. In fact, it’s the
same or fewer key presses for each one:</p>
<pre><code>Vim:   bbDi (5)
Emacs: gb.ki (5)

Vim:   db.i (4)
Emacs: g←.i (4)

Vim:   ?r↲lDi (8)
Emacs: rr↲ki (5)</code></pre>
<p>That’s not bad. I grant that my Vim fu is weak, so probably there are
shorter ways to write the Vim examples. But at any rate Emacs is doing
well here.</p>
<h2 id="evaluation-after-one-month">Evaluation After One Month</h2>
<p>I’ve been using this in my Emacs turned on by default for one month.
I knew I was going to stick with it after a week or so of use, it was
already ingrained into how I use Emacs. Now, when I access a remote
Emacs on a server or whatnot, I find that I reach for the Caps Lock key
(my toggler key) in order to do an involved editing operation, only to
find that it’s not there! Oh, no! I’ll have to use Ctrl for all these
dull commands…</p>
<p>In typical usage, it’s a 50-50. When I’m writing code, I tend to work
in normal Emacs mode. When I’m editing, I work almost exclusively in
God-mode. Cutting (<code>w</code>), copying (<code>gw</code>), moving
(<code>k</code>, <code>gk</code>, <code>Gk</code>, <code>y</code>),
navigating (<code>ga</code>, <code>gf</code>, etc.), reindenting,
slurping, buffer switching (<code>z</code>), running commands
(<code>cc</code>, <code>ci</code>, <code>ct</code>, etc), moving around
(<code>e</code>, <code>a</code>, <code>f</code>, <code>b</code>, etc.),
searching (<code>s</code>, <code>r</code>), replacing (<code>t</code>),
saving (<code>xs</code>). All those things I do from god mode.</p>
<p>I’ve also noticed that the more tired I get with my hands towards the
end of the day, the more I tend to stick in god-mode. That gives me
extra mileage to finish those last things.</p>
<h2 id="retaining-god-mode-exclusively">Retaining God Mode
Exclusively</h2>
<p>In fact in some modes it’s possible to remain entirely in God mode.
In CSS mode, for example, I’m able to produce out the following:</p>
<pre><code>.foo {
   display: none;
}</code></pre>
<p>by typing</p>
<pre><code>{ .foo ↲ : d ↲ ↲</code></pre>
<p>What happens there is that <code>{</code> prompts me for a rule and
inserts <code>{ }</code> and puts my cursor inside it. Then
<code>:</code> prompts for a property name, which is completed with
ido-mode. Then it prompts for a value. In the case of the
<code>display</code> property, it knows there’s only a list of values
available for it, and it prompts for a choice of <code>none</code>,
<code>block</code>, etc. I hit <code>↲</code> to choose the default.</p>
<p>If I want to edit a property/value pair, I hit <code>;</code> and it
prompts me for the value with the input containing the existing
value.</p>
<p>The more one is able to stay in God mode, the more the speed and
convenience benefits.</p>
<h2 id="the-keymapping">The Keymapping</h2>
<p>(This is described in the README, but including here for
posterity.)</p>
<p>God-mode defines the following mapping:</p>
<ul>
<li><p>All commands are assumed to be <code>C-&lt;something&gt;</code>
unless otherwise indicated. Examples:</p>
<ul>
<li><code>a</code> → <code>C-a</code></li>
<li><code>s</code> → <code>C-s</code></li>
<li><code>akny</code> → <code>C-a C-k C-n C-y</code></li>
<li><code>xs</code> → <code>C-x C-s</code></li>
<li><code>x s</code> → <code>C-x s</code></li>
</ul>
<p>Note the use of space to produce <code>C-x s</code>.</p></li>
<li><p><code>g</code> is a special key to indicate
<code>M-&lt;something&gt;</code>. This means that there is no way to
write <code>C-g</code> in this mode, you must therefore type
<code>C-g</code> directly. Examples:</p>
<ul>
<li><code>gf</code> → <code>M-f</code></li>
<li><code>gx</code> → <code>M-x</code></li>
</ul></li>
<li><p><code>G</code> is a special key to indicate
<code>C-M-&lt;something&gt;</code>. Example:</p>
<ul>
<li><code>Gx</code> → <code>C-M-x</code></li>
</ul></li>
<li><p>Digit arguments:</p>
<ul>
<li><code>12f</code> → <code>M-12 C-f</code></li>
</ul></li>
<li><p>Repetition:</p>
<ul>
<li><code>gfzz</code> → <code>M-f M-f M-f</code></li>
</ul></li>
<li><p>Universal boolean argument:</p>
<ul>
<li><code>uco</code> → <code>C-u C-c C-o</code></li>
</ul></li>
<li><p>There is a key (default <code>i</code> - think <em>insert</em>)
to disable God mode, similar to Vim’s i.</p></li>
</ul>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2013-09-21 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sat, 21 Sep 2013 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Functional Programming is Hard?]]></title><link>https://chrisdone.com/posts/functional-programming-is-hard</link><guid>https://chrisdone.com/posts/functional-programming-is-hard</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Functional Programming is Hard?</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Functional Programming is Hard?</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Just a reminder to those who think imperative object oriented style
is inherently easier to understand for humans, and that functional
programming languages are really hard, if you look at any class of
complete programming newbies trying to learn a modern language like Java
or C++, you quickly realise this is false. Here’s an email I received a
few years ago from a friend who was taking programming at college,
verbatim:</p>
<blockquote>
<p>Encapsulation, Inheritance, Class, Object</p>
<p>I have to define what these mean in terms of programming yet every
time I research them I come across information I don’t understand. If
you could lend me a hand or point me in the right direction of something
a bit easier to understand that’d be great.</p>
<p>Just need some one to explain the terms in a simple manner, I don’t
get why every time you research something they try to explain it in the
most complex terms possible.</p>
</blockquote>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2013-09-21 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sat, 21 Sep 2013 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[CamelCase vs under_scores vs hyphenated-words]]></title><link>https://chrisdone.com/posts/camelcase-vs-underscores-vs-hyphens</link><guid>https://chrisdone.com/posts/camelcase-vs-underscores-vs-hyphens</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>CamelCase vs under_scores vs hyphenated-words</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>CamelCase vs under_scores vs hyphenated-words</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<h2 id="snake-case-do_and_go">Snake-case: <code>do_and_go</code></h2>
<ul>
<li>2 key presses per new component</li>
<li>Chords involved: 1</li>
<li>Doesn’t use standard English compounding character</li>
<li>Marginally aesthetically pleasing, but not normal typography</li>
</ul>
<h2 id="camel-case-doandgo">Camel-case: <code>doAndGo</code></h2>
<ul>
<li>2 key presses per new component</li>
<li>Chords involved: n where n is the first character of the next
component</li>
<li>Non-standard upper-case</li>
<li>Not aesthetically pleasing, like a camel’s back</li>
</ul>
<h2 id="lisp-case-do-and-go">Lisp-case: <code>do-and-go</code></h2>
<ul>
<li>1 key press per new component</li>
<li>Chords involved: 0</li>
<li>Uses standard English compounding character: <code>-</code> (think:
“type-class”, “camel-case”, “five-point”, “computer-generated”)</li>
<li>Aesthetically pleasing, consistent height and separation</li>
</ul>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2013-08-30 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Fri, 30 Aug 2013 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Analysis of Emacs keys pressed]]></title><link>https://chrisdone.com/posts/emacs-key-analysis</link><guid>https://chrisdone.com/posts/emacs-key-analysis</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Analysis of Emacs keys pressed</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Analysis of Emacs keys pressed</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Here’s the deal: Emacs keybindings make my fingers hurt. I don’t
think I ever experienced RSI before I started using Emacs. I guess I’ve
been using Emacs for about 6 years. I’m very efficient with it. I can
edit almost as fast as I can think, my fingers never need to take a
break. But that efficiency comes at a steep price, I feel.</p>
<p>I hypothesize that chords are to blame, and that I would be happier
and less achey if I used a modal set of keybindings, like in Vim, in
which every key binding is a single character. Not all the keybindings
(e.g. <code>$</code>) are a single key press, but most are.</p>
<p>I’ve tried <code>evil-mode</code>, and it’s pretty poor. It doesn’t
provide a proper mapping to Emacs; hitting <code>$</code> doesn’t
actually execute <code>move-end-of-line</code>, it executes
<code>evil-end-of-line</code>, which does not integrate with existing
modes well at all. It’s catering to Vimers, but it’s not good for Emacs
power users.</p>
<p>I suspect that I would like to have a global modal switcher that will
make <code>C-</code> and <code>M-</code> implicit somehow, so that
<code>a SPC e w</code> is equivalent to typing
<code>C-a C-SPC C-e C-w</code>. Before sitting down to develop such a
system, tackle the problem of how to start and exit the mode, and how to
deal with the meta key, I thought I would collect some statistics. (And
actually there are systems like sticky keys or chords for Emacs for
tackling stuff like this, so it’s not a scary, new area.)</p>
<p>What I wanted to prove (or collect evidence for) was:</p>
<ul>
<li>I waste a lot of energy on <code>C-</code> and <code>M-</code>
commands.</li>
<li>Said commands happen in clusters, which would justify a modal
switcher.</li>
</ul>
<p>I already had <a href="http://lpaste.net/91637">a trivial script</a>
to print key presses for screencasts, so I modified that to also store
the time and mode in the buffer, and I opened a <code>keys.log</code>
file to which I would save the key presses for a day.</p>
<p>I then whipped up a <a href="http://lpaste.net/91638">script</a> to
read in those statistics and print out a summary, to (hopefully) provide
evidence for the above claims.</p>
<p>The output is the following:</p>
<blockquote>
<p>Recording start/end: 2013-08-07 09:52:23 UTC/2013-08-08 07:54:23
UTC</p>
<p>Time spent: 22 hours (not 100% activity)</p>
<p>Total key presses: 29687</p>
<p>Commands (including character presses): 22657</p>
<p>Single-key commands: 16457</p>
<p>C- or M- commands: 6200 (27.36%)</p>
<p>Runs of (consecutively) unique C-/M- clusters: min/max/avg/stddev:
1/45/2.25/2.52</p>
<p>Runs of non-unique C-/M- clusters: min/max/avg/stddev:
1/189/3.35/7.04</p>
<p>Key presses used on C-/M- commands: 13230 (44.56%)</p>
<p>Runs of C-f/C-n/C-p/C-b: min/max/avg/stddev: 1/39/2.96/4.63</p>
<p>Key presses used on C-f/C-b/C-n/C-p: 4572 (15.40% of all key presses,
34.56% of C-/M- command key presses)</p>
</blockquote>
<pre><code>Top commands used:

 1 |   750 | C-n
 2 |   716 | C-p
 3 |   355 | C-f
 4 |   341 | C-/
 5 |   335 | C-b
 6 |   259 | M-DEL
 7 |   248 | C-z
 8 |   245 | M-b
 9 |   231 | C-e
10 |   221 | M-p
11 |   193 | C-d
12 |   189 | M-f
13 |   157 | C-s
14 |   145 | C-M-u
15 |   142 | C-g
16 |   136 | C-a
17 |   117 | C-y
18 |   109 | C-x C-s
19 |   107 | M-
20 |    92 | C-SPC</code></pre>
<p>Terms:</p>
<ul>
<li><em>Unique</em>: <code>C-SPC C-a C-w</code> – this would cut the
text from the point to the start of the line, that’s a unique
cluster.</li>
<li><em>Non-unique</em>: <code>C-f C-f C-f</code> – move forward three
times, that’s a non-unique cluster.</li>
</ul>
<p>For unique clusters, I’m doing 2.26 commands per cluster. So if I
used sticky keys, or a modal switcher, it would not be a gain. E.g.
<code>C f f C</code> vs <code>C-f C-f</code> is no gain, it’s actually
more presses due to having to hit C again.</p>
<p>But in terms of non-unique clusters, there’s a gain at 3.44 commands
per cluster. That means <code>C f f f C</code> vs
<code>C-f C-f C-f</code>, which is one key less pressed. If I’m pressing
<code>9218</code> keys for <code>C-</code>/<code>M-</code> commands,
there might be a 20% decrease in key presses.</p>
<p>I’d love to see a similar analysis done of Vim. How often do Vim
users switch from insert mode to normal or presentation mode? I will
continue recording my keys for the next couple of days.</p>
<p>Very interesting is how much I use navigation functions. In reaction
to this, I’m disabling those keybindings and switching to arrow keys.
And I’ve found <code>M-e</code>, a more convenient binding for
<code>C-M-u</code>. I will also stop using <code>C-d</code> and use
<code>DEL</code>.</p>
<p><a href="/posts/speculations-on-exclusive-editing">Follow-up page
→</a></p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2013-08-07 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Wed, 07 Aug 2013 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Haskell News]]></title><link>https://chrisdone.com/posts/haskell-news</link><guid>https://chrisdone.com/posts/haskell-news</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Haskell News</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Haskell News</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>As a consumer of Haskell content I neither have the time nor
inclination to follow haskell-cafe and other various mailing lists, the
reddits, the google+ community, planet haskell, hackage releases,
twitter, youtube and whatever other submission places I haven’t heard
of.</p>
<p>I wrote this <a
href="http://www.haskell.org/pipermail/haskell-cafe/2013-February/104898.html">to
Haskell-Cafe</a> four months ago. Only one person responded, which was
<a
href="http://www.haskell.org/pipermail/haskell-cafe/2013-February/104899.html">Daniel
Díaz Casanueva</a>, the producer of <a
href="http://contemplatecode.blogspot.it/">Haskell Weekly News</a>.
Naturally this would be a great resource for him, as it would summarize
everything of the past few days in one place.</p>
<p>Shortly after this post I went ahead and implemented <a
href="http://haskellnews.org/">Haskell News</a> for which you can find
<a href="https://github.com/chrisdone/haskellnews/">the source code here
on GitHub</a>.</p>
<p>It has two views: grouped and mixed. Grouped lists all the items
according to their source, and mixed lists everything in a flat stream.
The mixed view polls for updates every ten minutes, so that users can
leave it open in a tab a la Twitter. There is also <a
href="http://haskellnews.org/feed">an RSS feed</a>, because I heard you
like feeds, so I put a feed in your feed so you can subscribe while you
subscribe.</p>
<p>The sources, as of writing, are:</p>
<ul>
<li>Reddit: /r/haskell and /r/programming posts containing the word
“haskell”</li>
<li>Haskell-Cafe</li>
<li>Stack Overflow: questions tagged “haskell”</li>
<li>Pastes: pastes made to the #haskell channel</li>
<li>GitHub: updates for projects that contain Haskell code</li>
<li>Planet Haskell</li>
<li>Google+: posts to the Haskell community</li>
<li>Twitter: posts tagged “#haskell” or containing “Haskell”</li>
<li>Hackage</li>
<li>IRC Quotes: things that have been <span class="citation"
data-cites="remember">@remember</span>’d in the #haskell channel</li>
<li>Vimeo: various Haskell related feeds</li>
<li>HaskellWiki: updates to the wiki</li>
</ul>
<p>I think this paints a fairly comprehensive picture of the Haskell
community’s public activities. Certainly, if you want Haskell news, here
is the best place online to go.</p>
<p>All the feeds are updated every ten minutes. All of the feeds are
taken from RSS or Atom feeds, with the exception of three, which I
scraped with tagsoup:</p>
<ul>
<li>Google+, which provides no RSS feed (but they do provide an API,
which I could look into if I had nothing better to do)</li>
<li>Twitter, which no longer provides an RSS feed (but they do provide
an API, which I could look into if I had nothing better to do)</li>
<li>Github, which does not provide an RSS feed for language-specific
project updates (I don’t know if they have an API, nor care too
much)</li>
</ul>
<p>All feed items are stored in a database forever. There are currently
17k entries from 4 months of running. Feeds are unparseable for the feed
library from time to time.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2013-07-26 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Fri, 26 Jul 2013 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[IRC Browse]]></title><link>https://chrisdone.com/posts/ircbrowse</link><guid>https://chrisdone.com/posts/ircbrowse</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>IRC Browse</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>IRC Browse</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Haven’t blogged in a while, had some time to write now.</p>
<p>Since I last blogged, I made <a href="http://ircbrowse.net/">IRC
Browse.</a> It’s a service which allows you to browse the IRC logs of
the #haskell and #lisp channels of Freenode. The logs come from <a
href="tunes.org/~nef/logs/">tunes</a>, and, for <a
href="http://ircbrowse.net/browse/haskell">Haskell</a>, they go back to
2001. I like IRC. I don’t go on it that frequently anymore, but I like
to read the logs and I see it for the useful communication and
coordination tool it is. I’ve always wanted a trivial way to view and
share IRC logs as a service, so I made one. The source code is <a
href="https://github.com/chrisdone/ircbrowse">here</a>.</p>
<p>It boasts these features:</p>
<ul>
<li><a href="http://ircbrowse.net/">A simple summary</a> of statistics
on the home page</li>
<li><a href="http://ircbrowse.net/browse/haskell">Browsing, page by
page</a>, all the logs</li>
<li><a
href="http://ircbrowse.net/browse/haskell?q=chrisdone">Searching</a> the
logs</li>
<li><a href="http://ircbrowse.net/nick/chrisdone">Viewing a statistics
profile</a> of a particular person</li>
</ul>
<p>It’s written in Haskell, using Snap, PostgreSQL for the database, and
Sphinx for search. It’s fast.</p>
<p>I made it ages ago, really, but thought it worth blogging about
once.</p>
<h2 id="the-irc-summary">The IRC summary</h2>
<p>The IRC summary is generated upon request, and reveals some possibly
interesting insights into channel activity and the top contributors.</p>
<p>Of interest the most is the activity by year, which indicates that
2009 was the apex of the IRC channel’s activity, which has since
dwindled, and appears to be continuing to dwindle: despite sustained
activity, conversation generally is decreasing.</p>
<p>There are various hypotheses put forth for this. I speculate that</p>
<ul>
<li>People have been moving to other channels, such as #haskell-lens,
#haskell-blah, etc.</li>
<li>People are able to read reliable books that are now well publicized
in contrast to in the past</li>
<li>Some very active people have moved on</li>
</ul>
<h2 id="browsing">Browsing</h2>
<p>This is where the name “IRC Browse” comes from. There used to be a
service at ircbrowse.com, a few years back, providing a similar browsing
service. I asked the author of that old site whether I could use the
name ircbrowse.net, and they approved and wished me luck.</p>
<p>One thing that bugged me about the old IRC Browse was the speed. It
was god-awfully slow. It would take ages just to display one page of
logs. What I wanted was to have a log browsing service that would be
<em>instantaneous</em> and snappy.</p>
<p>After some learning with PostgreSQL, I discovered some ways to make
paginating 26 million rows of a table quite fast. Simply using
<code>OFFSET</code>/<code>LIMIT</code> is far too slow—takes about one
second to retrieve a result. I couldn’t simply query on the IDs, because
there isn’t just one channel, or one pagination type. So I created a
separate table to store paging indexes. For every row of the “event”
table, I created a corresponding, ordered, row in the index table. After
that, it was snappy.</p>
<p>Another thing I discovered is that my pgsql-simple library was a
little sluggish. The pages would retrieve in, say, 50ms, rather than,
say, 2ms. So I switched the library to postgresql-simple and got the
extremely snappy responsiveness that I wanted.</p>
<h2 id="searching">Searching</h2>
<p>For searching I learned how to use the tool called Sphinx. It takes
in a configuration and a database, and then populates a search index.
From that search index, it provides very fast full text search.</p>
<p>I couldn’t get the Sphinx library to work with the version of Sphinx
I was using at the time. I made a trivial wrapper to the command line
program instead. That worked. At some point I will replace this with use
of the Haskell sphinx library.</p>
<p>Another optimization I can do is split the indexes into #haskell and
#lisp.</p>
<h2 id="profiles">Profiles</h2>
<p>Profiles give a nice way to tell when someone probably goes to sleep
and is probably available. It also tells whether someone has been active
lately. If they haven’t been active lately, you can check their complete
history by year, and if you see it dwindling, perhaps they’re not on the
IRC anymore.</p>
<p>There are also quotes <span class="citation"
data-cites="remember">@remember</span>’d by lambdabot, which can be fun
to read.</p>
<h2 id="importation">Importation</h2>
<p>Importing the logs happens daily, at 10:30 UTC time. One day I might
update this so that it connects to the IRC directly and updates the logs
in real time. But I’m not sure it’s worth it.</p>
<h2 id="other-stuff">Other stuff</h2>
<p>I also did a social graph thing, but it’s not that good and I will
probably remove it. There’s a word cloud, which looks pretty enough,
I’ll keep that.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2013-07-23 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Tue, 23 Jul 2013 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Fay, JavaScript, etc.]]></title><link>https://chrisdone.com/posts/fay</link><guid>https://chrisdone.com/posts/fay</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Fay, JavaScript, etc.</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Fay, JavaScript, etc.</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>A couple months back I released Fay in a preliminary stage, with a <a
href="http://fay-lang.org/">little web site of its own</a>. I haven’t
blogged about it yet, so I thought I’d do that.</p>
<h2 id="setting-the-scene">Setting the scene</h2>
<p>And lo, when God created the world, he looked at it, and saw that it
was good.</p>
<p>When Brendan Eich created JavaScript, he looked at it, and saw that
it was good enough given the questionable requirements and strict time
constraints.</p>
<p>When I look at JavaScript, I see that it is bad. And not good enough
given the various other superior languages out there.</p>
<p>But I repeat myself, see <a
href="http://www.haskell.org/haskellwiki/The_JavaScript_Problem">The
JavaScript Problem</a> for more details.</p>
<h2 id="recognizing-it-as-a-real-problem">Recognizing it as a real
problem</h2>
<p>I think any developer with their head screwed on knows about the
above problems and that JavaScript needs to be replaced as soon as
possible. But the problem is immediate.</p>
<p>My approach to the problem, as with everyone else, has long been:
well, we can’t do anything about it, let’s just wait for Google to
complete their native client project and hope that it breaks the market.
Or, let’s wait until the existing compiling-to-JavaScript solutions
become usable.</p>
<p>Any way you look at it, as you sit down to write a new project, and
every time you get a stupid error due to JavaScript’s wackiness, you say
to yourself “just one more project in JavaScript… just this quick
script…”</p>
<p>After seeing Inventing on Principle<a href="#fn1"
class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a>, I
was profoundly influenced by Bret Victor’s message. His talk was
impressive, but his message was moreso. The idea that I took away from
watching it was:</p>
<p>“If you recognise something as a problem, and you have the capability
to fix it, you have a moral duty to fix that problem.”</p>
<p>I’m not sure I have such strong convictions as Bret to apply that
generally, but his principled approach influenced me. One day I wanted
to write a web app, and got that sinking feeling of wasting it on
JavaScript, and decided never to write any JavaScript again for a new
project.</p>
<h2 id="fixing-the-problem">Fixing the problem</h2>
<p>I decided that to make such a claim, I should have to back it up with
a solution, and do it fast. So I spent that weekend hacking on a Haskell
compiler for JavaScript. I spent another weekend polishing it, and on
the third week I was using it at work in production. Back then the
project was called “hj.” And for months it sat hidden, private to me. A
mini-success and a solution to the problem I saw.</p>
<p>I’ll note that Elm and Roy also inspired me to give it a go.</p>
<h2 id="reaction">Reaction</h2>
<p>Fast-forward a couple months, I decide it’s time to re-brand it to
something friendly and put it online. I called it “Fay.”</p>
<p>Someone posted it to Reddit’s programming forum and Hacker News, and
the site got about ten thousand hits in two days. Lots of interest
generated, and people emailed me asking what the implications of such a
project are. That’s really encouraging!</p>
<p>I got invited to talk at <a href="http://2012.lxjs.org/">LXJS</a>, a
JavaScript conference. I will be going in two weeks. Ironically, I will
go to basically say how much I dislike JavaScript to a crowd of people
who mostly like JavaScript, but that’s how I roll.</p>
<p>After putting it on Github I had quite <a
href="https://github.com/faylang/fay/network">a few contributions</a>,
too!</p>
<p>Today and tomorrow I’ll be producing a bunch of demo examples of Fay
code, and finalizing my short 20-minute talk.</p>
<h2 id="future-work">Future work</h2>
<p>Fay is missing some things that would be nice to have:</p>
<ul>
<li>Type-classes</li>
<li>Tail-call optimization</li>
<li>Strictness analysis</li>
<li>Source mappings</li>
<li>Cabal support</li>
<li>Lots more other stuff</li>
</ul>
<p>But these can wait a bit of time. I could/would write more, in more
detail, but I have a lot of stuff to do at the moment. So, apologies for
the brief post, but I thought it was worth having this post in the blog
for the sake of chronology, and to get this series of events out of my
system. That’s the point of a blog, right?</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Watch it on <a
href="http://vimeo.com/36579366">Vimeo</a>, or on <a
href="http://www.youtube.com/watch?v=PUv66718DII">YouTube</a>.<a
href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2012-09-15 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sat, 15 Sep 2012 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Making HaskellDB slightly more type-safe]]></title><link>https://chrisdone.com/posts/haskelldb-more-type-safe</link><guid>https://chrisdone.com/posts/haskelldb-more-type-safe</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Making HaskellDB slightly more type-safe</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Making HaskellDB slightly more type-safe</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>I was just discussing HaskellDB’s major flaws with Oliver Charles and
I noted that one <em>huge</em> problem is that the type of
<code>update</code> does not restrict the record given to make the
update. Its type is</p>
<pre><code>update :: (ShowLabels s, ToPrimExprs s)
       =&gt; Database             -- ^ Database.
       -&gt; Table r              -- ^ Entity.
       -&gt; (Rel r -&gt; Expr Bool) -- ^ Predicate.
       -&gt; (Rel r -&gt; Record s)  -- ^ Updates.
       -&gt; IO ()</code></pre>
<p>which is straight-forward enough. The problem is the “updates”
argument, which will allow me to write a bogus field that does not
belong to <code>r</code>, like</p>
<pre><code>update mytable
       (\row -&gt; row!field .==. whatever)
       (\row -&gt; badfield &lt;&lt;- whatever)</code></pre>
<p>This problem actually bit me in the ass in production once before.
That is not an exciting bug to have.</p>
<p>So I thought, we need to prove that for the type above,
<code>s &lt;: r</code> (read as “s is a <a
href="http://en.wikipedia.org/wiki/Subtype_polymorphism">subtype</a> of
r”). How do we express that? How about a type class.</p>
<p>The type-class can be</p>
<pre><code>class Subset sub super</code></pre>
<p>But how to implement it? Well, we need to say that for every
<code>field</code> of sub, that <code>field</code> is also a field of
<code>super</code>. That’s made easy for us, because HaskellDB already
has a <code>HasField field record</code> class for exactly that!</p>
<pre><code>instance (HasField field super,Subset sub super) =&gt;
         Subset (RecCons field typ sub) super</code></pre>
<p>This is similar to traversing a list at the value level, with
<code>RecCons field type sub</code> like a pattern-match on the current
element. You can read it as:</p>
<blockquote>
<p><code>sub</code> is a subset of <code>super</code>, if
<code>super</code> has the <code>field</code> of the head of the list,
and the tail is a subset of super</p>
</blockquote>
<p>So far so good. Now we need a base case, to cover the last element of
the list:</p>
<pre><code>instance Subset RecNil super</code></pre>
<p>And we’re done. Update now becomes</p>
<pre><code>update :: (Subset s r,ShowLabels s, ToPrimExprs s)
       =&gt; Database             -- ^ Database.
       -&gt; Table r              -- ^ Entity.
       -&gt; (Rel r -&gt; Expr Bool) -- ^ Predicate.
       -&gt; (Rel r -&gt; Record s)  -- ^ Updates.
       -&gt; IO ()</code></pre>
<p>Testing this on my codebase actually found a bug in which I was using
the wrong field!</p>
<p>I will send this to the maintainer of HaskellDB as it’s a glaring bug
waiting to happen to someone.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2012-08-25 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sat, 25 Aug 2012 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Comments on my blog]]></title><link>https://chrisdone.com/posts/blog-comments</link><guid>https://chrisdone.com/posts/blog-comments</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Comments on my blog</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Comments on my blog</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Comments are unsupported on my blog for the same reason as <a
href="http://www.scripting.com/2007/01/01.html#theUneditedVoiceOfAPerson">Dave
Winer</a> gives:</p>
<blockquote>
<p>“…to the extent that comments interfere with the natural expression
of the unedited voice of an individual, comments may act to make
something not a blog…. The cool thing about blogs is that while they may
be quiet, and it may be hard to find what you’re looking for, at least
you can say what you think without being shouted down. This makes it
possible for unpopular ideas to be expressed. And if you know history,
the most important ideas often are the unpopular ones…. That’s what’s
important about blogs, not that people can comment on your ideas. As
long as they can start their own blog, there will be no shortage of
places to comment.”</p>
</blockquote>
<p>Joel Spolsky first exposed me to the above. He elaborates <a
href="http://www.joelonsoftware.com/items/2007/07/20.html">in his
blog</a>:</p>
<blockquote>
<p>The important thing to notice here is that Dave does not see blog
comments as productive to the free exchange of ideas. They are a part of
the problem, not the solution. You don’t have a right to post your
thoughts at the bottom of someone else’s thoughts. That’s not freedom of
expression, that’s an infringement on their freedom of expression. Get
your own space, write compelling things, and if your ideas are smart,
they’ll be linked to, and Google will notice, and you’ll move up in
PageRank, and you’ll have influence and your ideas will have power.</p>
</blockquote>
<p>If I wanted to have my expression shared and democratised I’d comment
on a forum.</p>
<p>People email me regarding my blog with ideas and errata/amendments
all the time, I’m glad for them, and I reply.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2012-01-19 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Thu, 19 Jan 2012 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Ji, a little library for controlling a web browser from Haskell]]></title><link>https://chrisdone.com/posts/ji-haskell-web</link><guid>https://chrisdone.com/posts/ji-haskell-web</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Ji, a little library for controlling a web browser from
Haskell</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Ji, a little library for controlling a web browser from Haskell</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p><strong>UPDATE</strong>: This project was forked into <a
href="https://github.com/HeinrichApfelmus/threepenny-gui">Threepenny-gui</a>
in 2012~.</p>
<hr />
<p>As of recent I have only been creating a lot of new projects, not
working one existing ones or finishing half done ones off.<a href="#fn1"
class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></p>
<p>So here’s yet another little project that is to test the concept of
controlling the web browser’s DOM from Haskell as a means to write user
applications.</p>
<p>It doesn’t use websockets as websockets aren’t well supported<a
href="#fn2" class="footnote-ref" id="fnref2"
role="doc-noteref"><sup>2</sup></a>, so I just used a simple poll/push
protocol.</p>
<p>The code is on Github:</p>
<ul>
<li><a
href="https://github.com/chrisdone-archive/ji">https://github.com/chrisdone-archive/ji</a></li>
</ul>
<p>Here are <a
href="https://github.com/chrisdone-archive/ji/tree/master/examples">examples
I made.</a></p>
<p>It seems fairly viable so far. I would have liked to produce many
more examples, but I couldn’t really think of any. I stole the idea for
the dollars from Albert Lai. There is more room for optimizations, but
until I do a more large scale test, hard to say exactly where needs
it.</p>
<p>It might be a good test to rewrite TryHaskell with it. Probably still
too easy. I’ll give it a while to think about it.</p>
<p>It could be a base on which to build a more high-level library or
framework.</p>
<p>I could also write a back-end for digestive-formlets.</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Partly this is a way to feel like
I’ve spent my time well as it’s easier to complete something small, and
partly that ideas I get which sound feasible typically linger in my head
asking to be prototyped, so this is a way of flushing them out.<a
href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p>I wanted to use socket.io but there
is no Haskell socket.Io back-end, and I didn’t feel like writing Node.
There are several websockets Haskell libraries, but as mentioned
websockets itself isn’t well supported, I’d have to upgrade to try it
(and so would everyone else). Websockets would be the eventual protocol,
though.<a href="#fnref2" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2011-12-26 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Mon, 26 Dec 2011 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[A concept for editing code as an AST rather than text]]></title><link>https://chrisdone.com/posts/concept-for-editing-asts-rather-than-text</link><guid>https://chrisdone.com/posts/concept-for-editing-asts-rather-than-text</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>A concept for editing code as an AST rather than text</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>A concept for editing code as an AST rather than text</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p><a href="http://www.youtube.com/watch?v=v2ypDcUM06U">Here is a demo
video</a>.</p>
<p>It’s not my intention for this to be all point and click, at all, but
coming up with keybindings and a means to navigate the AST via keyboard
is an interesting problem somewhat separate to the problem of
creating/displaying/editing as-is. As you can see I’m even confused
myself when using it, and it’s a lot slower with the mouse. With
keyboard control it could be blindingly faster than any text
editing-based language editors available now. Think paredit-mode, but
for non-Lisp languages.</p>
<p>I’ve had this idea in the back of my mind for years and today thought
that I might do a concept implementation to solidify the idea
somewhat.</p>
<p>The idea is that you can’t create a syntactically invalid tree, and
at each point it can offer you a choice between the valid choices.
That’s one part, the correctness. But that’s merely a nice side-effect
to the idea of purely syntactical editing, rather than textual editing,
so that jumping around, transposing, moving, deleting expressions will
be a lot easier. Even so that there is no need to care about
indentation, but rather moving things about the AST. Still merely a
concept at this point. It’s really hard to think about what you might
like from an editing mode like this without going ahead and implementing
something.</p>
<p>It can technically be generalized to any programming language, but
Haskell is my main working language so I am targeting it
specifically.</p>
<p>It could also be helpful for newbies, being guided on the syntax.
Purists will argue people should be able to write syntax. I suppose
they’d be right.</p>
<p>In summary I made a little DSL for describing an AST for manipulating
like this. There is a “list of things” combinator, an “optional”
combinator (e.g. the “module” decl is optional), there is a “choice”
combinator, e.g. when adding a new top-level decl it prompts for a
choice between the different types of decls, validating text inputs
(e.g. module name, constructor, variable, etc.), and that is more or
less enough, as far as I can tell, so far. Hopefully it won’t get much
more complicated than that.</p>
<p>For a real implementation I would probably do it in Emacs, if
overlays would permit me enough power to do it (I think so). But it
could also be implemented in Yi, or Leksah, or Vim, or whatever, were
those users so inclined.</p>
<p>If you’re implementing something like this already, I’d be interested
to see it. If you have some interesting ideas, feel free to comment.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2011-12-17 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sat, 17 Dec 2011 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[A map generic upon the value thanks to typeable]]></title><link>https://chrisdone.com/posts/generic-map</link><guid>https://chrisdone.com/posts/generic-map</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>A map generic upon the value thanks to typeable</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>A map generic upon the value thanks to typeable</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Not sure why I never tried this before.</p>
<pre><code>{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE DeriveDataTypeable #-}

import Data.Typeable
import qualified Data.Map as M
import Data.Map (Map)

data Person = Person Integer String
  deriving (Typeable,Show)

data Value = forall v. Typeable v =&gt; Value v

demo = do
  print (glookup &quot;foo&quot; map :: Maybe ())
  print (glookup &quot;bar&quot; map :: Maybe Char)
  print (glookup &quot;chris&quot; map :: Maybe Person)

    where map = M.insert &quot;bar&quot; (Value &#39;a&#39;) $
                M.insert &quot;foo&quot; (Value ())  $
                M.insert &quot;chris&quot; (Value (Person 123 &quot;Chris Done&quot;))  $
                M.empty

glookup :: (Typeable a,Ord key) =&gt; key -&gt; Map key Value -&gt; Maybe a
glookup key map =
  case M.lookup key map of
    Nothing -&gt; Nothing
    Just (Value x) -&gt; (cast x)

-- λ&gt; demo
-- Just ()
-- Just &#39;a&#39;
-- Just (Person 123 &quot;Chris Done&quot;)</code></pre>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2011-12-05 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Mon, 05 Dec 2011 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[HaskellDB: A long tutorial]]></title><link>https://chrisdone.com/posts/haskelldb-tutorial</link><guid>https://chrisdone.com/posts/haskelldb-tutorial</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>HaskellDB: A long tutorial</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>HaskellDB: A long tutorial</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>I’ve been using HaskellDB in production for about two years. I
decided that I’d write a proper, up-to-date description, or tutorial,
about what it is, how it works, what it can do, and my experience using
it in projects.<a href="#fn1" class="footnote-ref" id="fnref1"
role="doc-noteref"><sup>1</sup></a></p>
<h2 id="what-is-haskelldb">What is HaskellDB?</h2>
<p><a href="http://hackage.haskell.org/package/haskelldb">HaskellDB</a>
is a database interface library for Haskell which features</p>
<ul>
<li>explicit declaration of schema of entities and fields,</li>
<li>an EDSL<a href="#fn2" class="footnote-ref" id="fnref2"
role="doc-noteref"><sup>2</sup></a>—a <code>Query</code> monad—for
making queries and statements based on using operations based on the
relational algebra<a href="#fn3" class="footnote-ref" id="fnref3"
role="doc-noteref"><sup>3</sup></a>,</li>
<li>a simple record system for dealing with entities and fields.</li>
</ul>
<p>It was originally developed for Hugs making use of the TRex, but was
later made portable and is now happy in both Hugs and GHC<a href="#fn4"
class="footnote-ref" id="fnref4"
role="doc-noteref"><sup>4</sup></a>.</p>
<p>The <a href="http://rubyonrails.org/">Ruby on Rails project</a>
recently adopted <a href="http://github.com/rails/arel">ARel, a library
based on the same idea</a>.</p>
<h2 id="connecting">Connecting</h2>
<p>So to connect to a database with HaskellDB, you can use different
backends. In this case, I’ll assume you’re using HDBC as a backend.</p>
<p>Pop them in a separate module:</p>
<pre><code>module Caturday.Model.Connect where

import Database.HaskellDB.HDBC
import Database.HaskellDB.Sql.PostgreSQL
import Database.HDBC.PostgreSQL (connectPostgreSQL)

withDB :: [(String,String)] -&gt; (Database -&gt; IO a) -&gt; IO a
withDB opts = hdbcConnect generator (connectPostgreSQL conninfo)
  where conninfo = unwords [ k ++ &quot;=&quot; ++ v | (k,v) &lt;- opts ]

opts = [(&quot;host&quot;,&quot;localhost&quot;)
       ,(&quot;user&quot;,&quot;your_username&quot;)
       ,(&quot;password&quot;,&quot;your_password&quot;)
       ,(&quot;dbname&quot;,&quot;your_db_name&quot;)]</code></pre>
<p>Usually you ought to combine this with configuration options.</p>
<h2 id="orm-approach">ORM approach</h2>
<h3 id="fields">Fields</h3>
<p>The approach for the object relational mapping is that one defines
the column types and entity schemas up front. So, supposing our project
is named Caturday, in a module named
<code>Caturday.Model.Fields</code>,<a href="#fn5" class="footnote-ref"
id="fnref5" role="doc-noteref"><sup>5</sup></a> using the
<code>field</code> macro,<a href="#fn6" class="footnote-ref" id="fnref6"
role="doc-noteref"><sup>6</sup></a> one declares fields. For
example:</p>
<pre><code>{-# LANGUAGE TemplateHaskell #-}

-- | All database fields.

module Caturday.Model.Fields where

import Database.HaskellDB.TH

-- Keys.
field &quot;Id&quot; &quot;id&quot; &quot;id&quot; [t|Int|]

-- Data fields.
field &quot;Title&quot; &quot;title&quot; &quot;title&quot; [t|String|]</code></pre>
<p>This produces three things:</p>
<ul>
<li>A type called <code>Title</code>.</li>
<li>A field variable called <code>title</code>.</li>
<li>An instance of the field class which can be used to reference
<code>title</code> in the database.</li>
</ul>
<p>In other words, a Haskell-level representation of the database field
“title”.</p>
<h3 id="tables">Tables</h3>
<p>Then one defines the entities that use those fields in a module such
as <code>Caturday.Model.Tables</code>, using the <code>table</code>
macro<a href="#fn7" class="footnote-ref" id="fnref7"
role="doc-noteref"><sup>7</sup></a>. For example:</p>
<pre><code>{-# LANGUAGE TemplateHaskell #-}

-- | Database tables and entities.

module Caturday.Model.Tables where

import Caturday.Model.Fields as Fields

import Database.HaskellDB.TH
import Prelude ()

-- | Content table.
table &quot;content&quot; &quot;content&quot;
  [&#39;id
  ,&#39;title
  ]</code></pre>
<p>The first argument is the Haskell-level value name for the table, and
the second is the SQL-level name of the entity. To import
<code>Fields as Fields</code> is a good idea.<a href="#fn8"
class="footnote-ref" id="fnref8" role="doc-noteref"><sup>8</sup></a></p>
<h3 id="importing">Importing</h3>
<p>Once the model schema has been defined in these two modules, one
ought to import them like so:</p>
<pre><code>import qualified Caturday.Model.Fields as F
import qualified Caturday.Model.Tables as T

import Database.HaskellDB
import Database.HaskellDB.HDBRec</code></pre>
<p>So that later we will refer to fields as <code>F.foo</code> and
tables as <code>T.bar</code>.</p>
<h2 id="querying">Querying</h2>
<h3 id="selection">Selection</h3>
<p>Queries and statements in HaskellDB are composed with the
<code>Query</code> monad. For example, simple selection works like
this:</p>
<pre><code>simpleSelection = do
  table T.content</code></pre>
<p>We use the <code>table</code> function to select tables from our
predefined set of tables. It returns a relation of some kind;
i.e. tables or result of a sub-select or projection, etc.</p>
<p>To select more tables (i.e., <em>joining</em>) we just list more
tables:</p>
<pre><code>simpleDoubleSelection = do
  table T.content
  table T.content</code></pre>
<p>We execute this query with <code>withDB</code>, for example:</p>
<pre><code>λ&gt; fmap (take 1) $ withDB opts $ \db -&gt; query db simpleSelection
[[(&quot;id&quot;,&quot;34750&quot;),(&quot;title&quot;,&quot;\&quot;Spanner Based Distributed Channel Assignment in Wireless Mesh Networks\&quot;&quot;)]]</code></pre>
<h3 id="projection">Projection</h3>
<p>For projection we use the <code>project</code> function defined in
<code>Database.HaskellDB.Query</code>:</p>
<pre><code>simpleProjection = do
  content &lt;- table T.content
  project $ F.id &lt;&lt; content!F.id</code></pre>
<p>For each field we want to project, we specify a value for it using
the <code>(&lt;&lt;)</code> function, defined in
<code>Database.HaskellDB.Query</code>. To project more fields, we use
the record constructing operator, <code>(#)</code>:</p>
<pre><code>simpleProjection2 = do
  content &lt;- table T.content
  project $ F.id    &lt;&lt; content!F.id
          # F.title &lt;&lt; content!F.title</code></pre>
<p>One can see this operator as akin to the tuple constructor
<code>(,)</code> as in <code>(1,2)</code>.</p>
<p>We can also project our own Haskell-level values as SQL
constants:</p>
<pre><code>simpleStringProjection = do
  content &lt;- table T.content
  project $ F.id    &lt;&lt; constant 123
          # F.title &lt;&lt; constant &quot;Hello, World!&quot;</code></pre>
<p>Personally in my use, I have renamed <code>constant</code> to
<code>val</code>.<a href="#fn9" class="footnote-ref" id="fnref9"
role="doc-noteref"><sup>9</sup></a> I just find this more convenient. I
will use this henceforth.</p>
<pre><code>import Database.HaskellDB.Extra</code></pre>
<h3 id="restriction">Restriction</h3>
<p>We restrict results using the <code>restrict</code> function:</p>
<pre><code>simpleRestriction = do
  content &lt;- table T.content
  restrict $ content!F.title .==. val &quot;Coco Jambo&quot;
  return content</code></pre>
<p>The restrict function takes an SQL boolean expression:</p>
<pre><code>λ&gt; :i restrict
restrict :: Expr Bool -&gt; Query ()
        -- Defined in Database.HaskellDB.Query</code></pre>
<p>For boolean expressions there are a bunch of logical operators that
commonly appear in SQL:</p>
<pre><code>-- | Equality comparison on Exprs, = in SQL.
(.==.) :: Eq a =&gt; Expr a -&gt; Expr a -&gt; Expr Bool

-- | Inequality on Exprs, &lt;&gt; in SQL.
(.&lt;&gt;.) :: Eq a =&gt; Expr a -&gt; Expr a -&gt; Expr Bool
(.&lt;.) :: Ord a =&gt; Expr a -&gt; Expr a -&gt; Expr Bool
(.&gt;=.) :: Ord a =&gt; Expr a -&gt; Expr a -&gt; Expr Bool

-- | \&quot;Logical and\&quot; on &#39;Expr&#39;, AND in SQL.
(.&amp;&amp;.):: Expr Bool -&gt; Expr Bool -&gt; Expr Bool

-- | \&quot;Logical or\&quot; on &#39;Expr&#39;. OR in SQL.
(.||.) :: Expr Bool -&gt; Expr Bool -&gt; Expr Bool</code></pre>
<p>Note that the convention is for operators in HaskellDB to be
surrounded by periods. For more see the Operators section of
Database.HaskellDB.Query.</p>
<h3 id="raw-sql-output">Raw SQL Output</h3>
<p>To get a concrete feeling of what SQL this code will produce, let’s
observe the output. To do that, we can use <code>ppSqlUnOpt</code>:</p>
<pre><code>λ&gt; :i ppSqlUnOpt
ppSqlUnOpt :: Query (Rel r) -&gt; Text.PrettyPrint.HughesPJ.Doc
        -- Defined in Database.HaskellDB.PrintQuery</code></pre>
<p>The simple selection:</p>
<pre><code>λ&gt; ppSqlUnOpt simpleSelection
SELECT id,
       title
FROM content as T1</code></pre>
<p>The projection example:</p>
<pre><code>λ&gt; ppSqlUnOpt simpleProjection
SELECT id as id1,
       title as title1
FROM content as T1</code></pre>
<p>The constant value example:</p>
<pre><code>λ&gt; ppSqlUnOpt simpleStringProjection
SELECT 123 as id,
       &#39;Hello, World!&#39; as title,
       id1,
       title1
FROM (SELECT id as id1,
             title as title1
      FROM content as T1) as T1</code></pre>
<p>The code is clear to read and not that surprising.</p>
<h3 id="insertion-delete-update">Insertion, delete, update</h3>
<p>Insertion uses the <code>insert</code> function. Similar to the
<code>query</code> function, it takes a connection value. Pretty
self-explanatory:</p>
<pre><code>simpleInsert conn = do
  insert conn
         T.content
         ( F.id    &lt;&lt; val 123
         # F.title &lt;&lt; val &quot;What is Love?&quot;)</code></pre>
<p>The delete function takes a restriction clause for the row to delete,
with the ability to inspect the row for the condition.</p>
<pre><code>simpleDelete conn = do
  delete conn
         T.content
         (\content -&gt; content!F.title .==. val &quot;Coco Jambo&quot;)</code></pre>
<p>Updating is the same as insert, but we provide a function for the
update:</p>
<pre><code>simpleUpdate conn = do
  update conn
         T.content
         (\content -&gt; content!F.title .==. val &quot;Coco Jambo&quot;)
         (\content -&gt; F.title &lt;&lt; val &quot;What is Love?&quot;)</code></pre>
<h2 id="speed-and-optimisation">Speed and optimisation</h2>
<p>But the subquery is useless in this example, so clearly the optimizer
isn’t magic.</p>
<pre><code>λ&gt; ppSqlUnOpt simpleDoubleSelection
SELECT id2 as id,
       title2 as title
FROM (SELECT id as id2,
             title as title2
      FROM content as T1) as T1,
     (SELECT id as id1,
             title as title1
      FROM content as T1) as T2</code></pre>
<p>In fact, subqueries are created in all cases.</p>
<p>For normal query optimizers, e.g. PostgreSQL, the subquery is lifted
as to be equivalent to there being one query. I am not sure about MySQL;
it may have trouble when joins are involved. Don’t expect good
performance from HaskellDB if you’re using MySQL.<a href="#fn10"
class="footnote-ref" id="fnref10"
role="doc-noteref"><sup>10</sup></a></p>
<p>For example, PostgreSQL sees such use of sub-query as equivalent to
direct join:</p>
<pre><code>=&gt; explain SELECT id2 as id,
           title2 as title
    FROM (SELECT id as id2,
                 title as title2
          FROM content as T1) as T1,
         (SELECT id as id1,
                 title as title1
          FROM content as T1) as T2;
                          QUERY PLAN
------------------------------------------------------------------
 Nested Loop  (cost=1578.48..330231.64 rows=16353936 width=77)
 -&gt;Seq Scan on content t1 (cost=0.00..1574.44 rows=4044 width=77)
 -&gt;Materialize (cost=1578.48..1618.92 rows=4044 width=0)
   -&gt;Seq Scan on content t1 (cost=0.00..1574.44 rows=4044 width=0)
(4 rows)

=&gt; explain SELECT T1.id as id,
           T1.title as title
    FROM content as T1,
         content as T2;
                          QUERY PLAN
-------------------------------------------------------------------
 Nested Loop  (cost=1578.48..330231.64 rows=16353936 width=77)
 -&gt;Seq Scan on content t1 (cost=0.00..1574.44 rows=4044 width=77)
 -&gt;Materialize (cost=1578.48..1618.92 rows=4044 width=0)
   -&gt;Seq Scan on content t1 (cost=0.00..1574.44 rows=4044 width=0)
(4 rows)

=&gt;</code></pre>
<p>I’m not joining on any indexes so it’s a sequence scan. For people
not used to PostgreSQL output, this basically means it will do a
cartesian product in both versions.</p>
<h2 id="maintenance">Maintenance</h2>
<p>The great part about HaskellDB is that it is in first-class Haskell
land. Fields and tables have a statically enforced membership and
field-type schema.</p>
<p>The obvious use case is that it avoids making mistakes in naming and
ending up with the wrong field type, or using a field that doesn’t exist
in a given table.</p>
<p>The fact that all fields are defined up front with the right type
means that one really has to think about how meaningful a type is and
how one will use it. For example:</p>
<pre><code>field &quot;Abstract&quot; &quot;abstract&quot; &quot;abstract&quot; [t|Maybe String|]</code></pre>
<p>This is how to encode a database text field that is nullable. When
one is encoding their database schema into the Haskell type system, one
finds that it really needs to be thought of properly of what types are
there in the database, particularly nullability.</p>
<p>In my day to day work, I have to work with database schemas that
aren’t mine, I have to interface with them. Due to my use of HaskellDB,
I have a lot of correctness questions about these schemas I’m working
with to the authors, if they are available for consultation.</p>
<p>Often it comes up, that I ask “why is this field nullable?” and the
question often comes back, “I don’t know.” As the PostgreSQL
documentation says, in most database designs the majority of columns
should be marked not null.<a href="#fn11" class="footnote-ref"
id="fnref11" role="doc-noteref"><sup>11</sup></a></p>
<p>Note that in Haskell nullability is not implicit. No values can be
null. But you can have choice between a value or not a value, as in
<code>Maybe</code>:</p>
<pre><code>data Maybe a = Just a | Nothing</code></pre>
<p>And so if we use the abstract field, as mentioned, and use it as a
string, it’s not a string, it’s a <code>Maybe String</code>, so we get a
compile error such as:</p>
<pre><code>Mismatch: Demo.hs:23:32: “Maybe String” ≠ “String”</code></pre>
<p>Another nice property is that fields named in your codebase, and
their names in the database, are entirely separate and configurable.
Just because Joe Master Designer chose certain names in his schema, that
doesn’t mean that you have to conform to those names. Maybe they call it
<code>thetitle</code>, and you just want <code>title</code>:</p>
<pre><code>field &quot;Title&quot; &quot;title&quot; &quot;thetitle&quot; [t|String|]</code></pre>
<p>Another fact is changes to the schema underneath: if someone (you or
someone else) changes the type or availability of a field or table in
the schema, all you need do is make the necessary change in the field
module or table module, and the compiler will tell you immediately which
modules need updating with the new invariants.</p>
<p>Suppose we change the type of the field title to <code>Int</code>
(for example), when we recompile our examples above, we get:</p>
<pre><code>Mismatch: Demo.hs:23:32: “Int” ≠ “String”
Mismatch: Demo.hs:25:0: “String” ≠ “Int”</code></pre>
<p>So the following two functions are now inconsistent:</p>
<pre><code>simpleStringProjection = do
  content &lt;- table T.content
  project $ F.id    &lt;&lt; constant 123
          # F.title &lt;&lt; constant &quot;Hello, World!&quot;

simpleRestriction = do
  content &lt;- table T.content
  restrict $ content!F.title .==. val &quot;Coco Jambo&quot;
  return content</code></pre>
<p>In a codebase of 10K+ lines, this starts to become very
compelling.</p>
<p>I believe LINQ in C# et al provide similar static assurances.</p>
<h2 id="extension">Extension</h2>
<h3 id="pagination-and-composing-queries">Pagination and composing
queries</h3>
<p>Because the query DSL is a monad (as plenty of Haskell DSLs are), it
is really nicely composable. This means it’s trivial to split up queries
into discrete parts that have meaningful and generic purposes.</p>
<p>For example, to implement pagination, which is essentially the simple
problem of an offset and a count. I implemented this in
<code>HaskellDB.Database.Pagination</code>.<a href="#fn12"
class="footnote-ref" id="fnref12"
role="doc-noteref"><sup>12</sup></a></p>
<p>Thus the following implementation is possible. Suppose we write some
functions to search the articles by title in the database, but
paginated. Two things we need for this are:</p>
<ul>
<li>The count of total articles filtered by the search query,
<code>q</code>.</li>
<li>The paginated articles filtered by the search query.</li>
</ul>
<p>First we define a query that does the search and restriction:</p>
<pre><code>getContent q = do
  article &lt;- table T.content
  restrict $ article!F.title .==. val q
  return article</code></pre>
<p>In the fields module we need another field:</p>
<pre><code>field &quot;Count&quot; &quot;count&quot; &quot;count&quot; [t|Int|]</code></pre>
<p>Then we write the function that uses this query, and projects the
count:</p>
<pre><code>getArticlesCount conn q = fmap (sum . map (!F.count)) $ query conn $ do
  article &lt;- getContent q
  project $ F.count &lt;&lt; count (article!F.id)</code></pre>
<p>Then we can write a function to get the articles and then
paginate.</p>
<pre><code>getArticles conn pn q = fmap (map (!F.title)) $ query conn $ do
  article &lt;- getContent q
  paginate pn
  return article</code></pre>
<p>Very, very easy to compose.</p>
<h3 id="functions-and-operators">Functions and operators</h3>
<p>Sometimes you want to define more SQL functions and operators, which
is <a href="http://hpaste.org/53608">a use case I had for PostgreSQL</a>
as <code>Database.HaskellDB.PostgreSQL</code>.</p>
<p>The function to use for extending with new functions is
<code>func</code>.</p>
<pre><code>λ&gt; :i func
func :: (Args a) =&gt; String -&gt; a
        -- Defined in Database.HaskellDB.Query</code></pre>
<p><code>Args</code> is implemented as a way to have arbitrary number of
serializable parameters, in the same way <code>Text.Printf.printf</code>
works.</p>
<p>For example, <a
href="http://www.postgresql.org/docs/8.1/static/functions-datetime.html">date_part</a>
in PostgreSQL:</p>
<pre><code>-- | Get part of a date.
date_part :: Expr String -&gt; Expr CalendarTime -&gt; Expr Integer
date_part = func &quot;date_part&quot;</code></pre>
<p>Or maybe we want to use full text search support from PostgreSQL.
Let’s add a field to represent the <code>ts_vector</code>, and define a
table with the searchable stuff:</p>
<pre><code>-- | Search fields.
field &quot;Textsearchable&quot; &quot;textsearchable&quot; &quot;textsearchable_index_col&quot;
      [t|TSVector|]

-- | Content table with searchable full text field.
table &quot;contentSearchable&quot; &quot;content&quot;
  [&#39;id
  ,&#39;title
  ,&#39;textsearchable
  ]</code></pre>
<p>Now we can redefine <code>getContent</code> which matches on the
<code>ts_vector</code>:</p>
<pre><code>getContentFullText q = do
  article &lt;- table T.contentSearchable
  restrict $ article!F.textsearchable .@@. (to_tsquery (val q))
  order [descExpr $ ts_rank_cd (article!F.textsearchable)
                               (to_tsquery (val q))]
  return article</code></pre>
<p>This can be achieved by a phantom type (i.e. an uninhabitable type at
the value-level):</p>
<pre><code>-- | A text-search vector.
data TSVector

-- | Convert a string to a textsearch vector.
to_tsvector :: Expr String -&gt; Expr TSVector
to_tsvector = func &quot;to_tsvector&quot;</code></pre>
<p>And the function can be used, at the SQL-level, because the vector is
constructed at the SQL-level, not the Haskell level. That’s quite
nice.</p>
<p>Likewise, <code>descExpr</code> was written by me from the
Database.HaskellDB.Extra module:</p>
<pre><code>-- | Order the query by an arbitrary expression.
descExpr :: Expr a -&gt; OrderExpr
descExpr e = OrderExpr OpDesc expr where
  Expr expr = e</code></pre>
<p>One just needs access to the internal tree and a new combinator can
be constructed.</p>
<h2 id="enums">Enums</h2>
<p>It’s also possible to use enum types with HaskellDB that map from
DB-level enums and Haskell enums.</p>
<p>Suppose we define an Enums module, with an enum type
<code>ArticleType</code>:</p>
<pre><code>module Caturday.Types.Enums where

import Data.Enum.Print
import Database.HaskellDB.Get
import Database.HaskellDB.PrimQuery
import Database.HaskellDB.Query

data ArticleType
  = ResearchArticle
  | Editorial
  deriving (Show,Enum,Read,Eq)</code></pre>
<p>In order to get values of this type from the database with HaskellDB,
we need to implement the <code>GetValue</code> and the
<code>ShowConstant</code> classes:</p>
<pre><code>instance GetValue ArticleType where
  getValue = getValueWith readEnum &quot;ArticleType&quot;

instance ShowConstant ArticleType where
  showConstant = StringLit . showEnum</code></pre>
<p>This uses two <em>other</em> modules (I know, I’m referencing a lot
of modules I’ve written, sorry), <a
href="http://hpaste.org/53612">Data.Enum.Print</a>, a simple enum
serialization module, and <a
href="http://hpaste.org/53614">Database.HaskellDB.Get</a>, which
provides the <code>getValueWith</code> function.</p>
<p>Now we can define the fields that use this type in our Fields
module:</p>
<pre><code>import qualified Caturday.Types.Enums as Types (ArticleType)

-- | Enum types.
field &quot;ArticleType&quot; &quot;articleType&quot; &quot;type&quot; [t|Types.ArticleType|]</code></pre>
<p>and redefine the content table’s schema:</p>
<pre><code>-- | Content table.
table &quot;content&quot; content&quot;
  [&#39;id
  ,&#39;title
  ,&#39;articleType
  ]</code></pre>
<p>So now, our Demo module doesn’t compile, so we update:</p>
<pre><code>import Caturday.Types.Enums

simpleInsert conn = do
  insert conn
         T.content
         ( F.id          &lt;&lt; val 123
         # F.title       &lt;&lt; val &quot;What is Love?&quot;
         # F.articleType &lt;&lt; val Editorial)</code></pre>
<p>And we can also use the enum for restriction as well as
retrieval:</p>
<pre><code>restrictOnArticleType conn = query conn $ do
  content &lt;- table T.content
  restrict $ content!F.articleType .==. val Editorial
  return content

λ&gt; fmap (take 1) $ withDB opts $ \db -&gt; restrictOnArticleType db
[[(&quot;id&quot;,&quot;82&quot;)
,(&quot;title&quot;,&quot;\&quot;Welcome message from the Editor-in-Chief\&quot;&quot;)
,(&quot;type&quot;,&quot;Editorial&quot;)]]</code></pre>
<h2 id="stability">Stability</h2>
<p>The problem with HaskellDB is that the implementation can be
unstable. I found that I had to patch the PostgreSQL library to handle
simple stupid things like fields named “user” or “order”, by making sure
to quote all fields.</p>
<p>I also had to open up some of the internal parts of the API so that I
could extend it further, such as for the operator <code>(.@@.)</code>
defined above. I’ll push these fixes and extensions to fork repos at
some point.</p>
<h2 id="reading-error-messages">Reading error messages</h2>
<p>HaskellDB gets a lot of stick for hard to read error messages. This
is true when you get things badly wrong.</p>
<p>In the general case the errors are quite straight forward.</p>
<p>For example, if I try to use a field which doesn’t exist in the
table, like this:</p>
<pre><code>simpleRestriction = do
  content &lt;- table T.content
  restrict $ content!F.count .==. val 1
  return content</code></pre>
<p>Then the compile error looks like this:</p>
<pre><code>Error: Demo.hs:39:13: No instance for (HasField F.Count RecNil)
      arising from a use of `!&#39; at Demo.hs:39:13-27
    Possible fix:
      add an instance declaration for (HasField F.Count RecNil)
    In the first argument of `(.==.)&#39;, namely `content ! F.count&#39;
    In the second argument of `($)&#39;, namely
        `content ! F.count .==. val 1&#39;
    In a stmt of a &#39;do&#39; expression:
          restrict $ content ! F.count .==. val 1</code></pre>
<p>Which is a very useful error message. <code>content</code> does not
has field <code>count</code>.</p>
<p>For getting the wrong type, it merely shows “couldn’t match type A
against type B,” straight-forward.</p>
<p>The cases where compile errors blow up are, for example, if I wrote
this:</p>
<pre><code>simpleRestriction = do
  content &lt;- table T.content
  restrict $ content!content .==. val &quot;Coco Jambo&quot;
  return content

then the error is:

Error: Demo.hs:39:13:
  No instance for
    (Select
      (Rel
        (RecCons F.Id (Expr Int)
                (RecCons F.Title (Expr String) RecNil)))
      (Rel
        (RecCons F.Id (Expr Int)
                (RecCons F.Title (Expr String) RecNil)))
      (Expr [Char]))
      arising from a use of `!&#39;
                   at Demo.hs:39:13-27
    Possible fix:
      add an instance declaration for […]
    In the first argument of `(.==.)&#39;, namely `content ! content&#39;
    In the second argument of `($)&#39;, namely
        `content ! content .==. val &quot;Coco Jambo&quot;&#39;
    In a stmt of a &#39;do&#39; expression:
          restrict $ content ! content .==. val &quot;Coco Jambo&quot;</code></pre>
<p>The error actually makes sense if you understand the API well enough,
but otherwise it can be very confusing and worrying. Don’t worry about
it, you didn’t break something complicated, you just made a typo
somewhere. It shows the offending expression; you realised you tried to
use a table as a field, and you correct.</p>
<h2 id="files">Files</h2>
<p>The complete files for this demo including patched libraries are <a
href="https://github.com/chrisdone/haskelldb-demo">here in Github
flavour.</a></p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Afterwards it would seem like a good
idea to get a proper comprehensive tutorial on the HaskellWiki, or much
better yet, embed a tutorial in the Haddock documentation for HaskellDB.
At the moment the haddock docs are literally just an API listing, with
no elaborative explanation or examples. Writing in Haddock mark-up is
quite a painful, boring experience. Regardless, I believe the haddock
docs of a project should (most of the time) be sufficient to explain its
use, linking to external papers and blog posts and whatnot is annoyingly
terse and quickly becomes out of date.<a href="#fnref1"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p>Embedded domain-specific language. A
common notion in Haskell and Lisp languages, though implemented
differently in each.<a href="#fnref2" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn3" role="doc-endnote"><p>See <a
href="http://hackage.haskell.org/package/haskelldb">package description
for HaskellDB</a>.<a href="#fnref3" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn4" role="doc-endnote"><p>See the <a
href="http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.136.3828&amp;rep=rep1&amp;type=pdf">“HaskellDB
Improved” paper.</a><a href="#fnref4" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn5" role="doc-endnote"><p>This is the convention I have chosen
to use. It makes good sense and can be very helpful for all fields used
in the project to be defined on a per-project basis, rather than
per-entity, and of the same type.<a href="#fnref5" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn6" role="doc-endnote"><p>A macro that you can get from <a
href="http://hpaste.org/53595">Database.HaskellDB.TH</a>, which I have
yet to put into a library or get added to HaskellDB mainline. I don’t
care to debate API decisions with the HaskellDB maintainers right now.<a
href="#fnref6" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn7" role="doc-endnote"><p>A macro that you can get from <a
href="http://hpaste.org/53595">Database.HaskellDB.TH</a>, which I have
yet to put into a library or get added to HaskellDB mainline. I don’t
care to debate API decisions with the HaskellDB maintainers right now.<a
href="#fnref7" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn8" role="doc-endnote"><p>When table names conflict with field
names—and eventually it happens—this is useful to have. Alternatively
<code>as F</code> also makes sense, to be consistent.<a href="#fnref8"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn9" role="doc-endnote"><p>I have defined a few extra functions
for HaskellDB in <a
href="http://hpaste.org/53599">Database.HaskellDB.Extra</a>.<a
href="#fnref9" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn10" role="doc-endnote"><p><a
href="http://pseudofish.com/blog/2008/05/18/haskelldb-performance/">Geoff
Wilson on HaskellDB performance.</a><a href="#fnref10"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn11" role="doc-endnote"><p><a
href="http://www.postgresql.org/docs/8.3/static/ddl-constraints.html">PostgreSQL
manual on constraints.</a><a href="#fnref11" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn12" role="doc-endnote"><p><a
href="http://hpaste.org/53619">Another simple module</a> and <a
href="http://hpaste.org/53607">another</a> that would be cool to put in
a package, but for now remains in my utility box.<a href="#fnref12"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2011-11-06 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sun, 06 Nov 2011 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Common Lisp/Haskell syntactic comparison]]></title><link>https://chrisdone.com/posts/common-lisp-haskell</link><guid>https://chrisdone.com/posts/common-lisp-haskell</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Common Lisp/Haskell syntactic comparison</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Common Lisp/Haskell syntactic comparison</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>This is a little reminder/documentation for myself to explain that,
despite having nice regular s-expression syntax, Common Lisp actually
has a lot of syntactic concepts. I add comparison to Haskell because
Haskell is known (perhaps superfically) for having a lot of syntax
compared to other languages.</p>
<pre><code>CL: ; comment here
HS: -- comment here

CL: (defun x () …)
HS: x = …

CL: (COND (((= x 1) r1) ((= x 2) r2)) (t r3))
HS: case x of 1 -&gt; r1; 2 -&gt; r2; _ -&gt; r3

CL: &#39;quotation
HS: &#39;value
    &#39;&#39;type

CL: &#39;(quotation)
    `(quasiquotation)
HS: [|quotation|]

CL: `(quasiquotation with ,splice)
HS: [| quotation with $(splice) |]

CL: `(list splice with ,@splice)
HS: [| list splice with $(splice) |]

CL: #(reader macros)
    #(… …) ; vector
    #p&quot; … &quot; ; path
HS: [| reader macros |]
    [v| … … |]
    [p| … |]

CL: :keyword arguments
CL: #: no idea what this is called

CL: (multiple-value-bind (x y) some-values (print x))
HS: (let (x,y) = someValues in print x)

CL: (list 1 2 3)
   &#39;(1 2 3)
HS: [1,2,3]

CL: (cons 1 (cons 2 (cons 3 nil)))
    (cons 1 (cons 2 (cons 3 &#39;())))
HS: 1 : 2 : 3 : []

CL: (funcall foo &#39;(arg1 arg2))
HS: foo arg1 arg2

CL: #&#39;function
HS: function

CL: (let ((f 1)) …)
    (let*((g 0) (f g)) …)
    (flet((g (n) (cons n …)) (f () (g 1))) …)
HS: let f = g 1; g n = n : g (n+1) in f

CL: *global*

CL: (lambda (a b) …)
HS: \a b -&gt; …

CL: (tagbody (go …))

CL: (defun x (f &amp;optional args) &quot;Docs here.&quot; …)

CL: (declare (single-float x) (optimize (safety 3)))
HS: x :: Float

CL: (do () (…) (…))

CL: (values a b c)
HS: (a,b,c)

CL: (loop … ? ¿ ‽)

CL: #\space
    #\
HS: &#39; &#39;

CL: (+) =&gt; 0
HS: (+) =&gt; (+)

CL: (+ 1) =&gt; 1
HS: (+ 1) =&gt; (+ 1)

CL: (+ 1 2) =&gt; 3
HS: (1 + 2) =&gt; 3

CL: (sort (list &#39;(9 A) &#39;(3 B) &#39;(4 C)) #&#39;&lt; :key #&#39;first)
HS: sortBy (comparing fst) [(9,&#39;A&#39;),(3,&#39;B&#39;),(4,&#39;C&#39;)]

CL:  #1=(programmable . #1#) programming language
HS: fix (\x -&gt; &quot;programmable &quot; ++ x) ++ &quot; programming language&quot;

CL: (defclass x (a b) ())
HS: class X a b

CL: (if foo-bar then-x else-y)
HS: if fooBar then x else y

HS: False, Nothing, []
CL: nil</code></pre>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2011-10-31 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Mon, 31 Oct 2011 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Deprecate Prelude.head and partial functions]]></title><link>https://chrisdone.com/posts/boycott-head</link><guid>https://chrisdone.com/posts/boycott-head</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Deprecate Prelude.head and partial functions</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Deprecate Prelude.head and partial functions</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Please boycott <a
href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:head">Prelude.head</a>
and all its partial friends.</p>
<p>I’m sick of seeing <a
href="http://www.google.com/search?sourceid=chrome&amp;ie=UTF-8&amp;q=%22Prelude.head%3A+empty+list%22">this
exception</a>:</p>
<pre><code>Prelude.head: empty list</code></pre>
<p>That’s 6,610 results for this ridiculous exception. Alternatives
are:</p>
<pre><code>listToMaybe :: [a] -&gt; Maybe a
take :: Int -&gt; [a] -&gt; [a]
foldr :: (a -&gt; b -&gt; b) -&gt; b -&gt; [a] -&gt; b
data List a = Single a | Cons a (List a)
data NonEmpty a = NonEmpty a [a]
list :: (a -&gt; [a] -&gt; b) -&gt; b -&gt; [a] -&gt; b
Plain old pattern matching.</code></pre>
<p>And if your code really does not make sense to have an empty list
(then why are you using a list data type?) and you cannot be swayed
against using a list type, please at least do this:</p>
<pre><code>throw MeaningfulException
   `fromMaybe` (listToMaybe xs)</code></pre>
<p>Please stop using partial functions. Seriously. Remove them from your
codebase.</p>
<h2 id="expanding-with-examples">Expanding with examples</h2>
<p>Someone commented:</p>
<blockquote>
<p>What if my data type is a list and I know that head will not throw an
exception?</p>
<pre><code>foo [] = 0
foo xs = bar $ head xs</code></pre>
</blockquote>
<p>The problem is that this is an invariant that only exists in the
programmer’s head (sorry) and is not encoded in the type system (such is
the problem with all partial functions), when it so easily can be. Some
examples:</p>
<p>Sometime last year I found a Haddock bug:</p>
<pre><code>haddock: internal Haddock or GHC error: Prelude.head: empty list</code></pre>
<p>The cause is line 191:</p>
<pre><code>packageMod       = ifaceMod (head ifaces)</code></pre>
<p>in the <code>render</code> function, because the author assumed that
the “not-null” invariant would never be broken. But then he used the
renderStep function again, and line 158, in the <code>main</code>
function:</p>
<pre><code>renderStep flags packages []</code></pre>
<p>Breaking this invariant.</p>
<p>Around this time I also found a bug in Hakyll due to use of tail:</p>
<pre><code>./src/Text/Hakyll/Internal/CompressCss.hs:
| otherwise = head str : stripComments (tail str)</code></pre>
<p>which triggered <a href="http://hpaste.org/40264/hakyll_error">this
exception</a>.</p>
<p>So, despite the invariant being satisfied at the time of writing,
later that tacit invariant was broken and the developer didn’t realise
it. This is more or less the most common case of partial function
exceptions. You <em>just know</em> X will never happen, and then it
does.</p>
<p>It’s trivial to abstract away partiality. In some cases handling
cases might be a speed concern, but that should be a case-by-case
localized optimization based on profiling.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2011-10-17 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Mon, 17 Oct 2011 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[“Value polymorphism”, simple explanation with examples]]></title><link>https://chrisdone.com/posts/value-polymorphism</link><guid>https://chrisdone.com/posts/value-polymorphism</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>“Value polymorphism”, simple explanation with
examples</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>“Value polymorphism”, simple explanation with examples</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>A concept in Haskell which is particularly novel is that polymorphism
works at the value level rather than function-parameter or
object-dereference level.</p>
<p>Function-parameter polymorphism comes in some different forms, for
example, C++:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> draw<span class="op">(</span>Circle c<span class="op">){</span> … <span class="op">}</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> draw<span class="op">(</span>Triangle t<span class="op">){</span> … <span class="op">}</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>draw<span class="op">(</span>circle<span class="op">);</span> <span class="co">// draws a circle</span></span></code></pre></div>
<p>Function overloading is a type of function-parameter polymorphism.
Generic functions in Common Lisp are another way to have
function-parameter polymorphism:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode commonlisp"><code class="sourceCode commonlisp"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>(<span class="kw">defgeneric</span><span class="fu"> draw </span>(shape))</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>(<span class="kw">defmethod</span><span class="fu"> draw </span>((shape circle)) …)</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>(<span class="kw">defmethod</span><span class="fu"> draw </span>((shape triangle)) …)</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>(draw circle) <span class="co">;; draws a circle</span></span></code></pre></div>
<p>Object-dereference (or message passing) polymorphism is common to
most object oriented languages. Depending on the object, the
function/message will do something different:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Circle <span class="op">{</span> <span class="dt">void</span> draw<span class="op">(){</span> … <span class="op">}</span> <span class="op">}</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Triangle <span class="op">{</span> <span class="dt">void</span> draw<span class="op">(){</span> … <span class="op">}</span> <span class="op">}</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>circle<span class="op">.</span>draw<span class="op">();</span> <span class="co">// draws a circle</span></span></code></pre></div>
<p>To avoid confusion, Haskell also has function parameter polymorphism,
like C++ and Common Lisp above:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> <span class="dt">Drawable</span> a <span class="kw">where</span><span class="ot"> draw ::</span> a <span class="ot">-&gt;</span> <span class="dt">Bitmap</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Drawable</span> <span class="dt">Circle</span> <span class="kw">where</span> draw <span class="ot">=</span> …</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Drawable</span> <span class="dt">Triangle</span> <span class="kw">where</span> draw <span class="ot">=</span> …</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>draw circle <span class="co">-- draws a circle</span></span></code></pre></div>
<p>But more generally, Haskell has <em>value</em> polymorphism, which is
that any value can be polymorphic and will be instantiated to a class
instance depending on type signature or annotation:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> <span class="dt">Default</span> a <span class="kw">where</span><span class="ot"> def ::</span> a</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Default</span> <span class="dt">Int</span> <span class="kw">where</span> def <span class="ot">=</span> <span class="dv">0</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Default</span> <span class="dt">Char</span> <span class="kw">where</span> def <span class="ot">=</span> <span class="ch">&#39;a&#39;</span></span></code></pre></div>
<p>The type of an expression <code>def</code> therefore is
<code>Default a =&gt; a</code>, or, “any instance of
<code>Default</code>”. I can instantiate an instance myself by
specifying a type signature:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span><span class="ot"> def ::</span> <span class="dt">Int</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>→ <span class="dv">0</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span><span class="ot"> def ::</span> <span class="dt">Char</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>→ <span class="ch">&#39;a&#39;</span></span></code></pre></div>
<p>Or by type inference, meaning that the combination of this expression
with other expressions allows the compiler to infer the single correct
type instance:</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> def <span class="op">:</span> <span class="st">&quot;bc&quot;</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>→ <span class="st">&quot;abc&quot;</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> def <span class="op">-</span> <span class="dv">2</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>→ <span class="op">-</span><span class="dv">2</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> def <span class="op">==</span> <span class="dv">0</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>→ <span class="dt">True</span></span></code></pre></div>
<p>But with no information it will be a static compile error:</p>
<pre><code>λ&gt; def
Ambiguous type variable `a&#39; in the constraint:
  `Default a&#39; arising from a use of `def&#39; at
    &lt;interactive&gt;:1:0-2
Probable fix: add a type signature that fixes these type
              variable(s)</code></pre>
<p>Why is value polymorphism beneficial? Some trivial examples follow
(and you are trusted to extrapolate to the more sophisticated things
that might otherwise obscure the essence of this feature).</p>
<p>The <code>Read</code> class contains a method <code>read</code> which
is polymorphic on the return value:</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> <span class="dt">Read</span> a <span class="kw">where</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="ot">  read ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> a</span></code></pre></div>
<p>It parses a data type from a string. Combined with the
<code>Show</code> class, together <code>Read</code> and
<code>Show</code> make a naive serialization library. In the same way,
it would be ambiguous to read without specifying the instance:</p>
<pre><code>λ&gt; read &quot;2&quot;
Ambiguous type variable `a&#39; in the constraint:
  `Read a&#39; arising from a use of `read&#39; at
    &lt;interactive&gt;:1:0-7
Probable fix: add a type signature that fixes these type
              variable(s)</code></pre>
<p>But specifying with a type signature or using type inference are
fine:</p>
<div class="sourceCode" id="cb11"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="fu">read</span> <span class="st">&quot;2&quot;</span><span class="ot"> ::</span> <span class="dt">Int</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>→ <span class="dv">2</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="fu">read</span> <span class="st">&quot;2&quot;</span> <span class="op">*</span> <span class="dv">3</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>→ <span class="dv">6</span></span></code></pre></div>
<p>Another example is JSON parsing (the real class is different to this,
but introduces questions that are irrelevant to the point of this
post).</p>
<div class="sourceCode" id="cb12"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> <span class="dt">JSON</span> a <span class="kw">where</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="ot">  decode ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Result</span> a</span></code></pre></div>
<p>The <code>decode</code> function is return-value polymorphic, it can
be read like this:</p>
<div class="sourceCode" id="cb13"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="ot">decode ::</span> (<span class="dt">JSON</span> a) <span class="ot">=&gt;</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Result</span> a</span></code></pre></div>
<p>That is, it returns a result (success or fail) with a value which is
an instance of the JSON class.</p>
<p>So both specifying an instance or using inference works:</p>
<div class="sourceCode" id="cb14"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> decode <span class="st">&quot;1&quot;</span><span class="ot"> ::</span> <span class="dt">Result</span> <span class="dt">Int</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>→ <span class="dt">Ok</span> <span class="dv">1</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> <span class="kw">do</span> x <span class="ot">&lt;-</span> decode <span class="st">&quot;1&quot;</span>; <span class="fu">return</span> (x<span class="op">*</span><span class="dv">3</span>)</span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>→ <span class="dt">Ok</span> <span class="dv">3</span></span></code></pre></div>
<p>And it works however complex you want to go with your types:</p>
<div class="sourceCode" id="cb15"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> decode <span class="st">&quot;[[1,\&quot;a\&quot;,{\&quot;x\&quot;:3}],[1,\&quot;a\&quot;,{\&quot;x\&quot;:2}]]&quot;</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a><span class="ot">   ::</span> <span class="dt">Result</span> [(<span class="dt">Int</span>,<span class="dt">String</span>,<span class="dt">JSObject</span> <span class="dt">Int</span>)]</span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>→ <span class="dt">Ok</span> [(<span class="dv">1</span>,<span class="st">&quot;a&quot;</span>,<span class="dt">JSONObject</span> {fromJSObject <span class="ot">=</span> [(<span class="st">&quot;x&quot;</span>,<span class="dv">3</span>)]})</span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>     ,(<span class="dv">1</span>,<span class="st">&quot;a&quot;</span>,<span class="dt">JSONObject</span> {fromJSObject <span class="ot">=</span> [(<span class="st">&quot;x&quot;</span>,<span class="dv">2</span>)]})]</span></code></pre></div>
<p>Thus by merely specifying the return type we have effectively
generated a parser. An invalid string will produce an error:</p>
<div class="sourceCode" id="cb16"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a>λ<span class="op">&gt;</span> decode <span class="st">&quot;[[1,\&quot;a\&quot;,{\&quot;x\&quot;:3}],[1,\&quot;a\&quot;]]&quot;</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a><span class="ot">  ::</span> <span class="dt">Result</span> [(<span class="dt">Int</span>,<span class="dt">String</span>,<span class="dt">JSObject</span> <span class="dt">Int</span>)]</span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>→ <span class="dt">Error</span> <span class="st">&quot;Unable to read Triple&quot;</span></span></code></pre></div>
<p>In fact, the literal <code>1</code> is also polymorphic with type
<code>Num a =&gt; a</code>, meaning that the number could be an
<code>Integer</code>, a <code>Double</code>, a <code>Rational</code>, or
a user-defined type like <code>Scientific</code>. It will be determined
by inference or annotation.</p>
<p>Such static value polymorphism is difficult to do in popular
languages such as C#, Java, C++, without some kind of proxy objects to
explicitly instantiate an object to dereference using generics or
templates, and hard to do in Lisp, Python, Ruby and JavaScript without
static type systems (although can also be approximated with proxy aka
“witness” objects). This is, for example, why implementing the Monad
class is rather awkward in other languages.</p>
<p>The list goes on. More examples include database query results,
string literals, monoids, monads, …</p>
<p>Lastly, the <code>Default</code> class is a real class and in common
use today.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2011-10-16 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sun, 16 Oct 2011 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Rank-N types, a simple DB example]]></title><link>https://chrisdone.com/posts/rankntypes</link><guid>https://chrisdone.com/posts/rankntypes</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Rank-N types, a simple DB example</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Rank-N types, a simple DB example</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>This is a very simple example of rank-N types to demonstrate to
non-Haskellers/newbies.</p>
<p>Following the resources theme, rank-N types as seen in <a
href="http://www.haskell.org/haskellwiki/Monad/ST">the ST monad</a> are
also a gem:</p>
<pre><code>{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE RankNTypes #-}</code></pre>
<p>Define a monad for interacting with the DB parametrized on a
connection type variable, <code>c</code>, as well as the return
type:</p>
<pre><code>newtype DB c a = DB (IO a) deriving (Monad)</code></pre>
<p>And a connection data type parametrized on the connection type
variable:</p>
<pre><code>newtype Connection c = Connection ()</code></pre>
<p>Define the connection opening function such that the quantified type
variable <code>c</code> cannot escape from the DB monad:</p>
<pre><code>withConnection :: (forall c. DB c a) -&gt; IO a
withConnection m = case m of DB io -&gt; io</code></pre>
<p>Let’s say in a real implementation <code>withConnection</code> opens
a database connection in a transaction and commits and closes when done,
among other exception catching things.</p>
<p>Define some functions for the DB monad (note they all reference the
<code>c</code> type variable):</p>
<pre><code>getConn :: DB c (Connection c)
getConn = return (Connection ())

query :: Connection c -&gt; String -&gt; DB c [String]
query _ _ = return [&quot;Hello!&quot;]</code></pre>
<p>Now we can use it like this:</p>
<pre><code>demo1 = withConnection $ do
  conn &lt;- getConn
  rows &lt;- query conn &quot;SELECT …&quot;
  return rows

λ&gt; demo1
[&quot;Hello!&quot;]</code></pre>
<p>But if you try to return the connection…</p>
<pre><code> demo2 = withConnection $ do
   conn &lt;- getConn
   rows &lt;- query conn &quot;SELECT …&quot;
   return conn</code></pre>
<p>You get a compile error:</p>
<pre><code>Error:  Inferred type is less polymorphic than expected
      Quantified type variable `c&#39; escapes</code></pre>
<p>This is pretty nice if your DB library implementation, e.g., is
supposed to ensure operations on a connection run inside a transaction,
or if your operations assume a connection exists. Otherwise you’re
liable to having DB code run outside of a transaction, or code throwing
exceptions because the connection was closed but we tried to use it
anyway, or in severe cases, some C DB libraries will just segfault.</p>
<p>We didn’t have to do anything complex or write any boilerplate or
macros or whatnot, just use the type system. That’s what it’s for.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2011-10-16 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sun, 16 Oct 2011 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Experimenting with GHCJS, the Haskell→JavaScript compiler]]></title><link>https://chrisdone.com/posts/ghcjs</link><guid>https://chrisdone.com/posts/ghcjs</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Experimenting with GHCJS, the Haskell→JavaScript
compiler</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Experimenting with GHCJS, the Haskell→JavaScript compiler</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<!-- Part 1: Explain what's wrong with JavaScript -->
<p>JavaScript <em>per se</em> is insufficient. The depths to which
JavaScript fails is well-documented and well-understood. Its main faults
are its verbose function syntax<a href="#fn1" class="footnote-ref"
id="fnref1" role="doc-noteref"><sup>1</sup></a>, late binding<a
href="#fn2" class="footnote-ref" id="fnref2"
role="doc-noteref"><sup>2</sup></a>, which has led to the creation of
various static analysis tools to alleviate this language flaw<a
href="#fn3" class="footnote-ref" id="fnref3"
role="doc-noteref"><sup>3</sup></a>, but with limited success<a
href="#fn4" class="footnote-ref" id="fnref4"
role="doc-noteref"><sup>4</sup></a> (there is even a static type
checker<a href="#fn5" class="footnote-ref" id="fnref5"
role="doc-noteref"><sup>5</sup></a>), <a
href="http://stackoverflow.com/questions/5447153/javascript-equality-transitivity-is-weird/5447170#5447170">finicky
equality</a>, <code>this</code> behaviour, and lack of static types and
modules<a href="#fn6" class="footnote-ref" id="fnref6"
role="doc-noteref"><sup>6</sup></a>.</p>
<!-- Part 2: Explain the ways in which we fix JavaScript -->
<p>Using JavaScript for what it is good for<a href="#fn7"
class="footnote-ref" id="fnref7" role="doc-noteref"><sup>7</sup></a>,
but not using the language <em>per se</em>, is therefore desirable, and
many are working to achieve this<a href="#fn8" class="footnote-ref"
id="fnref8" role="doc-noteref"><sup>8</sup></a>, in some form or
another. There various ways to do it<a href="#fn9" class="footnote-ref"
id="fnref9" role="doc-noteref"><sup>9</sup></a>, but I will opt for
compiling an existing language, Haskell, to JavaScript, because I do not
have time to learn or teach other people a new language, garner a new
library set and a new type checker and all that Haskell implementations
provide.</p>
<!-- Part 3: Explain compiler choice -->
<p>Given the option, I’d choose <a
href="http://www.haskell.org/ghc/">GHC</a> because it is the flagship
Haskell compiler, with <a
href="http://www.haskell.org/ghc/docs/latest/html/users_guide/ghc-language-features.html">the
most features</a>, which most Haskellers write all their projects with.
Haskell has a standard, <a
href="http://www.haskell.org/pipermail/haskell/2009-November/021750.html">presently
Haskell 2010</a>, but I think that most projects out there use quite a
few language extensions<a href="#fn10" class="footnote-ref" id="fnref10"
role="doc-noteref"><sup>10</sup></a> outside of the standard; Haskellers
target GHC. This is not to say that for compiling to JS, Haskell 98
wouldn’t be a vast improvement.</p>
<!-- Part 4: Introduce GHCJS -->
<p>Fortunately there is a project maintained by <a
href="http://asviraspossible.livejournal.com/">Victor Nazarov</a> called
<a href="https://github.com/sviperll/ghcjs">GHCJS</a>. You can use GHC
6.12.3 or GHC 7+. For my experimentation I am using 6.12.3. I followed
<a
href="https://github.com/sviperll/ghcjs/blob/master/README.markdown">the
instructions given</a>, with a fix for the build process<a href="#fn11"
class="footnote-ref" id="fnref11" role="doc-noteref"><sup>11</sup></a>,
and some tweaks to the libraries<a href="#fn12" class="footnote-ref"
id="fnref12" role="doc-noteref"><sup>12</sup></a>. In order to build the
libraries and copy them to the <code>examples/</code> directory, I wrote
a little script<a href="#fn13" class="footnote-ref" id="fnref13"
role="doc-noteref"><sup>13</sup></a>, which helps automate this. There
is also <code>BuildTest.hs</code> in the <code>examples/</code> dir
which gentle reader should try first.</p>
<!-- Part 5: First GHCJS example -->
<p>After much twiddling and fudging with the example file and the
provided FFI, some help from Victor Nazarov, with some trial and error,
I managed to get some fundamental things working that are necessary to
be able to write effectively in the JavaScript environment<a
href="#fn14" class="footnote-ref" id="fnref14"
role="doc-noteref"><sup>14</sup></a>. Timers work (and AJAX requests
will), but <a href="http://hpaste.org/50477#line128">this example</a> is
merely a clickable blank page which alerts “’Ello, World!”.
Uninteresting functionally, but a good test of the fundamentals (see the
pasted Haskell source).</p>
<!-- Part 6: Where next -->
<p>Next up, I will write a simple pong game<a href="#fn15"
class="footnote-ref" id="fnref15" role="doc-noteref"><sup>15</sup></a>
to test integration with the canvas element and speed of the runtime and
establish some sort of base library and project template from which
other Haskellers can more easily experiment. Perhaps we could even have
in the future a browser-based IDE and compiler which can of course run
the compiled code in the user’s browser. That would be nice.</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Its support for closures is commonly
noted as being one of JavaScript’s redeeming features.<a href="#fnref1"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p>Early binding allows for static
verification of the existence of method-signature pairs (e.g. v-tables).
Late binding does not give the compiler (or an IDE) enough information
for existence verification, it has to be looked up at run-time.<a
href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn3" role="doc-endnote"><p>There are several hinting libraries,
which developers insist are indispensable tools when developing
JavaScript seriously, such as <a
href="http://www.javascriptlint.com/">JavaScript lint</a>, <a
href="http://www.jslint.com/">JSLint</a>, and <a
href="http://aurochs.fr/jsure.html">JSure</a>.<a href="#fnref3"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn4" role="doc-endnote"><p>“Any non-trivial analysis is very
difficult due to Javascript’s dynamic nature.” — Berke Durak, Ph.D.,
author of jsure.<a href="#fnref4" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn5" role="doc-endnote"><p>Google Inc. thought it necessary to
develop <a href="http://code.google.com/closure/compiler/">a compiler
which does type-checking and limited inference</a>, e.g.</p>
<pre><code>/**
 * Queries a Baz for items.
 * @param {number} groupNum Subgroup id to query.
 * @param {string|number|null} term An itemName,
 *     or itemId, or null to search everything.
 */
goog.Baz.prototype.query = function(groupNum, term) {
  ...
};</code></pre>
<p>This will ensure that invocations to <code>Bad.query()</code> will be
well-typed. See the <a
href="http://code.google.com/closure/compiler/docs/js-for-compiler.html">Google
closure docs</a> for more examples. Developers I’ve spoken to at Google
say this makes JS bearable with sufficient self-discipline, but without
it, maintaining a large codebase in JS is unrealistic.<a href="#fnref5"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn6" role="doc-endnote"><p>A <a
href="http://www.google.com/search?aq=f&amp;sourceid=chrome&amp;ie=UTF-8&amp;q=javascript+module+system">quick
Google search</a> demonstrates easily enough that there is a need for a
module system.<a href="#fnref6" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn7" role="doc-endnote"><p>It is established that JavaScript is
now a target platform due to its browser ubiquity. If we want to write
tools, applications, games, etc. that will reach a wide audience with
little effort on the user’s part, targetting the browser and therefore
JavaScript is an excellent option.<a href="#fnref7"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn8" role="doc-endnote"><p>There are already many projects
underway for doing this, such as <a href="http://pyjs.org/">Pyjamas</a>,
<a href="http://hotruby.yukoba.jp/">HotRuby</a>, <a
href="http://ejohn.org/blog/running-java-in-javascript/">Orto</a>, <a
href="http://www.zkoss.org/">ZK</a>, and <a
href="https://github.com/jashkenas/coffee-script/wiki/List-of-languages-that-compile-to-JS">many
which merely provide a layer ontop of JavaScript</a> to make using it
marginally less painful. Some Haskell ones include <a
href="http://utrechthaskellcompiler.wordpress.com/2010/10/18/haskell-to-javascript-backend/">UHC</a>,
<a href="http://www.haskell.org/haskellwiki/Yhc/Javascript">YHC</a>, <a
href="http://code.google.com/p/jshaskell/">jshaskell</a> and <a
href="https://github.com/valderman/lambdascript">lambdascript</a>.<a
href="#fnref8" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn9" role="doc-endnote"><p>Some ways that I see are:</p>
<ul>
<li>Write JavaScript with a functional/OO/“better” standard library, a
la <a href="https://github.com/runarorama/LambdaScript">LambdaScript</a>
or <a href="http://www.commonjs.org/">CommonJS</a>.</li>
<li>Write JavaScript with additional tools to provide static semantics
(a la Google Closure).</li>
<li>Write JavaScript in an EDSL in another more powerful language,
e.g. <a
href="http://common-lisp.net/project/parenscript/">ParenScript</a> and
<a href="http://hackage.haskell.org/package/HJScript">HJScript</a>.</li>
<li>Create a new language that mostly preserves JavaScript semantics but
adds some additional layer, e.g. <a
href="http://jashkenas.github.com/coffee-script/">CoffeeScript</a>.</li>
<li>Interpret an existing language in JavaScript.</li>
<li>Compile an existing language to JavaScript.</li>
</ul>
<p>I prefer the last option.<a href="#fnref9" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn10" role="doc-endnote"><p>To put it in perspective, here are
the extensions available in GHC as of 6.12.3: OverlappingInstances
NoOverlappingInstances, IncoherentInstances, NoIncoherentInstances
UndecidableInstances, NoUndecidableInstances, Arrows, NoArrows
DisambiguateRecordFields, NoDisambiguateRecordFields
ForeignFunctionInterface, NoForeignFunctionInterface, Generics
NoGenerics, ImplicitParams, NoImplicitParams, NoImplicitPrelude
ImplicitPrelude, NoMonomorphismRestriction, MonomorphismRrestriction
NoNPlusKPatterns, NPlusKPatterns, NoMonoPatBinds, MonoPatBinds
RelaxedPolyRec, NoRelaxedPolyRec, ExtendedDefaultRules
NoExtendedDefaultRules, OverloadedStrings, NoOverloadedStrings, GADTs
NoGADTs, TypeFamilies, NoTypeFamilies, ScopedTypeVariables
NoScopedTypeVariables, MonoLocalBinds, NoMonoLocalBinds, TemplateHaskell
NoTemplateHaskell, QuasiQuotes, NoQuasiQuotes, BangPatterns
NoBangPatterns, CPP, NoCPP, PatternGuards, NoPatternGuards, ViewPatterns
NoViewPatterns, UnicodeSyntax, NoUnicodeSyntax, MagicHash, NoMagicHash
NewQualifiedOperators, NoNewQualifiedOperators, ExplicitForALl
NoExplicitForAll, PolymorphicComponents, NoPolymorphicComponents
Rank2Types, NoRank2Types, RankNTypes, NoRankNTypes, ImpredicativeTypes
NoImpredicativeTypes, ExistentialQuantification
NoExistentialQuantification, KindSignatures, NoKindSignatures
EmptyDataDecls, NoEmptyDataDecls, ParallelListComp, NoParallelListComp
TransformListComp, NoTransformListComp, UnliftedFFITypes
NoUnliftedFFITypes, LiberalTypeSynonyms, NoLiberalTypeSynonyms
TypeOperators, NoTypeOperators, DoRec, NoDoRec, RecursiveDo,
NoRecursiveDo PArr, NoPArr, RecordWildCards, NoRecordWildCards,
NamedFieldPuns NoNamedFieldPuns, DisambiguateRecordFields,
NoDisambiguateRecordFields UnboxedTuples, NoUnboxedTuples,
StandaloneDeriving, NoStandaloneDeriving DeriveDataTypeable,
NoDeriveDataTypeable, GeneralizedNewtypeDeriving
NoGeneralizedNewtypeDeriving, TypeSynonymInstances
NoTypeSynonymInstances, FlexibleContexts, NoFlexibleContexts
FlexibleInstances, NoFlexibleInstances, ConstrainedClassMethods
NoConstrainedClassMethods, MultiParamTypeClasses
NoMultiParamTypeClasses, FunctionalDependencies
NoFunctionalDependencies, PackageImports, and NoPackageImports.<a
href="#fnref10" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn11" role="doc-endnote"><p>On Ubuntu, I had to explicitly add
-pthread to the build configuration of libraries/unix, otherwise it
didn’t figure it out automatically.<a href="#fnref11"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn12" role="doc-endnote"><p>There were maybe 5 <code>foo#</code>
shaped functions that were out of scope throughout the base libraries,
particularly in GHC. I simply replaced these with
<code>undefined</code>, or because that’s not available,
<code>let    a = a in a</code>, or whatever bottom value to stop it
complaining. I don’t know whether GHC will detect
<code>let a = a in a</code>, I think it does. So the runtime will just
throw an exception on these values.</p>
<pre><code>   chris@cn-done:~$ cat &gt; loop.hs
   main = putStrLn $ let r = r in r
   chris@cn-done:~$ ghc --make loop.hs -O2
   [1 of 1] Compiling Main             ( loop.hs, loop.o )
   Linking loop ...
   chris@cn-done:~$ ./loop
   loop: &lt;&lt;loop&gt;&gt;</code></pre>
<p>Looks OK.<a href="#fnref12" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn13" role="doc-endnote"><p>I called it
<code>ghcjs_buildlibs</code>, and run it from the
<code>ghc-6.12.3</code> directory. I think it should work fine for GHC
7, too.</p>
<pre><code> JSDIR=$1

 cd libraries/ghc-prim &amp;&amp;
 echo cding to libraries/ghc-prim &amp;&amp;
 ghcjs -odir $JSDIR/ghc-prim \
       -hidir $JSDIR/ghc-prim \
       -cpp -fglasgow-exts \
       -package-name ghc-prim \
       GHC/Types.hs &amp;&amp;
 ghcjs -odir $JSDIR/ghc-prim \
       -hidir $JSDIR/ghc-prim \
       -cpp -fglasgow-exts \
       -package-name ghc-prim \
       GHC/*  &amp;&amp;
 cd ../.. &amp;&amp;
 echo cding to ../.. &amp;&amp;
 cd libraries/integer-simple &amp;&amp;
 echo cding to libraries/integer-simple &amp;&amp;
 ghcjs -odir $JSDIR/integer-simple \
       -hidir $JSDIR/integer-simple \
       -cpp -fglasgow-exts \
       -package-name integer-simple \
       GHC/Integer.hs &amp;&amp;
 cd ../.. &amp;&amp;
 echo cding to ../.. &amp;&amp;
 cd libraries/base &amp;&amp;
 echo cding to libraries/base &amp;&amp;
 ghcjs -odir $JSDIR/base -hidir $JSDIR/base \
       -hide-package base \
       -package-name base \
       -I./include \
       -i./dist-install/build -XMagicHash \
       -XExistentialQuantification \
       -XRank2Types -XScopedTypeVariables \
       -XUnboxedTuples -XForeignFunctionInterface \
       -XUnliftedFFITypes -XDeriveDataTypeable \
       -XGeneralizedNewtypeDeriving -XFlexibleInstances \
       -XStandaloneDeriving -XPatternGuards \
       -XEmptyDataDecls -XNoImplicitPrelude -XCPP \
       Prelude.hs &amp;&amp;
 echo &quot;Copying lib to main ...&quot; &amp;&amp;
 cp $1/ghc-prim/GHC \
    $1/../main/ -R &amp;&amp;
 cp $1/integer-simple/GHC/ \
    $1/../main/ -R &amp;&amp;
 cp $1/base/* \
    $1/../main/ -R</code></pre>
<a href="#fnref13" class="footnote-back" role="doc-backlink">↩︎</a></li>
<li id="fn14" role="doc-endnote"><p>I.e. a way to use closure callbacks
for e.g. setInterval/setTimeout and AJAX, a way to serialize data
structures like strings and arrays from/to Haskell and JavaScript, and a
way to access the DOM and bind events to it.<a href="#fnref14"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn15" role="doc-endnote"><p>Pong is a good demo. I’ve already
started work on this, but hit some walls when trying to separate the
build into a more generic and less example-y structure. It’s quite easy
to break this system at present.<a href="#fnref15" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2011-08-20 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sat, 20 Aug 2011 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Some insights from The Mythical Man Month starting from Chapter 11]]></title><link>https://chrisdone.com/posts/the-mythical-man-month-insights</link><guid>https://chrisdone.com/posts/the-mythical-man-month-insights</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Some insights from The Mythical Man Month starting from
Chapter 11</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Some insights from The Mythical Man Month starting from Chapter
11</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>I recently read <a
href="http://en.wikipedia.org/wiki/The_Mythical_Man-Month">The Mythical
Man Month</a>, a classic book about software development.</p>
<p>I thought this quote was tres amusant:</p>
<blockquote>
<p>“The Bible of Software Engineering”, because, “everybody quotes it,
some people read it, and a few people go by it.”</p>
</blockquote>
<p>In my reading of the book, around chapter 11, “Plan to Throw One
Away”, I got the idea to annotate and underline sentences and paragraphs
that rang true with my experience or that I thought were insights that I
and everyone should take into account.</p>
<p>Now that I’ve finished it, I thought I’d jot those points, that I
felt the need to underscore, here. Flicking back through the earlier
chapters there are lots of other points I ought to underscore, but
that’s for another time.</p>
<p>I often see or participate in debates about software development that
are better summed up by many clear insights from <em>MMM</em>, so it’s
good for me to jot them down; having a common vocabulary and literature
avoids a bunch of redundant discussion. For example, I saw some rather
odd posts to Reddit’s programming section with laboured gardening and
writing analogies.</p>
<p>I’m not sure what the legality of typing up so much of a book is.
There is a lot more context to each of the points below, so you really
need <a href="http://www.amazon.com/gp/reader/0201835959">the book</a>
anyway to fully grok everything covered. Many points in the book may or
may not have been underscored depending on the availability of a pen at
the time, and I miss out the first ten chapters. Others downright do not
make sense without the context which I don’t feel comfortable in further
quoting verbatim.</p>
<p>At any rate, most of the quotes below have been quoted verbatim
elsewhere.</p>
<h2 id="plan-to-throw-one-away">Plan to Throw One Away</h2>
<h3 id="pilot-plants-and-scaling-up">Pilot Plants and Scaling Up</h3>
<ul>
<li>“Programming system builders have also been exposed to this lesson,
but it seems to have not yet been learned. Project after project designs
a set of algorithms and then plunges into construction of
customer-deliverable software on a schedule that demands delivery of the
first thing built.”</li>
<li>“In most projects, the first system built is barely usable. It may
be too slow, too big, awkward to use, or all three.”</li>
<li>“The discard and redesign may be done in one lump, or it may be done
piece-by-piece. But all large-system experience shows that it will be
done.”</li>
<li>“The management question, therefore, is not <em>whether</em> to
build a pilot system and throw it away. You <em>will</em> do that. The
only question is whether to plan in advance to build a throwaway, or to
promise to deliver the throwaway to customers.”</li>
<li>“Hence <em>plan to throw one away; you will, anyhow.</em>”</li>
</ul>
<h3 id="the-only-constancy-is-change-itself">The Only Constancy is
Change Itself</h3>
<ul>
<li>“But the very existence of a tangible object serves to contain and
quantize user demand for changes.”</li>
<li>“Clearly a threshold has to be established, and it must get higher
and higher as development proceeds, or no product ever appears.”</li>
<li>“The throw-one-away concept is itself just an acceptance of the fact
that as one learns, he changes the design.”</li>
</ul>
<h3 id="plan-the-system-for-change">Plan the System for Change</h3>
<ul>
<li>“Most important is the use of a high-level language and
self-documenting techniques so as to reduce errors induced by changes.
Using compile-time operations to incorporate standard declarations helps
powerfully in making changes.”</li>
<li>“Every product should have numbered versions, and each version must
have its own schedule and a freeze date, after which changes go into the
next version.”</li>
</ul>
<h3 id="plan-the-organization-for-change">Plan the Organization for
Change</h3>
<ul>
<li>“[…] the reluctance to document designs is not due merely to
laziness or time pressure. Instead it comes from the designer’s
reluctance to commit himself to the defense of decisions which he knows
to be tentative.”</li>
<li>“[M]anagers themselves often think of senior people as ‘too
valuable’ to use for actual programming.”</li>
</ul>
<h3 id="two-steps-forward-and-one-step-back">Two Steps Forward and One
Step Back</h3>
<ul>
<li>“The fundamental problem with program maintenance is that fixing a
defect has a substantial (20-50 percent) chance of introducing another.
So the whole process is two steps forward and one step back.”</li>
<li>“If fact it often has system-wide ramifications, usually nonobvious.
[…] the far-reaching effects of the repair will be overlooked.”</li>
<li>“Clearly, methods of designing programs so as to eliminate or at
least illuminate side effects can have an immense payoff in maintenance
costs. So can methods of implementing designs with fewer people, fewer
interfaces, and hence fewer bugs.”</li>
</ul>
<h3 id="one-step-forward-and-one-step-back">One Step Forward and One
Step Back</h3>
<ul>
<li>“Soon or later the fixing ceases to gain any ground. Each forward
step is matched by a backward one. Although in principle usable forever,
the system has worn out as a base for progress.”</li>
<li>“A brand-new, from-the-ground-up redesign is necessary.”</li>
<li>“Systems program building is an entropy-decreasing process, hence
inherently metastable. Program maintenance is an entropy-increasing
process, and even its most skillful execution only delays the subsidence
of the system into unfixable obsolescence.”</li>
</ul>
<h2 id="sharp-tools">Sharp Tools</h2>
<ul>
<li>“A good workman is known by his tools.” (proverb)</li>
</ul>
<h3 id="high-level-language-and-interactive-programming">High-level
Language and Interactive Programming</h3>
<ul>
<li>“I cannot easily conceive of a programming system I would build in
assembly language.”</li>
</ul>
<h2 id="the-other-face">The other face</h2>
<h3 id="self-documenting-programs">Self-Documenting Programs</h3>
<ul>
<li>(An almost meta-quote here considering the context of this post)
“Refer to standard literature to document basic algorithms wherever
possible. This saves space, usually points to a much fuller treatment
than one would provide, and allows the knowledgeable reader to skip it
with confidence that he understands you.”</li>
</ul>
<h2 id="no-silver-bullet">No Silver Bullet</h2>
<h3 id="does-it-have-to-be-hardessential-difficulties">Does It Have to
Be Hard?—Essential difficulties</h3>
<ul>
<li>“First, we must observe that the anomaly is not that software
progress is so slow, but that computer hardware progress is so
fast.”</li>
<li>“No other technology since civilization began has seen six orders of
magnitude price-performance gain in 30 years.”</li>
<li>“Second, to see what rate of progress we can expect in software
technology, let us examine its difficulties. Following Aristotle, I
divide them into <em>essense</em>—the difficulties inherent in the
nature of the software—and <em>accidents</em>—those difficulties that
today attend its production but that are not inherent.”</li>
<li>“I believe the hard part of building software to be the
specification, design and testing of this conceptual construct, not the
labour of representing it and testing the fidelity of the
representation. […] If this is true, building software will always be
hard. There is inherently no silver bullet.”</li>
</ul>
<h3 id="complexity">Complexity</h3>
<ul>
<li>“Software entities are more complex for their size than perhaps any
other human construct, because no two parts are alike (at least above
the statement level). If they are, we make the two similar parts into
one, a subroutine, open or closed. In this respect software systems
differ profoundly from computers, buildings, automobiles, where repeated
elements abound.”</li>
<li>“Digital computers are themselves more complex than most things
people build; they have very large numbers of states. This makes
conceiving, describing, and testing them hard. Software systems have
orders of magnitude more states than computers do.”</li>
</ul>
<p>Below; functional programming springs to mind:</p>
<ul>
<li>“From the complexity comes the difficulty of enumerating, much less
understanding, all the possible states of the program, and from that
comes the unreliability.”</li>
<li>“From complexity of structure comes the difficulty of extending
programs to new functions without creating side effects. From complexity
of structure comes the unvisualized states that constitute security
trapdoors.”</li>
<li>“The physicist labors on, however, in a firm faith that there are
unifying principles to be found […] because God is not capricious or
arbitrary. No such faith comforts the software engineer.”</li>
<li>“[…] not because of necessity but only because they were designed by
different people, rather than God.”</li>
<li>“Partly this is because the software in a system embodies its
function, and the function is the part that most feels the pressures of
change. Partly it is because software can be changed more easily—it is
pure thought-stuff, infinitely malleable.”</li>
<li>“All successful software gets changed. Two processes are at work. As
a software product is found to be useful, people try it in new cases at
the edge of, or beyond, the original domain. The pressures for extended
function come chiefly from users who like the basic function and invent
new uses for it.”</li>
<li>“As soon as we attempt to diagram software, we find it to constitute
not one, but several, general directed graphs, superimposed on one
another.”</li>
</ul>
<p>I think the below is a very interesting point; having a visual mind
does not seem to help you in programming.</p>
<ul>
<li>“In spite of progress in restricting and simplifying the structures
of software, they remain inherently unvisualizable, thus depriving the
mind of some of its most powerful conceptual tools.”</li>
</ul>
<p>Which follows nicely into the next point I underscored a page
later:</p>
<h3 id="graphical-programming">Graphical programming</h3>
<ul>
<li>“Nothing even convincing, much less exciting, has yet emerged from
such efforts. I am persuaded that nothing will.”</li>
</ul>
<h3 id="program-verification">Program verification</h3>
<ul>
<li>“Program verification does not mean error-proof programs. There is
no magic here, either. Mathematical proofs also can be faulty. So
whereas verification might reduce the program-testing load, it cannot
eliminate it.”</li>
<li>“More seriously, even perfect program verification can only
establish that a program meets its specification. The hardest part of
the software task is arriving at a complete and consistent
specification, and much of the essence of building a program is in fact
the debugging of the specification.”</li>
</ul>
<h3 id="environments-and-tools">Environments and tools</h3>
<p>One point that reminded me of <a
href="http://erlang.org/pipermail/erlang-questions/2011-May/058769.html">a
recent post by Joe Armstrong to the Erlang mailing list</a>:</p>
<ul>
<li>“Perhaps the biggest gain yet to be realized in the programming
environment is the use of integrated database systems to keep track of
the myriads of details that must be recalled accurately by the
individual programmer and kept current in a group of collaborators on a
single system.”</li>
</ul>
<p>(And I don’t think ‘intellisense’ really covers it.)</p>
<h3 id="promising-attacks-on-the-conceptual-essense">Promising Attacks
on the Conceptual Essense</h3>
<p>I found this to be a very interesting perspective considering the era
in which it was written:</p>
<ul>
<li>“There are dramatic exceptions to my argument that the
generalization of the software packages has changed little over the
years: electronic spreadsheets and simple database systems. These
powerful tools, <strong>so obvious in retrospect and yet so late
appearing</strong> [bold added for emphasis], lend themselves to myriad
uses, some quite unorthodox.”</li>
</ul>
<h3 id="incremental-development-grow-not-build-software">Incremental
development — grow, not build, software</h3>
<ul>
<li>“Some years ago, Harlan Mills proposed that any software system
should be grown by incremental development. That is, the system should
first be made to run, even though it does nothing useful except call the
proper set of dummy subprograms. Then, bit by bit it is fleshed out,
with the subprograms in turn being developed into actions or calls to
empty stubs in the level below.”</li>
<li>“The morale effects are startling. Enthusiasm jumps when there is a
running system, even a simple one.”</li>
<li>“I find that teams can <em>grow</em> much more complex entities in
four months than they can <em>build</em>.” (Yes, I see the gardener
analogy here, but <em>please</em>.)</li>
</ul>
<h3 id="great-designers">Great designers</h3>
<ul>
<li>“I think the most important single effort we can mount is to develop
ways to grow great designers.”</li>
</ul>
<p>There is a lot more crammed in this book, some several more chapters.
But I’ll stop here.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2011-06-26 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sun, 26 Jun 2011 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[‘amb’ operator and the list monad]]></title><link>https://chrisdone.com/posts/amb-list-monad</link><guid>https://chrisdone.com/posts/amb-list-monad</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>‘amb’ operator and the list monad</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>‘amb’ operator and the list monad</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>A friend was <a
href="http://mihai.bazon.net/blog/amb-in-javascript/take-two">messing
about with the <code>amb</code> operator</a> in JavaScript after seeing
it in Common Lisp. The <code>amb</code> (or <em>ambiguous</em>)
operator, first described by our pal John McCarthy (1967), and something
I first <a
href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-28.html#%_sec_4.3">encountered
in SICP.</a></p>
<p>These kind of constraint/logic puzzles seem naturally solved by the
list monad, <a href="http://hpaste.org/45504/who_owns_the_fish">here’s
an example of solving ‘Who owns the fish?’</a> Similar to <a
href="http://en.wikipedia.org/wiki/Zebra_Puzzle">the Zebra
puzzle.</a></p>
<pre><code>-- Translation of
-- http://mihai.bazon.net/blog/amb-in-javascript/take-two#wotf

import Control.Monad
import Data.Maybe
import Data.List

whoOwnsTheFish = addHouse []

addHouse houses = do

  nat &lt;- other &quot;nat&quot; [&quot;British&quot;,&quot;Swedish&quot;,&quot;Danish&quot;,&quot;Norwegian&quot;
                     ,&quot;German&quot;]
  col &lt;- other &quot;col&quot; [&quot;red&quot;,&quot;green&quot;,&quot;white&quot;,&quot;yellow&quot;,&quot;blue&quot;]
  pet &lt;- other &quot;pet&quot; [&quot;dogs&quot;,&quot;cats&quot;,&quot;horses&quot;,&quot;birds&quot;,&quot;fish&quot;]
  bev &lt;- other &quot;bev&quot; [&quot;tea&quot;,&quot;milk&quot;,&quot;coffee&quot;,&quot;beer&quot;,&quot;water&quot;]
  tob &lt;- other &quot;tob&quot; [&quot;pallmall&quot;,&quot;dunhill&quot;,&quot;marlboro&quot;
                     ,&quot;winfield&quot;,&quot;rothmans&quot;]

  (nat == &quot;British&quot;)  `iff` (col == &quot;red&quot;)
  (nat == &quot;Swedish&quot;)  `iff` (pet == &quot;dogs&quot;)
  (nat == &quot;Danish&quot;)   `iff` (bev == &quot;tea&quot;)
  (col == &quot;white&quot;)    `iff`
    (thisHouse &gt; 0 &amp;&amp; &quot;col&quot; `lookup` (houses!!(thisHouse - 1))
                       == Just &quot;green&quot;)
  (col == &quot;green&quot;)    `iff` (bev == &quot;coffee&quot;)
  (tob == &quot;pallmall&quot;) `iff` (pet == &quot;birds&quot;)
  (col == &quot;yellow&quot;)   `iff` (tob == &quot;dunhill&quot;)
  (thisHouse == 2)    `iff` (bev == &quot;milk&quot;)
  (thisHouse == 0)    `iff` (nat == &quot;Norwegian&quot;)
  (tob == &quot;winfield&quot;) `iff` (bev == &quot;beer&quot;)
  (nat == &quot;German&quot;)   `iff` (tob == &quot;rothmans&quot;)

  let h = [(&quot;nat&quot;,nat),(&quot;bev&quot;,bev),(&quot;tob&quot;,tob),(&quot;pet&quot;,pet)
          ,(&quot;col&quot;,col)]
      a = houses ++ [h]
  if length a == 5
     then do neighbors a &quot;tob&quot; &quot;marlboro&quot;  &quot;pet&quot; &quot;cats&quot;
             neighbors a &quot;pet&quot; &quot;horses&quot;    &quot;tob&quot; &quot;dunhill&quot;
             neighbors a &quot;nat&quot; &quot;Norwegian&quot; &quot;col&quot; &quot;blue&quot;
             neighbors a &quot;tob&quot; &quot;marlboro&quot;  &quot;bev&quot; &quot;water&quot;
             return a
     else addHouse a

  where other typ = filter (isNothing . findHouse houses typ)
        thisHouse = length houses

findHouse houses typ val =
  fmap fst . find ((==Just val) . lookup typ . snd) . zip [0..]
   $ houses

neighbors houses typ1 val1 typ2 val2 = guard $ diff == Just 1
  where diff = do h1 &lt;- findHouse houses typ1 val1
                  h2 &lt;- findHouse houses typ2 val2
                  return $ abs $ h1 - h2

iff x y = guard $ x == y</code></pre>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2011-04-10 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sun, 10 Apr 2011 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Hulk: A Haskell IRC server]]></title><link>https://chrisdone.com/posts/hulk-haskell-irc-server</link><guid>https://chrisdone.com/posts/hulk-haskell-irc-server</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Hulk: A Haskell IRC server</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Hulk: A Haskell IRC server</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Hulk is an working-and-work-in-progress IRC server. <a
href="https://github.com/chrisdone/hulk/">Github repo.</a></p>
<h2 id="motivation">Motivation</h2>
<p>Last Wednesday night I whipped up <a
href="https://github.com/chrisdone/hulk/tree/f1f8c662acfecbe7bb325ea1c1cda8f4284f0524">a
simple IRC server in Haskell in about four hours</a>. We have been long
time sick of the poor quality of the Skype Linux implementation, which
was, on the dev team, our main point of communication. We agreed
something like IRC would be good, so I thought it would be easy in
Haskell to make such a thing, and it was; the next day we were chatting
on it!</p>
<h2 id="good-timing">Good Timing</h2>
<p>I noticed that <a href="http://catonmat.net/">Peteris Krumins</a>
made a blog on Thursday about <a
href="http://catonmat.net/blog/simple-haskell-tcp-server">how to write a
TCP server in Haskell.</a> I thought, “That’s good timing!” I also use
the <a
href="hhttp://hackage.haskell.org/packages/archive/network/latest/doc/html/Network.html">Network</a>
module and <a
href="http://hackage.haskell.org/packages/archive/base/latest/doc/html/Control-Concurrent.html">Control.Concurrent</a>,
and do pretty much everything he is demonstrating in the blog. So it
seems like Hulk is a nice “real-world” demonstration of a non-simple TCP
server in Haskell.</p>
<h2 id="requirements">Requirements</h2>
<p>Our requirements for a server are quite narrow:</p>
<ul>
<li>It needs to be internal, so it has a mandatory login system (using
the Crypto package for salted SHA1 passwords). This not optional right
now.</li>
<li>We don’t care about flooding, IRC standards for nicknames, message
length of 512 bytes, lack of a specific encoding support, etc. The
server supports UTF8 everything.</li>
<li>I will be adding history, a la Skype and MSN Messenger, which stores
a log of all IRC activity and sends the ones of concern to you when you
re-connect.</li>
<li>I will also add OpenSSL support using <a
href="http://hackage.haskell.org/packages/archive/HsOpenSSL/0.9/doc/html/OpenSSL-Session.html#g:2">the
HsOpenSSL package which seemingly makes the whole process
trivial.</a></li>
</ul>
<p>We also pipe some feeds to it like tickets, Git commits, site issues,
etc.</p>
<h2 id="a-brief-overview">A Brief Overview</h2>
<h3 id="general-haskell-projects">General Haskell Projects</h3>
<p>In the spirit with which Peteris writes I thought that I might
describe the design of the project a little bit.</p>
<pre><code>$ ls
auth  history     hulk.conf  README    src
dist  hulk.cabal  LICENSE    Setup.hs  txt</code></pre>
<p>It’s good Haskell practice to start any project with
<code>cabal init</code> which asks you a series of questions and
generates a <code>.cabal</code> file for you. Common practice is to put
source in the <code>src</code> dir, and have your Project in a
sub-directory matching the project name:</p>
<pre><code>$ ls src
Control  Data  GeneratePass.hs  Hulk  Main.hs</code></pre>
<p>Code that isn’t specific to the particular project but could be used
anywhere should go in appropriate modules such as
<code>Control.*</code>, <code>Data.*</code>, etc. It occurs commonly
that you will need this code in other projects and because the
dependency between these modules and your main project’s modules is only
in one direction you can simply copy the files over to your new
project.</p>
<h3 id="hulks-module-hierarchy">Hulk’s module hierarchy</h3>
<pre><code>Control.Monad.IO
Data.String
Hulk
  Hulk.Auth
  Hulk.Client
  Hulk.Config
  Hulk.Event
  Hulk.Options
  Hulk.Providers
  Hulk.Server
  Hulk.Types
Main</code></pre>
<p>The first two just contain utilities that I tend to use often. The
<code>Main</code> module is the main entry point, then control goes to
<code>Hulk.Server</code> which starts listening on the right port,
accepting connections and handling/sending messages to/from clients.</p>
<h3 id="purity-vs-impurity">Purity vs Impurity</h3>
<p>In order to handle messages and reply to them from clients, the
<code>Hulk.Client</code> module is used. The code in Hulk.Client is
entirely pure, and it is the bulk of the project. This is an intentional
effort. The original program I whipped up used a bunch of MVars and was
basically an imperative program, and about as confusing.</p>
<center>
<img
src="http://img684.imageshack.us/img684/4484/spiderskullisland480x27.jpg"
title="Spider Skull Island from Venture Bros">
</center>
<p>Another “good practice” is for Haskell programs to be like a
well-oiled super villain base. On the edge is where all the explosions
happen, and inside is where the bad guys sit and drink Orzo and control
everything.</p>
<blockquote>
<p><img style="float:right;margin-left:10px;margin-bottom:5px;"
src="http://img593.imageshack.us/img593/1179/3202x.jpg"
title="Henchmen"> Impure code is like the wreckless henchmen who always
wreck everything, and double-cross you at every opportunity. Pure code
is the evil genius who devises the master plan, tells the henchmen what
to do, and keeps them in separate living quarters.</p>
</blockquote>
<p>It’s also common to put all your types into one module named
<code>Types</code>, as you tend to use types from every module and this
avoids circular dependency problems in the long run.</p>
<h3 id="flow-of-the-program">Flow of the program</h3>
<p>The main entry point to the project is in <code>Main</code>, as it
should be:</p>
<pre><code>{-# OPTIONS -Wall #-}
module Main where

import Network
import System.Console.CmdArgs
import System.Posix

import Hulk.Config  (getConfig)
import Hulk.Options (options,optionsConf)
import Hulk.Server  (start)
import Hulk.Types   ()

main :: IO ()
main = withSocketsDo $ do
  _ &lt;- installHandler sigPIPE Ignore Nothing
  cmdArgs options &gt;&gt;= getConfig . optionsConf &gt;&gt;= start</code></pre>
<p>I initialise the sockets subsystem for Windows and then install a
handler for <code>SIGPIPE</code>, because that signal is sent in Unix
when a program attempts to write to a socket that has been closed. Both
Windows and Unix have their novel design choices. Go figure.</p>
<p>I’m using the <a
href="http://hackage.haskell.org/package/cmdargs">CmdArgs library</a>,
<a
href="http://neilmitchell.blogspot.com/2010/08/cmdargs-example.html">tutorial
here by the author, Neil Mitchell</a>, which I am pleased is becoming
part of my standard project repertoire.</p>
<p>I define my options merely as a way to specify the configuration
file, for now.</p>
<pre><code>{-# LANGUAGE DeriveDataTypeable, RecordWildCards, ScopedTypeVariables #-}
{-# OPTIONS -Wall -fno-warn-missing-signatures #-}
module Hulk.Options (Options
                    ,options
                    ,optionsConf) where

import System.Console.CmdArgs

data Options = Options
  { conf      :: FilePath
  } deriving (Show,Data,Typeable)

options = Options
  { conf = def &amp;= opt &quot;hulk.conf&quot; &amp;= help &quot;The config file.&quot;
  }
  &amp;= summary &quot;Hulk IRC Daemon (C) Chris Done 2011&quot;
  &amp;= help &quot;Runs an IRC server based on the provided configuration file.&quot;</code></pre>
<p>And I read the config file with <a
href="http://hackage.haskell.org/package/ConfigFile">the great
ConfigFile library</a>:</p>
<pre><code>{-# OPTIONS -Wall -fno-warn-missing-signatures -fno-warn-name-shadowing #-}
module Hulk.Config
    (Config(..)
    ,getConfig)
    where

import Data.Word
import Data.ConfigFile

import Hulk.Types

getConfig :: FilePath -&gt; IO Config
getConfig conf = do
  contents &lt;- readFile conf
  let config = do
        c &lt;- readstring emptyCP contents
        hostname &lt;- get c &quot;LISTEN&quot; &quot;hostname&quot;
        listen &lt;- get c &quot;LISTEN&quot; &quot;port&quot;
        motd &lt;- get c &quot;STRINGS&quot; &quot;motd_file&quot;
        preface &lt;- get c &quot;STRINGS&quot; &quot;preface_file&quot;
        passwd &lt;- get c &quot;AUTH&quot; &quot;passwd_file&quot;
        key &lt;- get c &quot;AUTH&quot; &quot;passwd_key&quot;
        return Config { configListen = fromIntegral (listen::Word16)
                      , configMotd = Just motd
                      , configHostname = hostname
                      , configPasswd = passwd
                      , configPasswdKey = key
                      , configPreface = Just preface
                      }
  case config of
    Left cperr -&gt; error $ show cperr
    Right config -&gt; return config</code></pre>
<p>The reading process is merely a simple monad that either returns the
<code>Config</code> object or an error. I choose to just throw an error
when there’s an issue. I use this library for pretty much every project
I use, it really is an essential library.</p>
<p>An alternative way to express the code above is to
<code>runReaderT</code>, define a function like
<code>get' = ask &gt;&gt;= flip get</code> and then you can express the
above with Applicative operators <code>(&lt;$&gt;)</code> and
<code>(&lt;*&gt;)</code>.</p>
<p>This module will read a file like this:</p>
<pre><code>[LISTEN]
port = 6667
hostname = cn-done

[STRINGS]
motd_file = txt/MOTD
preface_file = txt/PREFACE

[AUTH]
passwd_file = auth/passwd</code></pre>
<h3 id="server-starter">Server starter</h3>
<p>I start the server by using the <code>listenOn</code> function,
covered in Peteris’s post, and accept connections, setting the buffering
to <code>NoBuffering</code>. This turns out to be rather important; as
Peteris mentions, this avoids surprises with buffering, which is
something I experienced when testing out <code>LineBuffering</code> in
this project. In certain situations unknown to me, access to handles
locks up.</p>
<pre><code>-- | Start an IRC server with the given configuration.
start :: Config -&gt; IO ()
start config = withSocketsDo $ do
  hSetBuffering stdout LineBuffering
  listenSock &lt;- listenOn $ PortNumber (configListen config)
  envar &lt;- newMVar Env { envClients = M.empty
                       , envNicks = M.empty
                       , envChannels = M.empty }
  forever $ do
    (handle,host,_port) &lt;- accept listenSock
    hSetBuffering handle NoBuffering
    let conn = Conn { connRef = newRef handle
                    , connHostname = host
                    , connServerName = configHostname config
                    }
    _ &lt;- forkIO $ handleClient config handle envar conn
    return ()</code></pre>
<h3 id="connection-handling">Connection handling</h3>
<p>I fork a new thread per handle. No big deal. I have one value,
<code>envar</code>, of type <code>MVar Env</code>, which stores the
state of the whole server. It can only be accessed by one thread at a
time, that’s why I put it on an <code>MVar</code>. The definition of
<code>Env</code> is:</p>
<pre><code>data Env = Env {
   envClients :: Map Ref Client
  ,envNicks :: Map Nick Ref
  ,envChannels :: Map ChannelName Channel
}</code></pre>
<p>where</p>
<pre><code>newtype Ref = Ref { unRef :: Handle }
    deriving (Show,Eq)</code></pre>
<p><code>Ref</code> is merely a wrapper for Handles, to avoid me
accidentally using a handle. It is only used as a unique reference to a
client.</p>
<p>In the new thread I have a handler which receives newlines from the
client:</p>
<pre><code>-- | Handle a client connection.
handleClient :: Config -&gt; Handle -&gt; MVar Env -&gt; Conn -&gt; IO ()
handleClient config handle env conn = do
  let runHandle = runClientHandler config env handle conn
  runHandle $ makeLine CONNECT []
  fix $ \loop -&gt; do
    line &lt;- catch (Right &lt;$&gt; UTF8.hGetLine handle) (return . Left)
    case filter (not.newline) &lt;$&gt; line of
      Right []   -&gt; loop
      Right line -&gt; do runHandle (line++&quot;\r&quot;); loop
      Left _err  -&gt; runHandle $ makeLine DISCONNECT [&quot;Connection lost.&quot;]

  where newline c = c==&#39;\n&#39; || c==&#39;\r&#39;</code></pre>
<p>I get a line which is Right, or fail and return what’s Left. The case
of getLine failing is when the socket is closed. I ignore messages only
containing newline characters, and the middle case is actually getting a
valid line which I pass to <code>runHandle</code> that runs the pure
client handler, then <code>loop</code>s again.</p>
<h3 id="client-handler">Client handler</h3>
<p>To run the client handler, I have the following function:</p>
<pre><code>-- | Handle a received line from the client.
runClientHandler :: Config -&gt; MVar Env -&gt; Handle -&gt; Conn -&gt; String -&gt; IO ()
runClientHandler config env handle conn line = do
  modifyMVar_ env $ \env -&gt; do
    (replies,env) &lt;- runReaderT (runHulkIO $ handleLine env conn line) config
    mapM_ (handleReplies handle) replies
    return env</code></pre>
<p>It passes the program state (<code>env</code>) and the current
connection info (<code>conn</code>) to the function
<code>handleLine</code>, which is the single export from
<code>Hulk.Client</code>, which is a transformer over an arbitrary
monad. Technically, in this case I’m running it inside a
<code>readerT</code> on <code>IO</code>, so it’s not actually pure. The
<code>handleLine</code> action returns a bunch of replies/instructions
for the <code>Server</code> module to perform and a new state
(<code>env</code>).</p>
<p>When I said that the <code>Hulk.Client</code> module was pure, I
meant that it is abstracted over whether it is pure or impure, and
therefore can be treated as pure for testing and developing, and when
running the server, runs in IO, but only 0.1% of the code uses IO. Also,
when I said “arbitrary monad”, I meant any monad implementing the
<code>MonadProvider</code> class.</p>
<pre><code>class Monad m =&gt; MonadProvider m where
  providePreface   :: m (Maybe String)
  provideMotd      :: m (Maybe String)
  provideKey       :: m String
  providePasswords :: m String</code></pre>
<p>Meaning that these are the only “impure” things I need when running
the program. I need to read the preface, motd, key, and password files
on demand. In the <code>IO</code> case, I simply read the file. In the
pure case, I can stick it in a <code>Reader</code> or
<code>Identity</code> monad and the whole computation is thus pure.</p>
<p>What’s the benefit? This means I can run arbitrary parts of the
computation trivially, and make pure test suites out of it. QuickCheck
my IRCd, anyone? The main benefits are not to have to worry about
conflicting simultaneous threads, and being able to run any function
from the module with whatever state one desires.</p>
<h3 id="client-replies">Client replies</h3>
<p>The <code>Client</code> module replies with one of the following:</p>
<pre><code>data Reply = MessageReply Ref Message | LogReply String | Close</code></pre>
<ul>
<li><code>MessageReply</code>: Send this <code>Message</code> to the
given handle (<code>Ref</code>).</li>
<li><code>LogReply</code>: Log this <code>String</code>.</li>
<li><code>Close</code>: Close the current connection.</li>
</ul>
<p>I find this separation of IO and logic to be useful.</p>
<h3 id="the-irc-monad-stack">The IRC monad stack</h3>
<p>The rest of the project lies in <code>Hulk.Client</code> and is
academic/straight-forward. I will explain the <code>IRC</code> monad,
though:</p>
<pre><code>newtype IRC m a = IRC {
    runIRC :: ReaderT Conn (WriterT [Reply] (StateT Env m)) a
  }
  deriving (Monad
           ,Functor
           ,MonadWriter [Reply]
           ,MonadState Env
           ,MonadReader Conn)</code></pre>
<ul>
<li>I output replies, hence the <code>MonadWriter [Reply]</code>.</li>
<li>I read the connection info (<code>Conn</code>), but I
<em>don’t/shouldn’t</em> modify it or write to it.</li>
<li>I <em>do</em> read/modify the <code>Env</code>, which is the whole
server state.</li>
<li>Finally, it is parametrized over an arbitrary monad, but the
functions in <code>Client</code> constrain to
<code>MonadProvider</code>.</li>
</ul>
<p>This is called <a
href="http://book.realworldhaskell.org/read/monad-transformers.html">a
monad transformer stack</a>. <a
href="http://en.wikibooks.org/wiki/Haskell/Monad_transformers">Haskell
Wikibook on transformers</a></p>
<h3 id="examples">Examples</h3>
<p>Example of a <code>MessageReply</code>:</p>
<pre><code>-- | Send a message reply.
reply :: Monad m =&gt; Ref -&gt; Message -&gt; IRC m ()
reply ref msg = do
  outgoing $ encode msg
  tell . return $ MessageReply ref msg</code></pre>
<p>Examples of <code>LogReply</code>:</p>
<pre><code>-- | Log an outgoing line.
outgoing :: Monad m =&gt; String -&gt; IRC m ()
outgoing = log . (&quot;-&gt; &quot; ++)

-- | Log a line.
log :: Monad m =&gt; String -&gt; IRC m ()
log = tell . return . LogReply</code></pre>
<p>Example of the <code>StateT</code>:</p>
<pre><code>-- | Modify the nicks mapping.
modifyNicks :: Monad m =&gt; (Map Nick Ref -&gt; Map Nick Ref) -&gt; IRC m ()
modifyNicks f = modify $ \env -&gt; env { envNicks = f (envNicks env) }</code></pre>
<p>Example of using the <code>Conn</code> object from the
<code>ReaderT</code>:</p>
<pre><code>-- | Make a new IRC message from the server.
newServerMsg :: Monad m =&gt; String -&gt; [String] -&gt; IRC m Message
newServerMsg cmd ps = do
  hostname &lt;- asks connServerName
  return $ Message {
    msg_prefix = Just $ Server hostname
   ,msg_command = cmd
   ,msg_params = ps
  }</code></pre>
<h2 id="summary">Summary</h2>
<p>That’s all, folks! I hope this is useful to some people thinking of
writing their first Haskell daemon project.</p>
<p>Haskell is the only language I know in which I can write 400~ lines
of code without running it and then run it and have it work as
expected.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2011-01-30 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sun, 30 Jan 2011 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Lisk - Lisp and Haskell]]></title><link>https://chrisdone.com/posts/lisk-lisp-haskell</link><guid>https://chrisdone.com/posts/lisk-lisp-haskell</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Lisk - Lisp and Haskell</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Lisk - Lisp and Haskell</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>In my spare time I’m working on a project called Lisk. Using the
<code>-pgmF</code> option for GHC, you can provide GHC a program name
that is called to preprocess the file before GHC compiles it. It also
works in GHCi and imports. You use it like this:</p>
<pre><code>{-# OPTIONS -F -pgmF lisk #-}
(module fibs
  (import system.environment)

  (:: main (io ()))
  (= main (&gt;&gt;= get-args (. print fib read head)))

  (:: test (-&gt; :string (, :int :string)))
  (= test (, 1))

  (:: fib (-&gt; :int :int))
  (= fib 0 0)
  (= fib 1 1)
  (= fib n (+ (fib (- n 1))
              (fib (- n 2)))))</code></pre>
<p>The git repo is here:</p>
<pre><code>git://github.com/chrisdone/lisk.git</code></pre>
<p>And the <a href="https://github.com/chrisdone/lisk">github page is
here.</a></p>
<p>I literally only support what is exhibited in the example above, and
it is not ready for use at all. But I am using <a
href="http://hackage.haskell.org/package/haskell-src-exts">haskell-src-exts’s</a>
AST and pretty printer in order to convert from Lisk to Haskell, so I’m
in good hands regarding completeness of the syntax. I don’t have a lot
of time to work on it right now, but I will be doing.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2010-11-25 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Thu, 25 Nov 2010 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Duck typing in Haskell]]></title><link>https://chrisdone.com/posts/duck-typing-in-haskell</link><guid>https://chrisdone.com/posts/duck-typing-in-haskell</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Duck typing in Haskell</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Duck typing in Haskell</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>This is a simple Literate Haskell file demonstrating <a
href="http://en.wikipedia.org/wiki/Duck_typing">duck typing</a> in
Haskell. You copy the whole web page and paste it into a .hs file and
compile/load it. Grab the normal Haskell version <a
href="http://hpaste.org/41710/duck_typing">here.</a></p>
<p>I’m using <a href="http://hackage.haskell.org/package/has">a library
called Has which you can grab from Hackage</a> (or just
<code>cabal install has</code>). It’s pretty neat, it allows you to
define field names and their types, that you are going to use at some
point, and then lets you construct/access/update arbitrary records based
on those fields.</p>
<p>We need to enable type families and flexible class contexts to work
with this library. And also it’s nice if we disable the monomorphism
restriction. I don’t want mono, I want manymorphism! As many as you can
fit in your pocket.</p>
<pre><code>&gt; {-# LANGUAGE TypeFamilies, FlexibleContexts, NoMonomorphismRestriction #-}</code></pre>
<p>In this library you define fields like this:</p>
<pre><code>data Flap = Flap; type instance TypeOf Flap = IO ()</code></pre>
<p>Here I’m defining a “flap” method. Ducks flap! The <code>Flap</code>
part is the accessor. But it sucks to have to write that, so we define a
synonym. So the whole field definition ends up being:</p>
<pre><code>data Flap = Flap; type instance TypeOf Flap = IO (); flap = Flap</code></pre>
<p>Which is getting a little tedius, so I whipped up a little template
haskell to make this easier. You can install that <a
href="http://hackage.haskell.org/package/has-th">from Hackage too</a>
(or just <code>cabal install has-th</code>). So let’s enable template
haskell:</p>
<pre><code>&gt; {-# LANGUAGE TemplateHaskell #-}</code></pre>
<p>Now I just import the Has library and my template haskell module.</p>
<pre><code>&gt; import Data.Has hiding (field)
&gt; import Data.Has.TH</code></pre>
<p>And defining accessors is really easy:</p>
<pre><code>&gt; field &quot;flap&quot;  [t|IO ()|]
&gt; field &quot;quack&quot; [t|String|]
&gt; field &quot;swim&quot;  [t|IO ()|]
&gt; data Food = Bread | Pasta | Duck deriving Show
&gt; field &quot;eat&quot;   [t|Food -&gt; Either String String|]
&gt; field &quot;name&quot;  [t|String|]
&gt; field &quot;age&quot;   [t|Integer|]</code></pre>
<p>The <code>[t|Foo|]</code> is just a reader macro for reading types
that exist.</p>
<p>So I’ve defined a bunch of things that a duck generally <em>does</em>
and <em>has</em>. Referring to James Whitcomb Riley:</p>
<blockquote>
<p>“When I see a bird that walks like a duck and swims like a duck and
quacks like a duck, I call that bird a duck.”</p>
</blockquote>
<p>Now let’s make some ducks! The obvious being Donald Duck:</p>
<pre><code>&gt; donald = flap  ^- putStrLn &quot;*Flap flap flap*&quot;
&gt;        &amp; quack ^- &quot;QUACK!&quot;
&gt;        &amp; swim  ^- putStrLn &quot;*Ducky paddle*&quot;
&gt;        &amp; eat   ^- nom
&gt;        &amp; name  ^- &quot;Donald Duck&quot;
&gt;   where nom Bread = Right &quot;Nom nom nom!&quot;
&gt;         nom Pasta = Right &quot;Ew, give me something bweady.&quot;
&gt;         nom Duck  = Left  &quot;Are you cwazy!?&quot;</code></pre>
<p>He flaps, quacks, swims, eats and has a name. Also, I’ll pretend to
be a duck, too:</p>
<pre><code>&gt; chris = flap  ^- putStrLn &quot;I&#39;m flapping my arms!&quot;
&gt;       &amp; quack ^- &quot;Erm, quack?&quot;
&gt;       &amp; swim  ^- putStrLn &quot;I&#39;m doing the butterfly because it&#39;s efficient ...&quot;
&gt;       &amp; age   ^- 67
&gt;       &amp; eat   ^- nom
&gt;       &amp; name  ^- &quot;Chris Done&quot;
&gt;   where nom Bread = Left  &quot;Bread is alright, but no thanks.&quot;
&gt;         nom Pasta = Right &quot;Pasta is okay. Got anything to go with it?&quot;
&gt;         nom Duck  = Right &quot;Om nom nom.&quot;</code></pre>
<p>Notice that I’ve got one more field than <code>donald</code>, I’ve
got an <code>age</code>. This means we are two distinct record types.
We’ve got different stuff! But we’re both ducks! See:</p>
<pre><code>λ&gt; flap ^. donald
*Flap flap flap*

λ&gt; flap ^. chris
I&#39;m flapping my arms!

λ&gt; quack ^. donald
&quot;QUACK!&quot;

λ&gt; quack ^. chris
&quot;Erm, quack?&quot;</code></pre>
<p>Here is a nice thing that we get, we can define any function as
taking anything that <strong>has</strong> certain fields, and we know
that those fields have the right type because we defined them above:</p>
<pre><code>&gt; fly :: (Has Flap duck) =&gt; duck -&gt; IO ()
&gt; fly duck = do go; go; go where go = flap ^. duck

λ&gt; fly donald
*Flap flap flap*
*Flap flap flap*
*Flap flap flap*</code></pre>
<p>We do this multiple times, too:</p>
<pre><code>&gt; playInPond :: (Has Swim duck, Has Flap duck, Has Eat duck, Has Name duck)
&gt;            =&gt; duck -&gt; Food -&gt; IO ()
&gt; playInPond duck food = do
&gt;   putStrLn $ (name ^. duck) ++ &quot; is swimming happily.&quot;
&gt;   swim ^. duck
&gt;   putStrLn $ &quot;You give them some &quot; ++ show food ++ &quot; to eat.&quot;
&gt;   case (eat ^. duck) food of
&gt;     Left dnw  -&gt; do putStrLn dnw; fly duck
&gt;     Right nom -&gt; putStrLn nom
&gt;   swim ^. duck</code></pre>
<p>And let’s see the ducks play in the pond when someone’s throwing some
food:</p>
<pre><code>λ&gt; playInPond donald Bread
Donald Duck is swimming happily.
*Ducky paddle*
You give them some Bread to eat.
Nom nom nom!
*Ducky paddle*

λ&gt; playInPond chris Bread
Chris Done is swimming happily.
I&#39;m doing the butterfly because it&#39;s efficient ...
You give them some Bread to eat.
Bread is alright, but no thanks.
I&#39;m flapping my arms!
I&#39;m flapping my arms!
I&#39;m flapping my arms!
I&#39;m doing the butterfly because it&#39;s efficient ...

λ&gt; playInPond donald Duck
Donald Duck is swimming happily.
*Ducky paddle*
You give them some Duck to eat.
Are you cwazy!?
*Flap flap flap*
*Flap flap flap*
*Flap flap flap*
*Ducky paddle*</code></pre>
<p>They both have the same things. However, they <em>are</em>
different:</p>
<pre><code>λ&gt; age ^. chris
67

λ&gt; age ^. donald

&lt;interactive&gt;:1:0: No instance for (Contains (Labelled Age Integer)
TyNil) arising from a use of `^.&#39; at &lt;interactive&gt;:1:0-12</code></pre>
<p>So there you have it, duck typing in a statically typed way. We get
to have our cake and eat it too.</p>
<hr />
<p>By the way, and this isn’t particularly important, I used a function
to make creating record fields a little nicer, because I don’t like the
namelessness of writing <code>fieldOf 23</code>:</p>
<pre><code>&gt; -- | Creation: I like to be able to name the fields that I&#39;m assigning.
&gt; (^-) :: a -&gt; TypeOf a -&gt; FieldOf a
&gt; (^-) = const $ fieldOf
&gt; infixr 6 ^-</code></pre>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2010-11-22 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Mon, 22 Nov 2010 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Applicative and ConfigFile, HSQL]]></title><link>https://chrisdone.com/posts/applicative-and-config-file</link><guid>https://chrisdone.com/posts/applicative-and-config-file</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Applicative and ConfigFile, HSQL</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Applicative and ConfigFile, HSQL</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>I’ve been noticing some totally sweet uses of Applicative cropping up
in my day to day coding. I figured I’d show off some neat uses of it I
had recently.</p>
<h2 id="configfile">ConfigFile</h2>
<p>Also worth mentioning is the ConfigFile library which is pretty
sweet.</p>
<p>The idea is to run in the ErrorT monad to pull specific configuration
items from the file. Here an example taken from the documentation reads
the configuration file into cp and uses the get function to extract
values from sections.</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.ConfigFile</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Monad.Error</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>          rv <span class="ot">&lt;-</span> runErrorT <span class="op">$</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>              <span class="kw">do</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>              cp <span class="ot">&lt;-</span> join <span class="op">$</span> liftIO <span class="op">$</span> readfile empty <span class="st">&quot;/etc/passwd&quot;</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>              <span class="kw">let</span> x <span class="ot">=</span> cp</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>              liftIO <span class="op">$</span> <span class="fu">putStrLn</span> <span class="st">&quot;In the test&quot;</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>              nb <span class="ot">&lt;-</span> get x <span class="st">&quot;DEFAULT&quot;</span> <span class="st">&quot;nobody&quot;</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>              liftIO <span class="op">$</span> <span class="fu">putStrLn</span> nb</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>              foo <span class="ot">&lt;-</span> get x <span class="st">&quot;DEFAULT&quot;</span> <span class="st">&quot;foo&quot;</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>              liftIO <span class="op">$</span> <span class="fu">putStrLn</span> foo</span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>              <span class="fu">return</span> <span class="st">&quot;done&quot;</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>          <span class="fu">print</span> rv</span></code></pre></div>
<p>This is pretty flexible and allows us to make one awesome
abstraction. Make an Applicative instance!</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> <span class="dt">Applicative</span> (<span class="dt">ErrorT</span> <span class="dt">C.CPError</span> m) <span class="kw">where</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    <span class="fu">pure</span> <span class="ot">=</span> <span class="fu">return</span>; (<span class="op">&lt;*&gt;</span>) <span class="ot">=</span> ap</span></code></pre></div>
<p>And this lets me write the config parser in a really nice way:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ot">getConf ::</span> <span class="dt">FilePath</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> (<span class="dt">Either</span> (<span class="dt">C.CPErrorData</span>,<span class="dt">String</span>) <span class="dt">Blog</span>)</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>getConf filePath <span class="ot">=</span> runErrorT <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>  contents <span class="ot">&lt;-</span> liftIO <span class="op">$</span> <span class="fu">readFile</span> filePath</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>  config <span class="ot">&lt;-</span> C.readstring C.emptyCP contents</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">let</span> get <span class="ot">=</span> C.get config <span class="st">&quot;BLOG&quot;</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Blog</span> <span class="op">&lt;$&gt;</span> get <span class="st">&quot;name&quot;</span> <span class="op">&lt;*&gt;</span> get <span class="st">&quot;root&quot;</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>       <span class="op">&lt;*&gt;</span> (<span class="fu">read</span> <span class="op">&lt;$&gt;</span> get <span class="st">&quot;css&quot;</span>) <span class="op">&lt;*&gt;</span> get <span class="st">&quot;entries&quot;</span> <span class="op">&lt;*&gt;</span> get <span class="st">&quot;html&quot;</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>       <span class="op">&lt;*&gt;</span> get <span class="st">&quot;author&quot;</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>       <span class="op">&lt;*&gt;</span> <span class="fu">return</span> <span class="dt">False</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>       <span class="op">&lt;*&gt;</span> get <span class="st">&quot;date&quot;</span></span></code></pre></div>
<p>Double checking the definition of Blog, we can see where everything
fits:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Blog</span> <span class="ot">=</span> <span class="dt">Blog</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    {<span class="ot"> blogName     ::</span> <span class="dt">String</span> <span class="co">-- e.g. Chris Done&#39;s Blog</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>    ,<span class="ot"> blogRoot     ::</span> <span class="dt">String</span> <span class="co">-- /blog</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>    ,<span class="ot"> blogCSS      ::</span> [<span class="dt">String</span>] <span class="co">-- e.g. [&quot;style.css&quot;,&quot;highlight.css&quot;]</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>    ,<span class="ot"> blogEntries  ::</span> <span class="dt">FilePath</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>    ,<span class="ot"> blogHtml     ::</span> <span class="dt">FilePath</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>    ,<span class="ot"> blogAuthor   ::</span> <span class="dt">String</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>    ,<span class="ot"> blogForce    ::</span> <span class="dt">Bool</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>    ,<span class="ot"> blogDate     ::</span> <span class="dt">String</span> <span class="co">-- date format e.g.</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>                             <span class="co">-- &quot;%A %d %b, %Y&quot; makes &quot;Tuesday 10 Feb, 2009&quot;</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>    } <span class="kw">deriving</span> (<span class="dt">Read</span>,<span class="dt">Show</span>)</span></code></pre></div>
<p>We see that I use return False for blogForce (an option to force
refreshing of all pages regardless of modification date), and that is
because I don’t want it to be specified in the configuration file.</p>
<p>Of course, not only is this more pretty, we can also make values
optional by making an Alternative instance. We see a real use of this in
my Lojbot source:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> <span class="dt">Alternative</span> (<span class="dt">ErrorT</span> <span class="dt">C.CPError</span> m) <span class="kw">where</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    empty <span class="ot">=</span> mzero; (<span class="op">&lt;|&gt;</span>) <span class="ot">=</span> mplus</span></code></pre></div>
<p>And now in the readConfig function, we see it’s slightly more complex
than Blogination’s; I’m taking from multiple sections. Do you see the
res function?</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="ot">readConfig ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> (<span class="dt">Either</span> (<span class="dt">C.CPErrorData</span>,<span class="dt">String</span>) <span class="dt">Config</span>)</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>readConfig filePath <span class="ot">=</span> runErrorT <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>  config <span class="ot">&lt;-</span> join <span class="op">$</span> liftIO <span class="op">$</span> C.readfile C.emptyCP filePath</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">let</span> irc <span class="ot">=</span> C.get config <span class="st">&quot;IRCBOT&quot;</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>      port <span class="ot">=</span> C.get config <span class="st">&quot;IRCBOT&quot;</span> <span class="st">&quot;port&quot;</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>      misc <span class="ot">=</span> C.get config <span class="st">&quot;MISC&quot;</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>      res k f <span class="ot">=</span> misc k <span class="op">&lt;|&gt;</span> liftIO (getDataFileName f)</span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Config</span> <span class="op">&lt;$&gt;</span> irc <span class="st">&quot;nick&quot;</span> <span class="op">&lt;*&gt;</span>  irc <span class="st">&quot;nickservpass&quot;</span> <span class="op">&lt;*&gt;</span> irc <span class="st">&quot;server&quot;</span> <span class="op">&lt;*&gt;</span> port</span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>         <span class="op">&lt;*&gt;</span> (irc <span class="st">&quot;chans&quot;</span> <span class="op">&gt;&gt;=</span> tryGet <span class="st">&quot;invalid channel list&quot;</span>)</span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>         <span class="op">&lt;*&gt;</span> (irc <span class="st">&quot;log&quot;</span> <span class="op">&gt;&gt;=</span> tryGet <span class="st">&quot;invalid log specification&quot;</span>)</span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>         <span class="op">&lt;*&gt;</span> res <span class="st">&quot;jbov&quot;</span> <span class="st">&quot;jbovlaste.db&quot;</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a>         <span class="op">&lt;*&gt;</span> res <span class="st">&quot;mlismu&quot;</span> <span class="st">&quot;fatci.txt&quot;</span></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a>         <span class="op">&lt;*&gt;</span> (misc <span class="st">&quot;mode&quot;</span> <span class="op">&gt;&gt;=</span> tryGet <span class="st">&quot;invalid mode&quot;</span>)</span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a>         <span class="op">&lt;*&gt;</span> (<span class="fu">read</span> <span class="op">&lt;$&gt;</span> irc <span class="st">&quot;interval&quot;</span>)</span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a>      <span class="kw">where</span> tryGet msg <span class="ot">=</span> list (<span class="fu">fail</span> msg) (<span class="fu">return</span> <span class="op">.</span> <span class="fu">fst</span> <span class="op">.</span> <span class="fu">head</span>) <span class="op">.</span> <span class="fu">reads</span></span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a><span class="ot">``` haskell</span></span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a><span class="ot">The res function either pulls an optional setting from the MISC section, or alternatively uses the getDataFileName function to find out a filename held in our cabal package.</span></span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true" tabindex="-1"></a><span class="ot">```</span> haskell</span>
<span id="cb6-21"><a href="#cb6-21" aria-hidden="true" tabindex="-1"></a>      <span class="op">$</span><span class="dt">Haskell</span><span class="op">$</span></span>
<span id="cb6-22"><a href="#cb6-22" aria-hidden="true" tabindex="-1"></a>      res k f <span class="ot">=</span> misc k <span class="op">&lt;|&gt;</span> liftIO (getDataFileName f)</span></code></pre></div>
<p>Isn’t that totally sweet?</p>
<h2 id="hsql">HSQL</h2>
<p>Of course, I’ve used this pattern elsewhere; in HSQL it works out
nicely, too, and I have added some fancier bits to it:</p>
<p>A straight-forward function to grab a field value from a Statement
(which is like a row in HSQL).</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="ot">field ::</span> (<span class="dt">SqlBind</span> a) <span class="ot">=&gt;</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Statement</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> a</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>field <span class="ot">=</span> <span class="fu">flip</span> MySQL.getFieldValue</span></code></pre></div>
<p>Another function to read a Haskell value from an SQL field:</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ot">readfield ::</span> <span class="dt">Read</span> a <span class="ot">=&gt;</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Statement</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> a</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>readfield f <span class="ot">=</span> <span class="fu">fmap</span> <span class="fu">read</span> <span class="op">.</span> <span class="fu">flip</span> MySQL.getFieldValue f</span></code></pre></div>
<p>Here is the nice part.</p>
<p>Originally, I would pull fields from a statement using the monadic
field, e.g.</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="ot">getOrder ::</span> <span class="dt">Statement</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> <span class="dt">Order</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>getOrder s <span class="ot">=</span> <span class="kw">do</span> <span class="fu">id</span> <span class="ot">&lt;-</span> field <span class="st">&quot;id&quot;</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>                name <span class="ot">&lt;-</span> field <span class="st">&quot;name&quot;</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="co">-- etc..</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>                <span class="fu">return</span> <span class="op">$</span> <span class="dt">Order</span> <span class="fu">id</span> name <span class="co">-- ...</span></span></code></pre></div>
<p>But then I realised I could make this into a use of applicative. You
see the pattern, right?</p>
<p>Here I define an instance of Applicative for the ReaderT monad
transformer, so that I can stick a Statement in it to be used later on
when extracting fields.</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">StatementM</span> <span class="ot">=</span> <span class="dt">ReaderT</span> <span class="dt">Statement</span> <span class="dt">IO</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> <span class="dt">Applicative</span> (<span class="dt">ReaderT</span> a m) <span class="kw">where</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>    (<span class="op">&lt;*&gt;</span>) <span class="ot">=</span> ap; <span class="fu">pure</span> <span class="ot">=</span> <span class="fu">return</span></span></code></pre></div>
<p>getFields is just an alias for runReaderT giving us the explicit
StatementM type:</p>
<div class="sourceCode" id="cb11"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="ot">getFields ::</span> <span class="dt">StatementM</span> a <span class="ot">-&gt;</span> <span class="dt">Statement</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> a</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>getFields <span class="ot">=</span> runReaderT</span></code></pre></div>
<p>Finally, rather than typing out field statement “blah” or readfield
all the time, I realised I could abstract that by putting the Statement
in the ReaderT and then define some operators which work with this
statement under the hood (I ain’t apologising for use of unicode
operators :-P):</p>
<div class="sourceCode" id="cb12"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>a · b <span class="ot">=</span> a <span class="op">&lt;*&gt;</span> getField b; <span class="kw">infixl</span> <span class="dv">4</span> ·</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>a ·<span class="op">.</span> b <span class="ot">=</span> a <span class="op">&lt;*&gt;</span> (<span class="fu">read</span> <span class="op">&lt;$&gt;</span> getField b); <span class="kw">infixl</span> <span class="dv">4</span> ·<span class="op">.</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>a ← b <span class="ot">=</span> a <span class="op">&lt;$&gt;</span> getField b; <span class="kw">infixl</span> <span class="dv">4</span> ←</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>getField b <span class="ot">=</span> <span class="kw">do</span> s <span class="ot">&lt;-</span> ask; lift <span class="op">$</span> field b s</span></code></pre></div>
<p>You can see that they are basically just performing the same as
&lt;$&gt; and &lt;*&gt; except that they work with the Statement value
so we don’t have to write it out. Here it is in use in a real
project:</p>
<div class="sourceCode" id="cb13"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="ot">getOrderItem ::</span> <span class="dt">Statement</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> <span class="dt">OrderItem</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>getOrderItem <span class="ot">=</span> getFields <span class="op">$</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">OrderItem</span> ← <span class="st">&quot;id&quot;</span> · <span class="st">&quot;name&quot;</span> · <span class="st">&quot;added&quot;</span> · <span class="st">&quot;price&quot;</span> · <span class="st">&quot;quantity&quot;</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>            · <span class="st">&quot;size&quot;</span> · <span class="st">&quot;size_metric&quot;</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a><span class="ot">getOrder ::</span> <span class="dt">Statement</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> <span class="dt">Order</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>getOrder <span class="ot">=</span> getFields <span class="op">$</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Order</span> ← <span class="st">&quot;id&quot;</span> · <span class="st">&quot;name&quot;</span> · <span class="st">&quot;items&quot;</span> · <span class="st">&quot;order_total&quot;</span> · <span class="st">&quot;delivery&quot;</span></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>        · <span class="st">&quot;total&quot;</span> · <span class="st">&quot;created&quot;</span> · <span class="st">&quot;card&quot;</span> · <span class="st">&quot;billto&quot;</span> · <span class="st">&quot;shipto&quot;</span></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>        · <span class="st">&quot;level&quot;</span> · <span class="st">&quot;completed&quot;</span> · <span class="st">&quot;code&quot;</span></span></code></pre></div>
<p>Looks gorgeous, right? I figured I could do this for the ConfigFile
stuff, but thought better of it because it needs to be slightly more
flexible. The reason this abstraction works so well for HSQL is that all
the fields are extracted in the same way.</p>
<p>We can see tonnes of other uses for Control.Applicative elsewhere.
Formlets, of course, are a prime example. It also works nicely in
monadic parsers like Parsec. I expect tonnes of other uses of it
cropping up in my daily coding.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2009-02-10 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Tue, 10 Feb 2009 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Lojbot]]></title><link>https://chrisdone.com/posts/lojbot</link><guid>https://chrisdone.com/posts/lojbot</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Lojbot</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Lojbot</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>I don’t think I have blogged at all about lojbot. Lojbot, or
{lojbot}<a href="#fn1" class="footnote-ref" id="fnref1"
role="doc-noteref"><sup>1</sup></a>, is an IRC bot<a href="#fn2"
class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a>
which I have written, in Haskell, which runs on the Freenode IRC
network, idles in #lojban and #lojbot. It has some neat commands which
are useful to Lojbanists. I’m going to demonstrate some of its features
briefly.</p>
<p>I’ve recently done over lojbot’s command and tidied up the source.
It’s much better now.</p>
<p>I’ve marked this post as Lojban and Haskell, but it’s only vaguely
related to Haskell in that I wrote the bot and all the Lojban library
stuff in it. I won’t be discussing Haskell in this post.</p>
<h2 id="help">Help</h2>
<p>First of all you can invoke the help command to list all the other
commands, and you can invoke help for each of those commands. Commands,
in channels, are prefixed with things, e.g. in #lojbot, it is ?command.
In private message, however, no prefix is needed.</p>
<pre><code>&lt;chrisdone&gt; help
&lt;lojbot&gt; commands: search (query, q), valsi (v), rafsi (r), gloss
(g), definition (d), selma&#39;o (s), translate (t), selrafsi (sr), cll,
lujvo (l), grammar (gr), correct (c), more (m), help (h, commands),
info (about)</code></pre>
<p>The words in brackets are short-hands/aliases. Easier to type when
you’re rushing about trying to make a response to someone!</p>
<h2 id="lookup">Lookup</h2>
<p>Look up entries according to the word itself:</p>
<pre><code>&lt;chrisdone&gt; h v
&lt;lojbot&gt; valsi (v): lookup a gismu/cmavo/lujvo/fu&#39;ivla

&lt;chrisdone&gt; v valsi
&lt;lojbot&gt; gismu {valsi}, with rafsi {val, vla}, glossing to &quot;word&quot;: x1
is a word meaning/causing x2 in language x3; (adjective: x1 is
lexical/verbal).</code></pre>
<p>Words don’t have spaces in, so we can reasonably assume when you
enter more than one word, you want to see more than one result:</p>
<pre><code>&lt;chrisdone&gt; v ganra garna grana
&lt;lojbot&gt; gismu {ganra}, with rafsi {gan}, glossing to &quot;broad&quot;: x1 is
broad/wide in dimension x2 [2nd most significant dimension] by
standard x3.
&lt;lojbot&gt; gismu {garna}, with rafsi {gar}, glossing to &quot;rail&quot;, &quot;bar&quot;,
&quot;railing&quot;: x1 is a rail/railing/bar [tool] supporting/restraining x2,
of material x3.
&lt;lojbot&gt; gismu {grana}, with rafsi {ga&#39;a}, glossing to &quot;stick&quot;,
&quot;pole&quot;, &quot;staff&quot;, &quot;cane&quot;, &quot;rod&quot;: x1 is a rod/pole/staff/stick/cane
[shape/form] of material x2.</code></pre>
<p>If we know the start of a gismu, or something like it, we can use a
wild card to search for it. Here’s an example of words starting with
{jd}, a cluster which many find difficult to pronounce:</p>
<pre><code>&lt;chrisdone&gt; v jd*
&lt;lojbot&gt; gismu {jdari}, with rafsi {jar}, glossing to &quot;firm&quot;: x1 is
firm/hard/resistant/unyielding to force x2 under conditions x3. .. 11
more results
&lt;chrisdone&gt; more
&lt;lojbot&gt; gismu {jdice}, with rafsi {jdi}, glossing to &quot;decide&quot;: x1
(person) decides/makes decision x2 (du&#39;u) about matter x3
(event/state). .. 10 more results
&lt;chrisdone&gt; more
&lt;lojbot&gt; gismu {jdika}, glossing to &quot;decrease&quot;: x1 (experiencer)
decreases/contracts/is reduced/diminished in property/quantity x2 by
amount x3. .. 9 more results

&lt;chrisdone&gt; v xa*m*
&lt;lojbot&gt; cmavo cluster {xamoi}, of selma&#39;o MOI*, glossing to &quot;is
sixth among&quot;: quantified selbri: convert 6 to ordinal selbri; x1 is
sixth among x2 ordered by rule x3. .. 15 more results
&lt;chrisdone&gt; more
&lt;lojbot&gt; gismu {xajmi}, with rafsi {xam}, glossing to &quot;funny&quot;: x1 is
funny/comical to x2 in property/aspect x3 (nu/ka); x3 is what is funny
about x1 to x2. .. 14 more results</code></pre>
<p>Next we have the ‘rafsi’ command. Search gismu/cmavo by their
rafsi:</p>
<pre><code>&lt;chrisdone&gt; h r
&lt;lojbot&gt; rafsi (r): find gismu/cmavo with the given rafsi

&lt;chrisdone&gt; r loj ban
&lt;lojbot&gt; gismu {logji}, with rafsi {loj}, glossing to &quot;logic&quot;: x1
[rules/methods] is a logic for deducing/concluding/inferring/reasoning
to/about x2 (du&#39;u).
&lt;lojbot&gt; gismu {bangu}, with rafsi {ban, bau}, glossing to
&quot;language&quot;: x1 is a/the language/dialect used by x2 to
express/communicate x3 (si&#39;o/du&#39;u, not quote).

&lt;chrisdone&gt; r sel
&lt;lojbot&gt; cmavo {se}, of selma&#39;o SE, with rafsi {sel}, glossing to
&quot;2nd conversion&quot;: 2nd conversion; switch 1st/2nd places.</code></pre>
<p>Similar to the valsi command, it can display more than one result at
a time because it is clear that you want this. Wild cards also work with
rafsi, but I have yet to see why this is useful. I will leave it in,
though.</p>
<p>Gloss are a very helpful way to search lojban vocabulary:</p>
<pre><code>&lt;chrisdone&gt; h g
&lt;lojbot&gt; gloss (g): find valsi with the given gloss

&lt;chrisdone&gt; g cat
&lt;lojbot&gt; gismu {mlatu}, with rafsi {lat}, glossing to &quot;cat&quot;: x1 is a
cat/[puss/pussy/kitten] [feline animal] of species/breed x2;
(adjective:) x1 is feline. .. 32 more results

&lt;chrisdone&gt; g speaking
&lt;lojbot&gt; cmavo {sa&#39;e}, of selma&#39;o UI3, glossing to &quot;precisely
speaking&quot;: discursive: precisely speaking - loosely speaking. .. 2
more results

&lt;chrisdone&gt; g love
&lt;lojbot&gt; cmavo {iu}, of selma&#39;o UI1, glossing to &quot;love&quot;: attitudinal:
love - no love lost - hatred. .. 8 more results
&lt;chrisdone&gt; more
&lt;lojbot&gt; lujvo {pampe&#39;o}, with rafsi {pam, pe&#39;o}, selrafsi {prami,
pendo} (friend), glossing to &quot;boyfriend&quot;, &quot;lover&quot;, &quot;girlfriend&quot;:
pr1=pe1 is a lover of pr2=pe2. .. 7 more results
&lt;chrisdone&gt; more
&lt;lojbot&gt; lujvo {pamsrasu}, with rafsi {pam, srasu}, selrafsi {prami,
srasu} (grass), glossing to &quot;lovegrass&quot;: x1 is lovegrass of
species/variety x2. .. 6 more results</code></pre>
<p>I have demonstrated the more command a few times. It simply displays
the next result. It used to display three or four results at a time. But
it’s usually the next result you want. And if you’re listing more than a
few results, you should use a proper mass lookup tool. Also, lojbot
waits a few seconds every three messages to stop it flooding the IRC
server. Keep that in mind.</p>
<p>Indeed, wildcards work with the gloss, too:</p>
<pre><code>&lt;chrisdone&gt; g *plant*
&lt;lojbot&gt; fu&#39;ivla {akmela}, glossing to &quot;toothache plant&quot;,
&quot;paracress&quot;, &quot;spotflower&quot;: x1 is a toothache
plant/spotflower/paracress of species/variety x2. .. 7 more results
&lt;chrisdone&gt; more
&lt;lojbot&gt; lujvo {derba&#39;o}, with rafsi {der, ba&#39;o}, selrafsi {dertu,
banro} (dirt, grow), glossing to &quot;to sprout [of plant]&quot;, &quot;sprouting
object&quot;, &quot;sprout&quot;: b1 initially grows b2 beyond the soil; b1 sprouts
b2 from the ground. .. 6 more results</code></pre>
<p>The definition search is nice. It will try to give you the best
matching result first. A good match is an exact word:</p>
<pre><code>&lt;chrisdone&gt; h d
&lt;lojbot&gt; definition (d): search for valsi(s) by definition

&lt;chrisdone&gt; d dances
&lt;lojbot&gt; gismu {dansu}, glossing to &quot;dance&quot;: x1 (individual, mass)
dances to accompaniment/music/rhythm x2.</code></pre>
<p>Above we see that we have matched a single word exactly. And now, we
match a word inside the slashes:</p>
<pre><code>&lt;chrisdone&gt; d music
&lt;lojbot&gt; gismu {dansu}, glossing to &quot;dance&quot;: x1 (individual, mass)
dances to accompaniment/music/rhythm x2. .. 6 more results</code></pre>
<p>No problem.</p>
<p>Indeed, this command will try the separate words, too, to see what
comes up better, which is useful for when you want to search a few
ideas:</p>
<pre><code>&lt;chrisdone&gt; d teacher teaches
&lt;lojbot&gt; gismu {ctuca}, with rafsi {ctu}, glossing to &quot;teach&quot;: x1
teaches audience x2 ideas/methods/lore x3 (du&#39;u) about subject(s) x4
by method x5 (event).</code></pre>
<p>But what about incomplete words?</p>
<p>Let’s say I want all results relevant to teaching, I can use a wild
card:</p>
<pre><code>&lt;chrisdone&gt; d *teach*
&lt;lojbot&gt; gismu {ckule}, with rafsi {kul, cu&#39;e}, glossing to &quot;school&quot;:
x1 is school/institute/academy at x2 teaching subject(s) x3 to
audien./commun. x4 operated by x5. .. 3 more results
&lt;chrisdone&gt; more
&lt;lojbot&gt; gismu {ctuca}, with rafsi {ctu}, glossing to &quot;teach&quot;: x1
teaches audience x2 ideas/methods/lore x3 (du&#39;u) about subject(s) x4
by method x5 (event). .. 2 more results
&lt;chrisdone&gt; more
&lt;lojbot&gt; lujvo {balcu&#39;e}, with rafsi {bal, cu&#39;e}, selrafsi {banli,
ckule} (great, school), glossing to &quot;university&quot;, &quot;university site&quot;,
&quot;course&quot;, &quot;student&quot;, &quot;regents&quot;: c1 is a university at c2 teaching
subject(s) c3 to audience/community c4 operated by c5. .. 1 more
result
&lt;chrisdone&gt; more
&lt;lojbot&gt; lujvo {ctununta&#39;a}, with rafsi {ctu, nun, ta&#39;a}, selrafsi
{ctuca, nu, tavla} (teach, event abstract, talk), glossing to
&quot;lecture&quot;, &quot;lecturer&quot;: n1=c5 is a lecture / an event of verbal
teaching by t1=c1 to audience $t_2 = c_2$ about subject $t_3 = c_4$ in
language t4 with facts taught c3.</code></pre>
<p>A nice way to investigate cmavo of a particular selma’o, especially
after just viewing a cmavo entry and wondering what else there is in
that selma’o, is to use the s (for selma’o) command:</p>
<pre><code>&lt;chrisdone&gt; h s
&lt;lojbot&gt; selma&#39;o (s): list cmavo of a selma&#39;o

&lt;chrisdone&gt; s UI5
&lt;lojbot&gt; {be&#39;u}: lack, {dai}: empathy, {fu&#39;i}: easy, {ga&#39;i}: hauteur,
{ju&#39;o}: certainty, {le&#39;o}: aggressive, {ri&#39;e}: release of emotion,
{se&#39;a}: self-sufficiency, {se&#39;i}: self-oriented, {vu&#39;e}: virtue,
{zo&#39;o}: humorously .. 11 more results
&lt;chrisdone&gt; more
&lt;lojbot&gt; cmavo {be&#39;u}, of selma&#39;o UI5, glossing to &quot;lack&quot;:
attitudinal modifier: lack/need - presence/satisfaction -
satiation. .. 10 more results
&lt;chrisdone&gt; more
&lt;lojbot&gt; cmavo {dai}, of selma&#39;o UI5, glossing to &quot;empathy&quot;:
attitudinal modifier: marks empathetic use of preceding attitudinal;
shows another&#39;s feelings. .. 9 more results</code></pre>
<p>The translation command uses jbofihe:</p>
<pre><code>&lt;chrisdone&gt; h t
&lt;lojbot&gt; translate (t): translate some lojban with jbofihe -x

&lt;chrisdone&gt; t coi ro do
&lt;lojbot&gt; (^coi /greetings/ ro /every/ /(of)/ do /you/^)
&lt;chrisdone&gt; t mi ui nelci la djan
&lt;lojbot&gt; [([nelci1 (like-r(s)):] mi /I, me/ .ui /{happiness..}/)
/[is, does]/ &lt;&lt;nelci /lik-ing/&gt;&gt; ([nelci2 (liked thing(s)):] la / /
djan. /[NAME]/)]
&lt;chrisdone&gt; t mi nelci la djan iu ru&#39;e
&lt;lojbot&gt; [([nelci1 (like-r(s)):] mi /I, me/) /[is, does]/ &lt;&lt;nelci
/lik-ing/&gt;&gt; ([nelci2 (liked thing(s)):] la / / djan. /[NAME]/ .iu ru&#39;e
/{weak love..}/)]</code></pre>
<p>Unfortunately it doesn’t yet give informative error messages:</p>
<pre><code>&lt;chrisdone&gt; t do mo do mo
&lt;lojbot&gt; parse error</code></pre>
<p>But I will do that some time.</p>
<p>The selrafsi command gives you the lujvo which the given selrafsi is
in:</p>
<pre><code>&lt;chrisdone&gt; h sr
&lt;lojbot&gt; selrafsi (sr): find all lujvo with given selrafsi

&lt;chrisdone&gt; sr gleki
&lt;lojbot&gt; bebgei (giddy), gekpanpi (blissful), tcegei (overjoyed) .. 3
more results
&lt;chrisdone&gt; more
&lt;lojbot&gt; lujvo {bebgei}, with rafsi {beb, gei}, selrafsi {bebna,
gleki} (foolish, happy), glossing to &quot;giddy&quot;: g1 is giddy about
g2. .. 2 more results
&lt;chrisdone&gt; more
&lt;lojbot&gt; lujvo {gekpanpi}, with rafsi {gek, panpi}, selrafsi {gleki,
panpi} (happy, peace), glossing to &quot;blissful&quot;: g1=p1 is blissful about
g2=p2 (event/state). .. 1 more result
&lt;chrisdone&gt; more
&lt;lojbot&gt; lujvo {tcegei}, with rafsi {tce, gei}, selrafsi {mutce,
gleki} (much, happy), glossing to &quot;overjoyed&quot;, &quot;delighted&quot;,
&quot;ecstatic&quot;, &quot;delightful&quot;: g1 is delighted/ecstatic/overjoyed about g2
(event/state).

&lt;chrisdone&gt; sr gletu
&lt;lojbot&gt; cpanygle (ride), datpavycinglepre (straight), glebre (heat),
glefi&#39;a (pornography), glepe&#39;o (sexual partner), gleve&#39;u (prostitute),
mitcinglepre (MOTSS), mitpavycinglepre (homo), nu&#39;ogle (virgin),
pavycinglepre (non-bisexual), relcinglepre (bisexual) .. 11 more
results</code></pre>
<p>The cll command looks up, using Google, results from The Lojban
Reference Grammar:</p>
<pre><code>&lt;chrisdone&gt; h cll
&lt;lojbot&gt; cll: lookup something in the lojban reference grammar

&lt;chrisdone&gt; cll ko&#39;a
&lt;lojbot&gt; http://jbotcan.org/cllc/c7/s5.html : Brevity Is The Soul Of
Language: Pro-sumti And Pro-bridi - The ...There are ten cmavo in the
ko&#39;a-series, and they may be assigned freely to any sumti
whatsoever. The English word ``he&#39;&#39; can refer only to males, ... .. 9
more results</code></pre>
<p>valid simply tells us that some grammar is valid.</p>
<pre><code>&lt;chrisdone&gt; h c
&lt;lojbot&gt; correct (c): camxes test for validity

&lt;lojbot&gt; valid: coi ro do
&lt;chrisdone&gt; correct coi ro d
&lt;lojbot&gt; not valid: coi ro d</code></pre>
<p>And finally, lujvo makes a lujvo for you:</p>
<pre><code>&lt;chrisdone&gt; h l
&lt;lojbot&gt; lujvo (l): construct lujvos from selrafsis and rate them

&lt;chrisdone&gt; lujvo xamgu dansu
&lt;lojbot&gt; xagdansu (7937), xaurdansu (9006)</code></pre>
<p>Ah, I forgot the search command. It is a combination of the other
look up commands, showing results of the highest priority first. It
goes:</p>
<pre><code>valsi &gt; rafsi &gt; gloss &gt; definition</code></pre>
<p>Thus, {bau} matches a rafsi, which means no valsi entries
matched:</p>
<pre><code>&lt;chrisdone&gt; q bau
&lt;lojbot&gt; cmavo {bau}, of selma&#39;o BAI, glossing to &quot;in language&quot;:
bangu modal, 1st place in language ... .. 1 more result
{bridi} matches a valsi, and 62 more results, meaning other things like gloss and definition results matched against &quot;bridi&quot;, but they are less precise, and so are listed later:

&lt;chrisdone&gt; q bridi
&lt;lojbot&gt; gismu {bridi}, with rafsi {bri}, glossing to &quot;predicate&quot;: x1
(text) is a predicate relationship with relation x2 among arguments
(sequence/set) x3. .. 62 more results
&lt;chrisdone&gt; more
&lt;lojbot&gt; lujvo {brirebla}, with rafsi {bri, rebla}, selrafsi {bridi,
rebla} (predicate, tail), glossing to &quot;bridi-tail&quot;: x1 is a bridi-tail
of predicate relationship x2 with relation x3 among arguments
(sequence/set) x4 . .. 61 more results</code></pre>
<p>Here we have a gloss match, meaning no valsi or rafsi entries
matched.</p>
<pre><code>&lt;chrisdone&gt; q precisely speaking
&lt;lojbot&gt; cmavo {sa&#39;e}, of selma&#39;o UI3, glossing to &quot;precisely
speaking&quot;: discursive: precisely speaking - loosely speaking. .. 4
more results</code></pre>
<p>And here a definition match, because “dances” doesn’t match any of
the valsi, rafsi or gloss entries.</p>
<pre><code>&lt;chrisdone&gt; q dances
&lt;lojbot&gt; gismu {dansu}, glossing to &quot;dance&quot;: x1 (individual, mass)
dances to accompaniment/music/rhythm x2.</code></pre>
<p>I might recommend this to newbies, or people who prefer to stick to
one mildly clever command than use different ones. But you get more
power using the individual ones; so I’d only recommend this for
valsi/rafsi/gloss lookup of singular words.</p>
<h2 id="mlismu">Mlismu</h2>
<p>Lojbot has a mlismu<a href="#fn3" class="footnote-ref" id="fnref3"
role="doc-noteref"><sup>3</sup></a> feature, invoked by COI or DOI
cmavo<a href="#fn4" class="footnote-ref" id="fnref4"
role="doc-noteref"><sup>4</sup></a>, which makes grammatically and
ontologically valid utterances, which may or may not have relevance to
what was said to lojbot. Mlismu generates these utterances using fatci
(facts), which are very simple statements such as that “all humans are
persons”.</p>
<pre><code>&lt;chrisdone&gt; coi lojbot pei
&lt;lojbot&gt; ckule lo va&#39;i te nicte .o&#39;e be le se murse be&#39;o fo mi le
prenu</code></pre>
<p>Some amusing instances of lojbot’s bantering:</p>
<p>Discussing bananas and religion:</p>
<pre><code>19:46 &lt; chrisdone&gt; ma grute doi lojbot
19:46 &lt; lojbot&gt; re&#39;e lo se lebna be mi&#39;o bei ko be&#39;o .u&#39;a fo&#39;o cu grute
19:46 &lt; chrisdone&gt; zo re&#39;e u&#39;i
19:48 &lt; timonator&gt; lijda la lojbot lo nu se lebna fi lo badna</code></pre>
<p>Roughly translated as:</p>
<pre><code>19:46 &lt; chrisdone&gt; What is a fruit, O, Lojbot?
19:46 &lt; lojbot&gt; [Religious feeling] YOU, be the one whose fruit we
sieze! [Gain]
19:46 &lt; chrisdone&gt; ‘Religious’, haha.
19:48 &lt; timonator&gt; Lojbot believes in a religion with practices of
taking bananas from people.</code></pre>
<p>(Go to the xamselsku page)</p>
<p>It’s surprisingly coherent, sometimes.</p>
<h2 id="source">Source</h2>
<p>Lojbot is written in Haskell; you can view its complete source code
or pull it with git:</p>
<pre><code>git clone git://github.com/chrisdone/lojbot.git</code></pre>
<p>Okay, so I said I wouldn’t discuss Haskell, but I wrote a neat wild
card library which Lojbot uses for the above described wild card stuff.
It’s pretty concise, I think. The pattern matching makes it easy to
analyse the state of the function. I’m pretty sure it’s essentially a
state machine. I’ve never written a wild card library. A regular
expression library would be cool to write some time. I believe there are
exceedingly fast algorithms for doing wild cards which I have not used
in this simple code. Maybe I’ll upgrade it some time and blog about
it.</p>
<h2 id="bugs-feedback">Bugs / feedback</h2>
<p>Please add any ideas/bugs/feedback you want to the lojbot lighthouse
page. That way, I will actually get them done if they’re recorded
somewhere.</p>
<p>Please join the #lojbot channel to discuss and test the bot.</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>We typically use { and } to quote
Lojban text, in English.<a href="#fnref1" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p>“An IRC bot is a set of scripts or an
independent program that connects to Internet Relay Chat as a client,
and so appears to other IRC users as another user. It differs from a
regular client in that instead of providing interactive access to IRC
for a human user, it performs automated functions.” — IRC bot at
Wikipedia<a href="#fnref2" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn3" role="doc-endnote"><p>Mlismu is a program written by Adam
Lopresto which “[Generates] semantically near-valid grammatical lojban
nonsense.” — mlismu’s web page<a href="#fnref3" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn4" role="doc-endnote"><p>That is, words which are vocatives,
such as {doi djan}, {ki’e djan}, {je’e djan}, etc. for “O, John”,
“Thanks, John”, “Roger, John”, etc.<a href="#fnref4"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2008-12-18 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Thu, 18 Dec 2008 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Kibro on Shared Hosting]]></title><link>https://chrisdone.com/posts/kibro-shared-hosting</link><guid>https://chrisdone.com/posts/kibro-shared-hosting</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Kibro on Shared Hosting</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Kibro on Shared Hosting</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>Right now I am doing work with PHP on a shared host with MySQL.
Wasn’t my choice, of course. Maybe I can use Haskell and MySQL for this
application and future ones. I’ve already tested compiling a Haskell web
application on this specific hosting server, and it works fine.</p>
<p>This host is pretty limited. I can only use provided configuration
interfaces. I had to use PHP to launch the Haskell process. Provided I
can keep a process open on the server (a cron job should do it), I can
probably use PHP as a kind of proxy to the FastCGI process.</p>
<p>The idea of using Haskell for my work sounds much more pleasant and
exciting than PHP. I really wish this PHP version (5.2.6) had closures
and namespaces. Yeah, it has those features now1 2, in newer versions
that I can’t use, but only tacked on, when they should’ve been there
from the start. Oh well.</p>
<p>Will post more about my
Haskell-on-horrid-but-necessary-shared-hosting adventures.</p>
<h3 id="hsql-mysql">HSQL MySQL</h3>
<p>On a fairly related note, MySQL with Database.HSQL.MySQL, is fairly
easy. Here is a basic example, which I tried:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>out <span class="ot">&lt;-</span> liftIO <span class="op">$</span> handleSql (<span class="fu">return</span> <span class="op">.</span> <span class="dt">Left</span> <span class="op">.</span> <span class="fu">show</span>) <span class="op">$</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>                      <span class="kw">do</span> conn <span class="ot">&lt;-</span> connect <span class="st">&quot;host&quot;</span> <span class="st">&quot;db&quot;</span> <span class="st">&quot;username&quot;</span> <span class="st">&quot;password&quot;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>                         statement <span class="ot">&lt;-</span> query conn <span class="st">&quot;SELECT * FROM blah&quot;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>                         rows <span class="ot">&lt;-</span> collectRows getId statement</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>                         closeStatement statement</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>                         disconnect conn</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>                         <span class="fu">return</span> <span class="op">$</span> <span class="dt">Right</span> rows</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>output <span class="op">$</span> <span class="fu">show</span> out</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">where</span><span class="ot"> getId ::</span> <span class="dt">Statement</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> <span class="dt">String</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>          getId <span class="ot">=</span> <span class="fu">flip</span> getFieldValue <span class="st">&quot;somefield&quot;</span></span></code></pre></div>
<p>This will return either (1) all the fields ‘somefield’ from table
‘blah’ or (2) an error message.</p>
<p>Obviously one can stick this connection in a Reader monad. There’s
not really much else to check out for HSQL. I suppose that’s the point.
All the work should be done in the query, anyway. Check out the rest of
the documentation for more information.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2008-12-11 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Thu, 11 Dec 2008 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Kibro: Haskell, Lighttpd and FastCGI]]></title><link>https://chrisdone.com/posts/kibro-lighttpd-fastcgi</link><guid>https://chrisdone.com/posts/kibro-lighttpd-fastcgi</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Kibro: Haskell, Lighttpd and FastCGI</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Kibro: Haskell, Lighttpd and FastCGI</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>This is a follow-up from the previous post about Haskell, lighttpd
and fastcgi. Hence forth I will call this kind of project an fcgi
site.</p>
<p>I have come up with a simple framework with consists of a library
called “Kibro” and an executable called “kibro”. Both come in one
package.</p>
<p>I intended for it to make getting an fcgi site up and running very
easily. I found myself previously copying over configuration files and
also copying library functions. Now I have started work on putting that
into one package, Kibro. The point of Kibro is that a web site is a
directory containing configuration, source and static web files. It is
contained and isolated.</p>
<p>Here is an example of what works:</p>
<p>I create the project:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>chris<span class="op">@</span>chrisdesktop<span class="op">:~$</span> kibro new example</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Creating</span> project example <span class="op">...</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="dt">Creating</span> directory structure <span class="op">...</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="dt">Creating</span> example<span class="op">/</span>app<span class="op">/</span>lighttpd <span class="op">...</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="dt">Creating</span> example<span class="op">/</span>app<span class="op">/</span>fastcgi <span class="op">...</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="dt">Creating</span> example<span class="op">/</span>app<span class="op">/</span>memcached <span class="op">...</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="dt">Creating</span> example<span class="op">/</span>db <span class="op">...</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="dt">Creating</span> example<span class="op">/</span>public <span class="op">...</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="dt">Creating</span> example<span class="op">/</span>src <span class="op">...</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="dt">Writing</span> example<span class="op">/</span>app<span class="op">/</span>lighttpd<span class="op">/</span>lighttpd<span class="op">.</span>conf <span class="op">...</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="dt">Writing</span> example<span class="op">/</span>src<span class="op">/</span>Main.hs <span class="op">...</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a><span class="dt">Writing</span> example<span class="op">/</span>example<span class="op">.</span>kibro <span class="op">...</span></span></code></pre></div>
<p>Done. I go into the directory and start it.</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>chris<span class="op">@</span>chrisdesktop<span class="op">:~$</span> cd example<span class="op">/</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>chris<span class="op">@</span>chrisdesktop<span class="op">:~/</span>example<span class="op">$</span> kibro start</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="dt">Not</span> built<span class="op">.</span> <span class="dt">Building</span> <span class="op">...</span></span></code></pre></div>
<p>The project hasn’t been built yet, so it builds it.</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>ghc <span class="co">--make src/Main.hs -o public/example.fcgi -threaded ...</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>[<span class="dv">1</span> <span class="kw">of</span> <span class="dv">1</span>] <span class="dt">Compiling</span> <span class="dt">Main</span>             ( src<span class="op">/</span>Main.hs, src<span class="op">/</span>Main.o )</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="dt">Linking</span> public<span class="op">/</span>example<span class="op">.</span>fcgi <span class="op">...</span></span></code></pre></div>
<p>Once built, Lighttpd is started under your username, with access to
this directory, with document root “public” and configured to work with
fastcgi.</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Starting</span> lighttpd <span class="op">...</span></span></code></pre></div>
<p>Fastcgi follows, executing it in the background, as your username,
saving the processID to a file so that we can stop it later.</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Starting</span> fastcgi process <span class="op">...</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>spawn<span class="op">-</span>fcgi <span class="op">-</span>f public<span class="op">/</span>example<span class="op">.</span>fcgi <span class="op">-</span>s <span class="op">/</span>home<span class="op">/</span>chris<span class="op">/</span>example<span class="op">/</span>app<span class="op">/</span>fastcgi<span class="op">/</span>example<span class="op">.</span>sock <span class="op">-</span><span class="dt">P</span> app<span class="op">/</span>fastcgi<span class="op">/</span>fastcgi<span class="op">.</span>pid <span class="op">...</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>spawn<span class="op">-</span>fcgi<span class="op">.</span>c<span class="op">.</span><span class="dv">197</span><span class="op">:</span> child spawned successfully<span class="op">:</span> <span class="dt">PID</span><span class="op">:</span> <span class="dv">25688</span></span></code></pre></div>
<p>That’s it, I’m afraid! Now go to your browser and go to
http://127.0.0.1:3000. Port 3000 is the default port, and I am going to
add a kibro configure command with which one can set a different port
(or you can just edit lighttpd manually).</p>
<p>BTW, Main.hs looks like this at the start of a new project:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">module</span> <span class="dt">Main</span> <span class="kw">where</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Kibro</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Kibro.DB.Sqlite3</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> kibro (db <span class="st">&quot;&quot;</span>) pages</span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>pages <span class="ot">=</span> [(<span class="st">&quot;.&quot;</span>, example)]</span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>example <span class="ot">=</span> output <span class="st">&quot;Change me! :-)&quot;</span></span></code></pre></div>
<p>This file is to be edited by you. The kibro function taking a
function which returns an SQL Connection, and a list of pages, and it
starts the fastcgi process. pages is an assoc list of regular
expressions to match on URLs and page functions. example is a page
function.</p>
<p>Something else I’ve got is kibro refresh, which rebuilds your project
and restarts the fastcgi process. No need to restart lighttpd.</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>chris<span class="op">@</span>chrisdesktop<span class="op">:~/</span>example<span class="op">$</span> kibro refresh</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Rebuilding</span> <span class="op">...</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="dt">Building</span> example <span class="op">...</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>ghc <span class="co">--make src/Main.hs -o public/example.fcgi -threaded ...</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>[<span class="dv">1</span> <span class="kw">of</span> <span class="dv">1</span>] <span class="dt">Compiling</span> <span class="dt">Main</span>             ( src<span class="op">/</span>Main.hs, src<span class="op">/</span>Main.o )</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a><span class="dt">Linking</span> public<span class="op">/</span>example<span class="op">.</span>fcgi <span class="op">...</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a><span class="dt">Restarting</span> fastcgi <span class="op">...</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a><span class="dt">Stopping</span> fastcgi <span class="op">...</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a><span class="dt">Starting</span> fastcgi process <span class="op">...</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>spawn<span class="op">-</span>fcgi <span class="op">-</span>f public<span class="op">/</span>example<span class="op">.</span>fcgi <span class="op">-</span>s <span class="op">/</span>home<span class="op">/</span>chris<span class="op">/</span>example<span class="op">/</span>app<span class="op">/</span>fastcgi<span class="op">/</span>example<span class="op">.</span>sock <span class="op">-</span><span class="dt">P</span> app<span class="op">/</span>fastcgi<span class="op">/</span>fastcgi<span class="op">.</span>pid <span class="op">...</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a>spawn<span class="op">-</span>fcgi<span class="op">.</span>c<span class="op">.</span><span class="dv">197</span><span class="op">:</span> child spawned successfully<span class="op">:</span> <span class="dt">PID</span><span class="op">:</span> <span class="dv">25737</span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a>chris<span class="op">@</span>chrisdesktop<span class="op">:~/</span>example<span class="op">$</span></span></code></pre></div>
<p>This will be very useful for updating your web pages’ code.</p>
<p>Let me show an example with a bit of session state.</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">module</span> <span class="dt">Main</span> <span class="kw">where</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Kibro</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Kibro.DB.Sqlite3</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Monad</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Maybe</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> kibro (db <span class="st">&quot;&quot;</span>) pages</span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>pages <span class="ot">=</span> [(<span class="st">&quot;^/$&quot;</span>,<span class="fu">index</span>),(<span class="st">&quot;/inc&quot;</span>, inc),(<span class="st">&quot;/adder&quot;</span>,adder)]</span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a><span class="fu">index</span> <span class="ot">=</span> outputHtml <span class="op">&lt;&lt;$</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a>  p <span class="op">&lt;&lt;</span> hotlink <span class="st">&quot;/inc&quot;</span> <span class="op">&lt;&lt;</span> <span class="st">&quot;incrementer&quot;</span></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a>  <span class="op">+++</span></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a>  p <span class="op">&lt;&lt;</span> hotlink <span class="st">&quot;/adder&quot;</span> <span class="op">&lt;&lt;</span> <span class="st">&quot;adder&quot;</span></span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true" tabindex="-1"></a>inc <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb8-19"><a href="#cb8-19" aria-hidden="true" tabindex="-1"></a>  n <span class="ot">&lt;-</span> readSessDef <span class="st">&quot;n&quot;</span> <span class="dv">0</span></span>
<span id="cb8-20"><a href="#cb8-20" aria-hidden="true" tabindex="-1"></a>  writeSess <span class="st">&quot;n&quot;</span> (n<span class="op">+</span><span class="dv">1</span>)</span>
<span id="cb8-21"><a href="#cb8-21" aria-hidden="true" tabindex="-1"></a>  outputHtml <span class="op">$</span> p <span class="op">&lt;&lt;</span> (<span class="fu">show</span> n)</span>
<span id="cb8-22"><a href="#cb8-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-23"><a href="#cb8-23" aria-hidden="true" tabindex="-1"></a>adder <span class="ot">=</span> <span class="kw">do</span> n <span class="ot">&lt;-</span> readInputDef <span class="st">&quot;a&quot;</span> <span class="dv">0</span></span>
<span id="cb8-24"><a href="#cb8-24" aria-hidden="true" tabindex="-1"></a>           v <span class="ot">&lt;-</span> readSessDef <span class="st">&quot;a&quot;</span> <span class="dv">0</span></span>
<span id="cb8-25"><a href="#cb8-25" aria-hidden="true" tabindex="-1"></a>           writeSess <span class="st">&quot;a&quot;</span> <span class="op">$</span> v<span class="op">+</span>n</span>
<span id="cb8-26"><a href="#cb8-26" aria-hidden="true" tabindex="-1"></a>           outputHtml <span class="op">$</span> p <span class="op">&lt;&lt;</span> (<span class="fu">show</span> (v<span class="op">+</span>n)) <span class="op">+++</span> theform</span>
<span id="cb8-27"><a href="#cb8-27" aria-hidden="true" tabindex="-1"></a>    <span class="kw">where</span></span>
<span id="cb8-28"><a href="#cb8-28" aria-hidden="true" tabindex="-1"></a>      theform <span class="ot">=</span> form <span class="op">!</span> [method <span class="st">&quot;post&quot;</span>] <span class="op">&lt;&lt;$</span></span>
<span id="cb8-29"><a href="#cb8-29" aria-hidden="true" tabindex="-1"></a>                p <span class="op">&lt;&lt;</span> <span class="st">&quot;Enter a number to add:&quot;</span> <span class="op">+++</span> input <span class="op">!</span> [name <span class="st">&quot;a&quot;</span>]</span></code></pre></div>
<p>That’s great. Now let’s refresh:</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>chris<span class="op">@</span>chrisdesktop<span class="op">:~/</span>example<span class="op">$</span> kibro refresh</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Rebuilding</span> <span class="op">...</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="dt">Building</span> example <span class="op">...</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>ghc <span class="co">--make src/Main.hs -o public/example.fcgi -threaded ...</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>[<span class="dv">1</span> <span class="kw">of</span> <span class="dv">1</span>] <span class="dt">Compiling</span> <span class="dt">Main</span>             ( src<span class="op">/</span>Main.hs, src<span class="op">/</span>Main.o )</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a><span class="dt">Linking</span> public<span class="op">/</span>example<span class="op">.</span>fcgi <span class="op">...</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a><span class="dt">Restarting</span> fastcgi <span class="op">...</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a><span class="dt">Stopping</span> fastcgi <span class="op">...</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a><span class="dt">Starting</span> fastcgi process <span class="op">...</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>spawn<span class="op">-</span>fcgi <span class="op">-</span>f public<span class="op">/</span>example<span class="op">.</span>fcgi <span class="op">-</span>s <span class="op">/</span>home<span class="op">/</span>chris<span class="op">/</span>example<span class="op">/</span>app<span class="op">/</span>fastcgi<span class="op">/</span>example<span class="op">.</span>sock <span class="op">-</span><span class="dt">P</span> app<span class="op">/</span>fastcgi<span class="op">/</span>fastcgi<span class="op">.</span>pid <span class="op">...</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a>spawn<span class="op">-</span>fcgi<span class="op">.</span>c<span class="op">.</span><span class="dv">197</span><span class="op">:</span> child spawned successfully<span class="op">:</span> <span class="dt">PID</span><span class="op">:</span> <span class="dv">30907</span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a>chris<span class="op">@</span>chrisdesktop<span class="op">:~/</span>example<span class="op">$</span></span></code></pre></div>
<p>You can probably guess what this does.</p>
<p>I think this is a nice-ish way to write web pages. Another is using
stringtemplate, which I will be incorporating in the future. Finally,
there is XSLT; equally doable. I can’t really think of other ways in
which to write web page content other than XSLT, templates and
code-as-data higher order functions or macros. I’d be interested in
hearing about other ways.</p>
<p>At the moment, session state is stored in MVars as simple Map values,
but it won’t take much changes to restructure the session code to use
memcached. Why memcached? Because storing the session state in a
separate process means fastcgi can restart, but your session state isn’t
lost. Granted, alternatively one could simply write to a database and
then session state would be safe! Well, it would be pointless. A session
state should time out after a while of no activity. There is no point
writing it to a file. I’d wage memcached is faster, but I haven’t tested
it.</p>
<p>So with this setup of external session state storage, it means
updating web page code is easy, similar to the “dynamic”ness of
interpreted web languages.</p>
<p>I would like to add a selenium interface at somepoint, e.g. for the
kibro refresh command.</p>
<p>Anyway, I’m trailing off into details.</p>
<p>Needs way more work before I’ll be showing off source code. It’s on
Hackage, so you can look at it, or the darcs repo, but I wouldn’t bother
trying it yet. I’m just giving a progress report. It’s therapeutic.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2008-11-14 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Fri, 14 Nov 2008 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Haskell Formlets: Composable web form construction and validation]]></title><link>https://chrisdone.com/posts/haskell-formlets</link><guid>https://chrisdone.com/posts/haskell-formlets</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Haskell Formlets: Composable web form construction and
validation</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Haskell Formlets: Composable web form construction and
validation</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p><strong>Note</strong>: This is an archive of an old 2008 post from an
old blog.</p>
<p>I think we all saw formlets some months ago when Chris Eidhof posted
a blog entry about Formlets in Haskell. For a reminder, a brief
description follows. Then I will jump straight into examples.</p>
<h2 id="description-of-a-formlet">Description of a formlet</h2>
<p>A formlet contains information about how to render itself in mark-up
language, whether values provided to it are valid, what error to show
when those values are invalid, or, if valid, the formlet returns a new
value. Perhaps as a loose model, we can enumerate these as:</p>
<ul>
<li>Presentation</li>
<li>Validation</li>
<li>Parsing</li>
<li>Failure</li>
<li>Success</li>
</ul>
<p>It is, therefore, a composition of five properties present in web
forms. I contend that keeping these properties specified in the same
place and therefore automatically consistent with eachother, is
something we want, as developers.</p>
<p>A formlet is self-contained and composable. By ‘self-contained’, this
means that all the data needed for a formlet is contained inside its
definition. By ‘composable’, this means that formlets can be used
together without influencing eachother, and that I can make new, valid,
formlets out of existing ones. Composability is something which Haskell
is exceedingly good at<a href="#fn1" class="footnote-ref" id="fnref1"
role="doc-noteref"><sup>1</sup></a>, as we will see. The Haskell
Formlets library provides us, very concisely, with a way to use
formlets. This entry discusses some examples of this library. I hope to
convince the reader that this is an excellent way to develop web
forms.</p>
<h2 id="example-1-a-user-registration-form">Example 1: A user
registration form</h2>
<p>Suppose I have a formlet that is a user registration form, called
register. The registration form takes a username and a password, and the
password must be entered twice, in two fields, for confirmation. I might
compose this formlet from two other formlets; user and pass. The user
formlet may simply display a text field, and checks that the field is
not empty. The pass formlet, on the other hand, ought to be composed of
two password entry formlets. Each of those sub-formlets will perform the
task of checking that the password is valid (such as ensuring that it is
greater than six characters in length), and the password formlet merely
needs to check that each of the values returned from these two are
equal.</p>
<p>Let us convince ourselves that we can indeed express this, using
Haskell.</p>
<p>Before defining the formlets, we’ll define a type to be returned:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Registration</span> <span class="ot">=</span> <span class="dt">Registration</span> {<span class="ot"> username ::</span> <span class="dt">String</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>                                 ,<span class="ot"> password ::</span> <span class="dt">String</span> }</span></code></pre></div>
<h3 id="description-of-a-simple-validating-formlet">Description of a
simple validating formlet</h3>
<p>Firstly, for the register formlet I have added type annotations.
Types in Haskell help us understand the behaviour of our code, and here
is a good example. It is a form which displays mark-up of type Html
(provided by Text.XHtml.Strict), it is intended to be ran in some monad
m (or instance of Applicative), and returns a Registration value.</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ot">register ::</span> (<span class="dt">Applicative</span> m,<span class="dt">Monad</span> m) <span class="ot">=&gt;</span> <span class="dt">Form</span> <span class="dt">Html</span> m <span class="dt">Registration</span></span></code></pre></div>
<p>Next, we can instantly see that register is composed of user and
pass.</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>register <span class="ot">=</span> <span class="dt">Registration</span> <span class="op">&lt;$&gt;</span> user <span class="op">&lt;*&gt;</span> pass</span></code></pre></div>
<p>But what are user and pass? I will explain user; the meaning of pass
can then be inferred. We’ve defined user as displaying a text input box,
with no value i.e. Nothing. The value provided from this form element is
then checked against what is called a Failing<a href="#fn2"
class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a>,
which ensures that a value is valid, or displays an error.</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ot">user ::</span> (<span class="dt">Applicative</span> m,<span class="dt">Monad</span> m) <span class="ot">=&gt;</span> <span class="dt">Form</span> <span class="dt">Html</span> m <span class="dt">String</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>user <span class="ot">=</span> F.input <span class="dt">Nothing</span> <span class="ot">`F.check`</span> F.ensure valid <span class="fu">error</span> <span class="kw">where</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>    valid <span class="ot">=</span> (<span class="op">&gt;=</span><span class="dv">3</span>)<span class="op">.</span> <span class="fu">length</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>    <span class="fu">error</span> <span class="ot">=</span> <span class="st">&quot;Username must be three characters or longer.&quot;</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a><span class="ot">pass ::</span> (<span class="dt">Applicative</span> m,<span class="dt">Monad</span> m) <span class="ot">=&gt;</span> <span class="dt">Form</span> <span class="dt">Html</span> m <span class="dt">String</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>pass <span class="ot">=</span> F.password <span class="dt">Nothing</span> <span class="ot">`F.check`</span> F.ensure valid <span class="fu">error</span> <span class="kw">where</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>    valid <span class="ot">=</span> (<span class="op">&gt;=</span><span class="dv">6</span>)<span class="op">.</span> <span class="fu">length</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>    <span class="fu">error</span> <span class="ot">=</span> <span class="st">&quot;Password must be six characters or longer.&quot;</span></span></code></pre></div>
<p>We can study ensure’s type briefly:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="ot">ensure ::</span> <span class="dt">Show</span> a <span class="ot">=&gt;</span> (a <span class="ot">-&gt;</span> <span class="dt">Bool</span>) <span class="ot">-&gt;</span> <span class="dt">String</span> <span class="ot">-&gt;</span> a <span class="ot">-&gt;</span> <span class="dt">Failing</span> a</span></code></pre></div>
<p>It takes a validating function (e.g. valid), an error message, and a
value to validate. It either returns a Failure with the error message,
or a Success with the value.</p>
<p>Now, the type of check should make sense to us, and this is very
lovely:</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="ot">check ::</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> <span class="dt">Form</span> xml m a <span class="ot">-&gt;</span> (a <span class="ot">-&gt;</span> <span class="dt">Failing</span> b) <span class="ot">-&gt;</span> <span class="dt">Form</span> xml m b</span></code></pre></div>
<p>We can see that it takes a formlet returning a, it takes a function
which validates a and returns b, finally producing a formlet which
returns b. What we have, now, is a function which wraps a validation
around a formlet, producing a new formlet.</p>
<h3 id="correction-of-the-registration-formlet">Correction of the
registration formlet</h3>
<p>Of course, the definition of pass is insufficient. It needs to
display two fields, and check them both, and ensure that their values
are equal. Let us correct this by defining a new formlet, passConfirmed.
The name means that this password has been confirmed by the user, by
their entering twice. Here is the definition<a href="#fn3"
class="footnote-ref" id="fnref3"
role="doc-noteref"><sup>3</sup></a>:</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ot">passConfirmed ::</span> (<span class="dt">Applicative</span> m,<span class="dt">Monad</span> m) <span class="ot">=&gt;</span> <span class="dt">Form</span> <span class="dt">Html</span> m <span class="dt">String</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>passConfirmed <span class="ot">=</span> <span class="fu">fst</span> <span class="op">&lt;$&gt;</span> (passwords <span class="ot">`F.check`</span> F.ensure equal <span class="fu">error</span>) <span class="kw">where</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>    passwords <span class="ot">=</span> (,) <span class="op">&lt;$&gt;</span> pass <span class="op">&lt;*&gt;</span> pass</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>    equal (a,b) <span class="ot">=</span> a <span class="op">==</span> b</span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>    <span class="fu">error</span> <span class="ot">=</span> <span class="st">&quot;The entered passwords do not match!&quot;</span></span></code></pre></div>
<p>Let us study what has been written here, using types to help us:</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="ot">passConfirmed ::</span> (<span class="dt">Applicative</span> m,<span class="dt">Monad</span> m) <span class="ot">=&gt;</span> <span class="dt">Form</span> <span class="dt">Html</span> m <span class="dt">String</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>passConfirmed <span class="ot">=</span> <span class="fu">fst</span> <span class="op">&lt;$&gt;</span> validPasswords <span class="kw">where</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="ot">    validPasswords ::</span> (<span class="dt">Applicative</span> m,<span class="dt">Monad</span> m) <span class="ot">=&gt;</span> <span class="dt">Form</span> <span class="dt">Html</span> m (<span class="dt">String</span>,<span class="dt">String</span>)</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>    validPasswords <span class="ot">=</span> passwords <span class="ot">`F.check`</span> F.ensure equal <span class="fu">error</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a><span class="ot">    passwords ::</span> (<span class="dt">Applicative</span> m,<span class="dt">Monad</span> m) <span class="ot">=&gt;</span> <span class="dt">Form</span> <span class="dt">Html</span> m (<span class="dt">String</span>,<span class="dt">String</span>)</span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>    passwords <span class="ot">=</span> (,) <span class="op">&lt;$&gt;</span> pass <span class="op">&lt;*&gt;</span> pass</span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a><span class="ot">    equal ::</span> (<span class="dt">String</span>,<span class="dt">String</span>) <span class="ot">-&gt;</span> <span class="dt">Bool</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a>    equal (a,b) <span class="ot">=</span> a <span class="op">==</span> b</span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a>    <span class="fu">error</span> <span class="ot">=</span> <span class="st">&quot;The entered passwords do not match!&quot;</span></span></code></pre></div>
<p>The validPasswords is what could be described as a wrapper around
passwords, which validates the values, and simply returns them if valid
(i.e. equal). passwords simply takes two valid passwords, and puts them
in a tuple.</p>
<p>Here we must recognise something special! Composability, ladies and
gentlemen! Our passConfirmed formlet does not have to care about whether
the passwords are six characters or longer, because the pass formlets
have done this for us!</p>
<p>We can now go back to our register formlet and update the code:</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="ot">register ::</span> (<span class="dt">Applicative</span> m,<span class="dt">Monad</span> m) <span class="ot">=&gt;</span> <span class="dt">Form</span> <span class="dt">Html</span> m <span class="dt">Registration</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>register <span class="ot">=</span> <span class="dt">Registration</span> <span class="op">&lt;$&gt;</span> user <span class="op">&lt;*&gt;</span> passConfirmed</span></code></pre></div>
<h3 id="adding-labels-wrapping-mark-up">Adding labels: wrapping
mark-up</h3>
<p>Right now, despite being very lovely, the display of our widgets
would be less than presentable. There are no labels on the form inputs!
Neither the user nor the pass are labelled. They are also not
paragraphed, in the mark-up. Therefore let us write a function which
will take a formlet and stick a label and a paragraph around it.</p>
<div class="sourceCode" id="cb11"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>label l <span class="ot">=</span> F.plug (\xhtml <span class="ot">-&gt;</span> X.p <span class="op">&lt;&lt;</span> (X.label <span class="op">&lt;&lt;</span> (l <span class="op">++</span> <span class="st">&quot;: &quot;</span>) <span class="op">+++</span> xhtml))</span></code></pre></div>
<p>What does the plug function do? Let us study its type:</p>
<div class="sourceCode" id="cb12"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="ot">plug ::</span> (<span class="dt">Monad</span> m, <span class="dt">Plus</span> xml) <span class="ot">=&gt;</span> (xml <span class="ot">-&gt;</span> xml1) <span class="ot">-&gt;</span> <span class="dt">Form</span> xml m a <span class="ot">-&gt;</span> <span class="dt">Form</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>xml1 m a</span></code></pre></div>
<p>It’s quite simple, of course. It takes a function which transforms
some mark-up, a form, and returns a new form with the changed
mark-up.</p>
<p>Therefore our label function simply wraps some XHTML around the
existing formlet. Now, we can use it.</p>
<div class="sourceCode" id="cb13"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="ot">user ::</span> (<span class="dt">Applicative</span> m,<span class="dt">Monad</span> m) <span class="ot">=&gt;</span> <span class="dt">Form</span> <span class="dt">Html</span> m <span class="dt">String</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>user <span class="ot">=</span> input <span class="ot">`F.check`</span> F.ensure valid <span class="fu">error</span> <span class="kw">where</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>    input <span class="ot">=</span> <span class="st">&quot;Username&quot;</span> <span class="ot">`label`</span> F.input <span class="dt">Nothing</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>    valid <span class="ot">=</span> (<span class="op">&gt;=</span><span class="dv">3</span>)<span class="op">.</span> <span class="fu">length</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>    <span class="fu">error</span> <span class="ot">=</span> <span class="st">&quot;Username must be three characters or longer.&quot;</span></span></code></pre></div>
<p>We now have a proper label for the user input field. We ought to now
confirm that this is indeed the case by running our code. …Finally!</p>
<h3 id="running-a-formlet">Running a Formlet</h3>
<p>In order to run our formlet, we need to use the runFormState
function. Studying its type, we see that it takes an environment, a
prefix for the form’s element names, and the formlet itself. Finally, it
returns a tuple of the return success or failure of the form, mark-up
which ought to be displayed, and the form content type, which we are not
interested in.</p>
<div class="sourceCode" id="cb14"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="ot">runFormState ::</span> <span class="dt">Monad</span> m</span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>             <span class="ot">=&gt;</span> <span class="dt">Env</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>             <span class="ot">-&gt;</span> <span class="dt">String</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>             <span class="ot">-&gt;</span> <span class="dt">Form</span> xml m a</span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>             <span class="ot">-&gt;</span> (m (<span class="dt">Failing</span> a),m xml,<span class="dt">FormContentType</span>)</span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Env</span> <span class="ot">=</span> [(<span class="dt">String</span>, <span class="dt">Either</span> <span class="dt">String</span> <span class="dt">File</span>)]</span></code></pre></div>
<p>We are interested only in the String form of values in the
environment.</p>
<p>Let us confirm that our code outputs what has been described:</p>
<div class="sourceCode" id="cb15"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><span class="dt">Register</span><span class="op">&gt;</span> <span class="op">:</span>load <span class="st">&quot;/var/www/chrisdone/blog/db/static/Register.hs&quot;</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>[<span class="dv">1</span> <span class="kw">of</span> <span class="dv">1</span>] <span class="dt">Compiling</span> <span class="dt">Register</span> ( Register.hs, interpreted )</span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a><span class="dt">Ok</span>, modules loaded<span class="op">:</span> <span class="dt">Register</span><span class="op">.</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><span class="dt">Register</span><span class="op">&gt;</span> <span class="kw">let</span> env <span class="ot">=</span> <span class="fu">map</span> ((<span class="st">&quot;input&quot;</span><span class="op">++</span>) <span class="op">.</span> <span class="fu">show</span>) [<span class="dv">0</span><span class="op">..</span>] <span class="ot">`zip`</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>                     <span class="fu">map</span> <span class="dt">Left</span> [<span class="st">&quot;chris&quot;</span>,<span class="st">&quot;mypassword&quot;</span>,<span class="st">&quot;mypassword&quot;</span>]</span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><span class="dt">Register</span><span class="op">&gt;</span> <span class="kw">let</span> (result,xml,_) <span class="ot">=</span> runFormState env <span class="st">&quot;&quot;</span> register</span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><span class="dt">Register</span><span class="op">&gt;</span> <span class="fu">putStrLn</span> <span class="op">.</span> X.prettyHtmlFragment <span class="op">=&lt;&lt;</span> xml</span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>p<span class="op">&gt;</span></span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true" tabindex="-1"></a>   <span class="op">&lt;</span>label<span class="op">&gt;</span></span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true" tabindex="-1"></a>      <span class="dt">Username</span><span class="op">:</span></span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true" tabindex="-1"></a>   <span class="op">&lt;/</span>label<span class="op">&gt;</span></span>
<span id="cb15-12"><a href="#cb15-12" aria-hidden="true" tabindex="-1"></a>   <span class="op">&lt;</span>input <span class="kw">type</span><span class="ot">=</span><span class="st">&quot;text&quot;</span> name<span class="ot">=</span><span class="st">&quot;input0&quot;</span> <span class="fu">id</span><span class="ot">=</span><span class="st">&quot;input0&quot;</span> value<span class="ot">=</span><span class="st">&quot;chris&quot;</span> <span class="op">/&gt;</span></span>
<span id="cb15-13"><a href="#cb15-13" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;/</span>p<span class="op">&gt;</span></span>
<span id="cb15-14"><a href="#cb15-14" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>input <span class="kw">type</span><span class="ot">=</span><span class="st">&quot;password&quot;</span> name<span class="ot">=</span><span class="st">&quot;input1&quot;</span> <span class="fu">id</span><span class="ot">=</span><span class="st">&quot;input1&quot;</span> value<span class="ot">=</span><span class="st">&quot;mypassword&quot;</span> <span class="op">/&gt;</span></span>
<span id="cb15-15"><a href="#cb15-15" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>input <span class="kw">type</span><span class="ot">=</span><span class="st">&quot;password&quot;</span> name<span class="ot">=</span><span class="st">&quot;input2&quot;</span> <span class="fu">id</span><span class="ot">=</span><span class="st">&quot;input2&quot;</span> value<span class="ot">=</span><span class="st">&quot;mypassword&quot;</span> <span class="op">/&gt;</span></span>
<span id="cb15-16"><a href="#cb15-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-17"><a href="#cb15-17" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><span class="dt">Register</span><span class="op">&gt;</span></span></code></pre></div>
<p>Here we have provided runFormState with a basic environment;
providing a value for the username and passwords. The result
demonstrates that our label wrapper does indeed work as described.</p>
<p>Finally, we can add labels to our password inputs:</p>
<div class="sourceCode" id="cb16"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="ot">passConfirmed ::</span> (<span class="dt">Applicative</span> m,<span class="dt">Monad</span> m) <span class="ot">=&gt;</span> <span class="dt">Form</span> <span class="dt">Html</span> m <span class="dt">String</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>passConfirmed <span class="ot">=</span> <span class="fu">fst</span> <span class="op">&lt;$&gt;</span> passwords <span class="ot">`F.check`</span> F.ensure equal <span class="fu">error</span> <span class="kw">where</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>    passwords <span class="ot">=</span> (,) <span class="op">&lt;$&gt;</span> pass <span class="st">&quot;Password&quot;</span> <span class="op">&lt;*&gt;</span> pass <span class="st">&quot;Password (confirm)&quot;</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>    equal (a,b) <span class="ot">=</span> a <span class="op">==</span> b</span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>    <span class="fu">error</span> <span class="ot">=</span> <span class="st">&quot;The entered passwords do not match!&quot;</span></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a><span class="ot">pass ::</span> (<span class="dt">Applicative</span> m,<span class="dt">Monad</span> m) <span class="ot">=&gt;</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Form</span> <span class="dt">Html</span> m <span class="dt">String</span></span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>pass caption <span class="ot">=</span> input <span class="ot">`F.check`</span> F.ensure valid <span class="fu">error</span> <span class="kw">where</span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a>    input <span class="ot">=</span> caption <span class="ot">`label`</span> F.password <span class="dt">Nothing</span></span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a>    valid <span class="ot">=</span> (<span class="op">&gt;=</span><span class="dv">6</span>)<span class="op">.</span> <span class="fu">length</span></span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a>    <span class="fu">error</span> <span class="ot">=</span> <span class="st">&quot;Password must be six characters or longer.&quot;</span></span></code></pre></div>
<p>We have simply added an extra argument to our pass formlet which
takes an argument for what label to display next to it. Thus we have the
following output:</p>
<div class="sourceCode" id="cb17"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span><span class="op">&gt;</span> <span class="op">:</span>load <span class="st">&quot;/var/www/chrisdone/blog/db/static/Register.hs&quot;</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>[<span class="dv">1</span> <span class="kw">of</span> <span class="dv">1</span>] <span class="dt">Compiling</span> <span class="dt">Register</span> ( Register.hs, interpreted )</span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a><span class="dt">Ok</span>, modules loaded<span class="op">:</span> <span class="dt">Register</span><span class="op">.</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><span class="dt">Register</span><span class="op">&gt;</span> <span class="kw">let</span> env <span class="ot">=</span> <span class="fu">map</span> ((<span class="st">&quot;input&quot;</span><span class="op">++</span>) <span class="op">.</span> <span class="fu">show</span>) [<span class="dv">0</span><span class="op">..</span>] <span class="ot">`zip`</span></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a>                     <span class="fu">map</span> <span class="dt">Left</span> [<span class="st">&quot;chris&quot;</span>,<span class="st">&quot;mypassword&quot;</span>,<span class="st">&quot;mypassword&quot;</span>]</span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><span class="dt">Register</span><span class="op">&gt;</span> <span class="kw">let</span> (result,xml,_) <span class="ot">=</span> runFormState env <span class="st">&quot;&quot;</span> register</span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><span class="dt">Register</span><span class="op">&gt;</span> <span class="fu">putStrLn</span> <span class="op">.</span> X.prettyHtmlFragment <span class="op">=&lt;&lt;</span> xml</span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>p<span class="op">&gt;</span></span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a>   <span class="op">&lt;</span>label<span class="op">&gt;</span></span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a>      <span class="dt">Username</span><span class="op">:</span></span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a>   <span class="op">&lt;/</span>label<span class="op">&gt;</span></span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true" tabindex="-1"></a>   <span class="op">&lt;</span>input <span class="kw">type</span><span class="ot">=</span><span class="st">&quot;text&quot;</span> name<span class="ot">=</span><span class="st">&quot;input0&quot;</span> <span class="fu">id</span><span class="ot">=</span><span class="st">&quot;input0&quot;</span> value<span class="ot">=</span><span class="st">&quot;chris&quot;</span> <span class="op">/&gt;</span></span>
<span id="cb17-13"><a href="#cb17-13" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;/</span>p<span class="op">&gt;</span></span>
<span id="cb17-14"><a href="#cb17-14" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>p<span class="op">&gt;</span></span>
<span id="cb17-15"><a href="#cb17-15" aria-hidden="true" tabindex="-1"></a>   <span class="op">&lt;</span>label<span class="op">&gt;</span></span>
<span id="cb17-16"><a href="#cb17-16" aria-hidden="true" tabindex="-1"></a>      <span class="dt">Password</span><span class="op">:</span></span>
<span id="cb17-17"><a href="#cb17-17" aria-hidden="true" tabindex="-1"></a>   <span class="op">&lt;/</span>label<span class="op">&gt;</span></span>
<span id="cb17-18"><a href="#cb17-18" aria-hidden="true" tabindex="-1"></a>   <span class="op">&lt;</span>input <span class="kw">type</span><span class="ot">=</span><span class="st">&quot;password&quot;</span> name<span class="ot">=</span><span class="st">&quot;input1&quot;</span> <span class="fu">id</span><span class="ot">=</span><span class="st">&quot;input1&quot;</span> value<span class="ot">=</span><span class="st">&quot;mypassword&quot;</span> <span class="op">/&gt;</span></span>
<span id="cb17-19"><a href="#cb17-19" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;/</span>p<span class="op">&gt;</span></span>
<span id="cb17-20"><a href="#cb17-20" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>p<span class="op">&gt;</span></span>
<span id="cb17-21"><a href="#cb17-21" aria-hidden="true" tabindex="-1"></a>   <span class="op">&lt;</span>label<span class="op">&gt;</span></span>
<span id="cb17-22"><a href="#cb17-22" aria-hidden="true" tabindex="-1"></a>      <span class="dt">Password</span> (confirm)<span class="op">:</span></span>
<span id="cb17-23"><a href="#cb17-23" aria-hidden="true" tabindex="-1"></a>   <span class="op">&lt;/</span>label<span class="op">&gt;</span></span>
<span id="cb17-24"><a href="#cb17-24" aria-hidden="true" tabindex="-1"></a>   <span class="op">&lt;</span>input <span class="kw">type</span><span class="ot">=</span><span class="st">&quot;password&quot;</span> name<span class="ot">=</span><span class="st">&quot;input2&quot;</span> <span class="fu">id</span><span class="ot">=</span><span class="st">&quot;input2&quot;</span> value<span class="ot">=</span><span class="st">&quot;mypassword&quot;</span> <span class="op">/&gt;</span></span>
<span id="cb17-25"><a href="#cb17-25" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;/</span>p<span class="op">&gt;</span></span>
<span id="cb17-26"><a href="#cb17-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-27"><a href="#cb17-27" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><span class="dt">Register</span><span class="op">&gt;</span> <span class="kw">let</span> env <span class="ot">=</span> <span class="fu">map</span> ((<span class="st">&quot;input&quot;</span><span class="op">++</span>) <span class="op">.</span> <span class="fu">show</span>) [<span class="dv">0</span><span class="op">..</span>] <span class="ot">`zip`</span></span>
<span id="cb17-28"><a href="#cb17-28" aria-hidden="true" tabindex="-1"></a>                     <span class="fu">map</span> <span class="dt">Left</span> [<span class="st">&quot;chris&quot;</span>,<span class="st">&quot;mypassword&quot;</span>,<span class="st">&quot;mypa&quot;</span>]</span>
<span id="cb17-29"><a href="#cb17-29" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><span class="dt">Register</span><span class="op">&gt;</span> <span class="kw">let</span> (result,xml,_) <span class="ot">=</span> runFormState env <span class="st">&quot;&quot;</span> register <span class="kw">in</span> result</span>
<span id="cb17-30"><a href="#cb17-30" aria-hidden="true" tabindex="-1"></a><span class="dt">Failure</span> [<span class="st">&quot;Password must be six characters or longer.&quot;</span>]</span>
<span id="cb17-31"><a href="#cb17-31" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><span class="dt">Register</span><span class="op">&gt;</span> <span class="kw">let</span> env <span class="ot">=</span> <span class="fu">map</span> ((<span class="st">&quot;input&quot;</span><span class="op">++</span>) <span class="op">.</span> <span class="fu">show</span>) [<span class="dv">0</span><span class="op">..</span>] <span class="ot">`zip`</span></span>
<span id="cb17-32"><a href="#cb17-32" aria-hidden="true" tabindex="-1"></a>                     <span class="fu">map</span> <span class="dt">Left</span> [<span class="st">&quot;chris&quot;</span>,<span class="st">&quot;mypassword&quot;</span>,<span class="st">&quot;mypassword-&quot;</span>]</span>
<span id="cb17-33"><a href="#cb17-33" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><span class="dt">Register</span><span class="op">&gt;</span> <span class="kw">let</span> (result,xml,_) <span class="ot">=</span> runFormState env <span class="st">&quot;&quot;</span> register <span class="kw">in</span> result</span>
<span id="cb17-34"><a href="#cb17-34" aria-hidden="true" tabindex="-1"></a><span class="dt">Failure</span> [<span class="st">&quot;The entered passwords do not match!&quot;</span>]</span>
<span id="cb17-35"><a href="#cb17-35" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><span class="dt">Register</span><span class="op">&gt;</span> <span class="kw">let</span> env <span class="ot">=</span> <span class="fu">map</span> ((<span class="st">&quot;input&quot;</span><span class="op">++</span>) <span class="op">.</span> <span class="fu">show</span>) [<span class="dv">0</span><span class="op">..</span>] <span class="ot">`zip`</span></span>
<span id="cb17-36"><a href="#cb17-36" aria-hidden="true" tabindex="-1"></a>                     <span class="fu">map</span> <span class="dt">Left</span> [<span class="st">&quot;chris&quot;</span>,<span class="st">&quot;mypassword&quot;</span>,<span class="st">&quot;mypassword&quot;</span>]</span>
<span id="cb17-37"><a href="#cb17-37" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><span class="dt">Register</span><span class="op">&gt;</span> <span class="kw">let</span> (result,xml,_) <span class="ot">=</span> runFormState env <span class="st">&quot;&quot;</span> register <span class="kw">in</span> result</span>
<span id="cb17-38"><a href="#cb17-38" aria-hidden="true" tabindex="-1"></a><span class="dt">Success</span> (<span class="dt">Registration</span> {regUser <span class="ot">=</span> <span class="st">&quot;chris&quot;</span>, regPass <span class="ot">=</span> <span class="st">&quot;mypassword&quot;</span>})</span></code></pre></div>
<p>We now have a full, presentable, composable, validating formlet.</p>
<h3 id="complete-haskell-source">Complete Haskell source</h3>
<p>Below is the source code in full for the reader to read, test and/or
run:</p>
<div class="sourceCode" id="cb18"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="kw">module</span> <span class="dt">Register</span> <span class="kw">where</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Applicative</span></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Network.CGI</span></span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Text.Formlets</span></span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Text.XHtml.Strict.Formlets</span> (<span class="dt">Form</span>)</span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Text.XHtml.Strict.Formlets</span> <span class="kw">as</span> <span class="dt">F</span></span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Text.XHtml.Strict</span> <span class="kw">as</span> <span class="dt">X</span></span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Text.XHtml.Strict</span> ((&lt;&lt;),(+++))</span>
<span id="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-11"><a href="#cb18-11" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Registration</span> <span class="ot">=</span> <span class="dt">Registration</span> {<span class="ot"> regUser ::</span> <span class="dt">String</span></span>
<span id="cb18-12"><a href="#cb18-12" aria-hidden="true" tabindex="-1"></a>                                 ,<span class="ot"> regPass ::</span> <span class="dt">String</span> }</span>
<span id="cb18-13"><a href="#cb18-13" aria-hidden="true" tabindex="-1"></a>                                 <span class="kw">deriving</span> <span class="dt">Show</span></span>
<span id="cb18-14"><a href="#cb18-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-15"><a href="#cb18-15" aria-hidden="true" tabindex="-1"></a><span class="ot">register ::</span> <span class="dt">Form</span> <span class="dt">Html</span> <span class="dt">IO</span> <span class="dt">Registration</span></span>
<span id="cb18-16"><a href="#cb18-16" aria-hidden="true" tabindex="-1"></a>register <span class="ot">=</span> <span class="dt">Registration</span> <span class="op">&lt;$&gt;</span> user <span class="op">&lt;*&gt;</span> passConfirmed</span>
<span id="cb18-17"><a href="#cb18-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-18"><a href="#cb18-18" aria-hidden="true" tabindex="-1"></a><span class="ot">user ::</span> (<span class="dt">Applicative</span> m,<span class="dt">Monad</span> m) <span class="ot">=&gt;</span> <span class="dt">Form</span> <span class="dt">Html</span> m <span class="dt">String</span></span>
<span id="cb18-19"><a href="#cb18-19" aria-hidden="true" tabindex="-1"></a>user <span class="ot">=</span> input <span class="ot">`F.check`</span> F.ensure valid <span class="fu">error</span> <span class="kw">where</span></span>
<span id="cb18-20"><a href="#cb18-20" aria-hidden="true" tabindex="-1"></a>    input <span class="ot">=</span> <span class="st">&quot;Username&quot;</span> <span class="ot">`label`</span> F.input <span class="dt">Nothing</span></span>
<span id="cb18-21"><a href="#cb18-21" aria-hidden="true" tabindex="-1"></a>    valid <span class="ot">=</span> (<span class="op">&gt;=</span><span class="dv">3</span>)<span class="op">.</span> <span class="fu">length</span></span>
<span id="cb18-22"><a href="#cb18-22" aria-hidden="true" tabindex="-1"></a>    <span class="fu">error</span> <span class="ot">=</span> <span class="st">&quot;Username must be three characters or longer.&quot;</span></span>
<span id="cb18-23"><a href="#cb18-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-24"><a href="#cb18-24" aria-hidden="true" tabindex="-1"></a><span class="ot">passConfirmed ::</span> (<span class="dt">Applicative</span> m,<span class="dt">Monad</span> m) <span class="ot">=&gt;</span> <span class="dt">Form</span> <span class="dt">Html</span> m <span class="dt">String</span></span>
<span id="cb18-25"><a href="#cb18-25" aria-hidden="true" tabindex="-1"></a>passConfirmed <span class="ot">=</span> <span class="fu">fst</span> <span class="op">&lt;$&gt;</span> passwords <span class="ot">`F.check`</span> F.ensure equal <span class="fu">error</span> <span class="kw">where</span></span>
<span id="cb18-26"><a href="#cb18-26" aria-hidden="true" tabindex="-1"></a>    passwords <span class="ot">=</span> (,) <span class="op">&lt;$&gt;</span> pass <span class="st">&quot;Password&quot;</span> <span class="op">&lt;*&gt;</span> pass <span class="st">&quot;Password (confirm)&quot;</span></span>
<span id="cb18-27"><a href="#cb18-27" aria-hidden="true" tabindex="-1"></a>    equal (a,b) <span class="ot">=</span> a <span class="op">==</span> b</span>
<span id="cb18-28"><a href="#cb18-28" aria-hidden="true" tabindex="-1"></a>    <span class="fu">error</span> <span class="ot">=</span> <span class="st">&quot;The entered passwords do not match!&quot;</span></span>
<span id="cb18-29"><a href="#cb18-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-30"><a href="#cb18-30" aria-hidden="true" tabindex="-1"></a><span class="ot">pass ::</span> (<span class="dt">Applicative</span> m,<span class="dt">Monad</span> m) <span class="ot">=&gt;</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Form</span> <span class="dt">Html</span> m <span class="dt">String</span></span>
<span id="cb18-31"><a href="#cb18-31" aria-hidden="true" tabindex="-1"></a>pass caption <span class="ot">=</span> input <span class="ot">`F.check`</span> F.ensure valid <span class="fu">error</span> <span class="kw">where</span></span>
<span id="cb18-32"><a href="#cb18-32" aria-hidden="true" tabindex="-1"></a>    input <span class="ot">=</span> caption <span class="ot">`label`</span> F.password <span class="dt">Nothing</span></span>
<span id="cb18-33"><a href="#cb18-33" aria-hidden="true" tabindex="-1"></a>    valid <span class="ot">=</span> (<span class="op">&gt;=</span><span class="dv">6</span>)<span class="op">.</span> <span class="fu">length</span></span>
<span id="cb18-34"><a href="#cb18-34" aria-hidden="true" tabindex="-1"></a>    <span class="fu">error</span> <span class="ot">=</span> <span class="st">&quot;Password must be six characters or longer.&quot;</span></span>
<span id="cb18-35"><a href="#cb18-35" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-36"><a href="#cb18-36" aria-hidden="true" tabindex="-1"></a><span class="ot">label ::</span> (<span class="dt">X.HTML</span> xml,<span class="dt">Monad</span> m,<span class="dt">Plus</span> xml)</span>
<span id="cb18-37"><a href="#cb18-37" aria-hidden="true" tabindex="-1"></a>      <span class="ot">=&gt;</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Form</span> xml m a <span class="ot">-&gt;</span> <span class="dt">Form</span> <span class="dt">Html</span> m a</span>
<span id="cb18-38"><a href="#cb18-38" aria-hidden="true" tabindex="-1"></a>label l <span class="ot">=</span> F.plug (\xhtml <span class="ot">-&gt;</span> X.p <span class="op">&lt;&lt;</span> (X.label <span class="op">&lt;&lt;</span> (l <span class="op">++</span> <span class="st">&quot;: &quot;</span>) <span class="op">+++</span> xhtml))</span></code></pre></div>
<p>Keen eyes will notice that I have changed the type of register:</p>
<div class="sourceCode" id="cb19"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="ot">register ::</span> <span class="dt">Form</span> <span class="dt">Html</span> <span class="dt">IO</span> <span class="dt">Registration</span></span></code></pre></div>
<p>I have set the monad type to IO. This is merely because we are
testing it in GHCi, which defaults to the IO monad, which is just dandy
for our purposes.<a href="#fn4" class="footnote-ref" id="fnref4"
role="doc-noteref"><sup>4</sup></a></p>
<h2 id="example-2-user-registration-with-monadic-validation">Example 2:
User registration with monadic validation</h2>
<p>We have so far covered how to develop a formlet from an informal
description, improve it and then test it in our Haskell prompt. We have
addressed the four points previously mentioned, i.e. we have worked with
how formlets are presented in mark-up, we have worked with how they
validate input, how they fail on invalid input, and how they succeed on
valid input. Furthermore, we have demonstrated to ourselves, albiet in a
limited way, that all of these things can be composed.</p>
<p>So far, our validation has been pure. A formlet takes a value and
validates it purely functionally. This is completely acceptable. Indeed,
initially the Haskell Formlets library was only pure. However, we now
have access to monadic validation! Yes! We shall briefly discuss why
this is a good, and then demonstrate with an example.</p>
<p>Consider a customer database; we want to use this database in our
registration form. Suppose we want to check to see if the username
already exists in the database. If it does, the form fails, otherwise it
returns a registration which can then be sent off to some other function
we don’t care about right now. This means that when validation occurs,
it ought to have the ability to behave differently for the same input.
We need to impurely talk to the database in order to complete the
validation. But why do the formlets need to be impure? Why not run the
whole form, and then compare the returned values against a database?
Because then the whole model of composability is broken. It is no longer
a formlet that validates inputs. It is a formlet that validates some
inputs, and then breaks the abstraction when it gets a bit hairy. We
want to be able to have a username formlet that has everything necessary
in its description contained within its definition. We are now going to
experiment with this notion.</p>
<p>Let us continue from where we left off from Example 1.</p>
<h3 id="create-a-simple-database-to-use">Create a simple database to
use</h3>
<p>For this example, we’ll play it safe and use Sqlite3.</p>
<div class="sourceCode" id="cb20"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Database.HDBC</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Database.HDBC.Sqlite3</span></span></code></pre></div>
<p>We shall create a customer table with some entries to work with, with
md5 hashed passwords:</p>
<div class="sourceCode" id="cb21"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Prelude</span><span class="op">&gt;</span> <span class="op">:</span>set prompt <span class="st">&quot;Haskell&gt; &quot;</span></span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Haskell</span><span class="op">&gt;</span> <span class="op">:</span>set <span class="op">-</span><span class="dt">XOverloadedStrings</span></span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a><span class="dt">Haskell</span><span class="op">&gt;</span> <span class="op">:</span>m <span class="op">+</span> <span class="dt">Data.Digest.Pure.MD5</span> <span class="dt">Data.ByteString.Lazy.Char8</span></span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a><span class="dt">Haskell</span><span class="op">&gt;</span> md5 <span class="st">&quot;haskell4life&quot;</span></span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a><span class="dt">Loading</span> package syb <span class="op">...</span> linking <span class="op">...</span> done<span class="op">.</span></span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a><span class="dt">Loading</span> package base<span class="op">-</span><span class="fl">3.0</span><span class="op">.</span><span class="fl">3.0</span> <span class="op">...</span> linking <span class="op">...</span> done<span class="op">.</span></span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a><span class="dt">Loading</span> package array<span class="op">-</span><span class="fl">0.2</span><span class="op">.</span><span class="fl">0.0</span> <span class="op">...</span> linking <span class="op">...</span> done<span class="op">.</span></span>
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a><span class="dt">Loading</span> package containers<span class="op">-</span><span class="fl">0.2</span><span class="op">.</span><span class="fl">0.0</span> <span class="op">...</span> linking <span class="op">...</span> done<span class="op">.</span></span>
<span id="cb21-9"><a href="#cb21-9" aria-hidden="true" tabindex="-1"></a><span class="dt">Loading</span> package bytestring<span class="op">-</span><span class="fl">0.9</span><span class="op">.</span><span class="fl">1.4</span> <span class="op">...</span> linking <span class="op">...</span> done<span class="op">.</span></span>
<span id="cb21-10"><a href="#cb21-10" aria-hidden="true" tabindex="-1"></a><span class="dt">Loading</span> package binary<span class="op">-</span><span class="fl">0.4</span><span class="op">.</span><span class="dv">4</span> <span class="op">...</span> linking <span class="op">...</span> done<span class="op">.</span></span>
<span id="cb21-11"><a href="#cb21-11" aria-hidden="true" tabindex="-1"></a><span class="dt">Loading</span> package pureMD5<span class="op">-</span><span class="fl">0.2</span><span class="op">.</span><span class="dv">4</span> <span class="op">...</span> linking <span class="op">...</span> done<span class="op">.</span></span>
<span id="cb21-12"><a href="#cb21-12" aria-hidden="true" tabindex="-1"></a>8afba4d177e7162510b9edf0139d1e8c</span>
<span id="cb21-13"><a href="#cb21-13" aria-hidden="true" tabindex="-1"></a><span class="dt">Haskell</span><span class="op">&gt;</span> md5 <span class="st">&quot;expert programmer&quot;</span></span>
<span id="cb21-14"><a href="#cb21-14" aria-hidden="true" tabindex="-1"></a>c60ce6776f224600bb33e463aa68d138</span>
<span id="cb21-15"><a href="#cb21-15" aria-hidden="true" tabindex="-1"></a><span class="dt">Haskell</span><span class="op">&gt;</span></span></code></pre></div>
<p>The OverloadedStrings option lets us write string literals which can
be provided as String or ByteString.<a href="#fn5" class="footnote-ref"
id="fnref5" role="doc-noteref"><sup>5</sup></a></p>
<div class="sourceCode" id="cb22"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a>chris<span class="op">@</span>chrisdesktop<span class="op">:/</span>var<span class="op">/</span>www<span class="op">/</span>chrisdone<span class="op">/</span>blog<span class="op">/</span>db<span class="op">/</span>static<span class="op">$</span> sqlite3 <span class="co">--version</span></span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a><span class="fl">3.4</span><span class="op">.</span><span class="dv">2</span></span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a>chris<span class="op">@</span>chrisdesktop<span class="op">:/</span>var<span class="op">/</span>www<span class="op">/</span>chrisdone<span class="op">/</span>blog<span class="op">/</span>db<span class="op">/</span>static<span class="op">$</span> sqlite3 customer<span class="op">.</span>db</span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a><span class="dt">SQLite</span> version <span class="fl">3.4</span><span class="op">.</span><span class="dv">2</span></span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a><span class="dt">Enter</span> <span class="st">&quot;.help&quot;</span> for instructions</span>
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a>sqlite<span class="op">&gt;</span> <span class="dt">CREATE</span> <span class="dt">TABLE</span> <span class="ot">`customer`</span> (<span class="ot">`id`</span> <span class="dt">INTEGER</span> <span class="dt">PRIMARY_KEY</span></span>
<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a><span class="dt">AUTO_INCREMENT</span>, <span class="ot">`username`</span> <span class="dt">TINY</span> <span class="dt">BLOB</span>, <span class="ot">`password`</span> <span class="dt">BLOB</span>);</span>
<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a>sqlite<span class="op">&gt;</span> <span class="dt">INSERT</span> <span class="dt">INTO</span> <span class="ot">`customer`</span> (<span class="ot">`username`</span>, <span class="ot">`password`</span>) <span class="dt">VALUES</span></span>
<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a>(<span class="dt">&#39;Peyton</span> <span class="ot">`Simon`</span> <span class="dt">Jones&#39;</span>, &#39;085b1b14b7212a61ab8bffe89b02c254&#39;);</span>
<span id="cb22-10"><a href="#cb22-10" aria-hidden="true" tabindex="-1"></a>sqlite<span class="op">&gt;</span> <span class="dt">INSERT</span> <span class="dt">INTO</span> <span class="ot">`customer`</span> (<span class="ot">`username`</span>, <span class="ot">`password`</span>) <span class="dt">VALUES</span></span>
<span id="cb22-11"><a href="#cb22-11" aria-hidden="true" tabindex="-1"></a>(<span class="dt">&#39;Christopher</span> <span class="dt">Done&#39;</span>, &#39;c60ce6776f224600bb33e463aa68d138&#39;);</span>
<span id="cb22-12"><a href="#cb22-12" aria-hidden="true" tabindex="-1"></a>sqlite<span class="op">&gt;</span> <span class="dt">SELECT</span> <span class="op">*</span> <span class="dt">FROM</span> <span class="ot">`customer`</span>;</span>
<span id="cb22-13"><a href="#cb22-13" aria-hidden="true" tabindex="-1"></a><span class="op">|</span><span class="dt">Christopher</span> <span class="dt">Done</span><span class="op">|</span>c60ce6776f224600bb33e463aa68d138</span>
<span id="cb22-14"><a href="#cb22-14" aria-hidden="true" tabindex="-1"></a><span class="op">|</span><span class="dt">Peyton</span> <span class="ot">`Simon`</span> <span class="dt">Jones</span><span class="op">|</span>085b1b14b7212a61ab8bffe89b02c254</span>
<span id="cb22-15"><a href="#cb22-15" aria-hidden="true" tabindex="-1"></a>sqlite<span class="op">&gt;</span> <span class="op">.</span>quit</span>
<span id="cb22-16"><a href="#cb22-16" aria-hidden="true" tabindex="-1"></a>chris<span class="op">@</span>chrisdesktop<span class="op">:/</span>var<span class="op">/</span>www<span class="op">/</span>chrisdone<span class="op">/</span>blog<span class="op">/</span>db<span class="op">/</span>static<span class="op">$</span></span>
<span id="cb22-17"><a href="#cb22-17" aria-hidden="true" tabindex="-1"></a><span class="dt">And</span> now ensuring we have access from <span class="dt">Haskell&#39;s</span> library<span class="op">:</span></span>
<span id="cb22-18"><a href="#cb22-18" aria-hidden="true" tabindex="-1"></a><span class="dt">Haskell</span><span class="op">&gt;</span> <span class="op">:</span>load <span class="st">&quot;/var/www/chrisdone/blog/db/static/Register.hs&quot;</span></span>
<span id="cb22-19"><a href="#cb22-19" aria-hidden="true" tabindex="-1"></a>[<span class="dv">1</span> <span class="kw">of</span> <span class="dv">1</span>] <span class="dt">Compiling</span> <span class="dt">Register</span> ( Register.hs, interpreted )</span>
<span id="cb22-20"><a href="#cb22-20" aria-hidden="true" tabindex="-1"></a><span class="dt">Ok</span>, modules loaded<span class="op">:</span> <span class="dt">Register</span><span class="op">.</span></span>
<span id="cb22-21"><a href="#cb22-21" aria-hidden="true" tabindex="-1"></a><span class="dt">Haskell</span><span class="op">&gt;</span> con <span class="ot">&lt;-</span> connectSqlite3 <span class="st">&quot;customer.db&quot;</span></span>
<span id="cb22-22"><a href="#cb22-22" aria-hidden="true" tabindex="-1"></a><span class="dt">Haskell</span><span class="op">&gt;</span> getTables con</span>
<span id="cb22-23"><a href="#cb22-23" aria-hidden="true" tabindex="-1"></a>[<span class="st">&quot;customer&quot;</span>]</span>
<span id="cb22-24"><a href="#cb22-24" aria-hidden="true" tabindex="-1"></a><span class="dt">Haskell</span><span class="op">&gt;</span> quickQuery con <span class="st">&quot;SELECT * FROM `customer`&quot;</span> []</span>
<span id="cb22-25"><a href="#cb22-25" aria-hidden="true" tabindex="-1"></a>[[<span class="dt">SqlNull</span>,<span class="dt">SqlString</span> <span class="st">&quot;Christopher Done&quot;</span>,</span>
<span id="cb22-26"><a href="#cb22-26" aria-hidden="true" tabindex="-1"></a>  <span class="dt">SqlString</span> <span class="st">&quot;c60ce6776f224600bb33e463aa68d138&quot;</span>],</span>
<span id="cb22-27"><a href="#cb22-27" aria-hidden="true" tabindex="-1"></a>[<span class="dt">SqlNull</span>,<span class="dt">SqlString</span> <span class="st">&quot;Peyton `Simon` Jones&quot;</span>,</span>
<span id="cb22-28"><a href="#cb22-28" aria-hidden="true" tabindex="-1"></a> <span class="dt">SqlString</span> <span class="st">&quot;085b1b14b7212a61ab8bffe89b02c254&quot;</span>]]</span>
<span id="cb22-29"><a href="#cb22-29" aria-hidden="true" tabindex="-1"></a><span class="dt">Haskell</span><span class="op">&gt;</span> quickQuery con <span class="st">&quot;SELECT * FROM `customer`</span></span>
<span id="cb22-30"><a href="#cb22-30" aria-hidden="true" tabindex="-1"></a><span class="st">WHERE `username` LIKE &#39;Christopher Done&#39;;&quot;</span> []</span>
<span id="cb22-31"><a href="#cb22-31" aria-hidden="true" tabindex="-1"></a>[[<span class="dt">SqlNull</span>,<span class="dt">SqlString</span> <span class="st">&quot;Christopher Done&quot;</span>,</span>
<span id="cb22-32"><a href="#cb22-32" aria-hidden="true" tabindex="-1"></a>  <span class="dt">SqlString</span> <span class="st">&quot;c60ce6776f224600bb33e463aa68d138&quot;</span>]]</span>
<span id="cb22-33"><a href="#cb22-33" aria-hidden="true" tabindex="-1"></a><span class="dt">Haskell</span><span class="op">&gt;</span></span></code></pre></div>
<h3 id="validating-against-an-sql-database">Validating against an SQL
database</h3>
<p>Let us now return to studying how to impurely validate in a formlet.
We notice that the types thus far have all talked about a monad type,
which we have ignored so far. Now we can make use of it:</p>
<div class="sourceCode" id="cb23"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="ot">checkM ::</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> <span class="dt">Form</span> xml m a <span class="ot">-&gt;</span> (a <span class="ot">-&gt;</span> m (<span class="dt">Failing</span> b)) <span class="ot">-&gt;</span> <span class="dt">Form</span> xml m b</span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a><span class="ot">ensureM ::</span> (<span class="dt">Monad</span> m, <span class="dt">Show</span> a) <span class="ot">=&gt;</span> (a <span class="ot">-&gt;</span> m <span class="dt">Bool</span>) <span class="ot">-&gt;</span> <span class="dt">String</span> <span class="ot">-&gt;</span> a <span class="ot">-&gt;</span> m (<span class="dt">Failing</span> a)</span></code></pre></div>
<p>These functions are monadic equivalents of check and ensure.
Therefore, with this in mind, let us consider our definition of
user.</p>
<div class="sourceCode" id="cb24"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="ot">user ::</span> (<span class="dt">Applicative</span> m,<span class="dt">Monad</span> m) <span class="ot">=&gt;</span> <span class="dt">Form</span> <span class="dt">Html</span> m <span class="dt">String</span></span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>user <span class="ot">=</span> input <span class="ot">`F.check`</span> F.ensure valid <span class="fu">error</span> <span class="kw">where</span></span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>    input <span class="ot">=</span> <span class="st">&quot;Username&quot;</span> <span class="ot">`label`</span> F.input <span class="dt">Nothing</span></span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a>    valid <span class="ot">=</span> (<span class="op">&gt;=</span><span class="dv">3</span>)<span class="op">.</span> <span class="fu">length</span></span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a>    <span class="fu">error</span> <span class="ot">=</span> <span class="st">&quot;Username must be three characters or longer.&quot;</span></span></code></pre></div>
<p>I think that this formlet is a fine piece of code. Indeed, we do not
need to change it at all. Instead, let us define a new formlet which
wraps around this one, called uniqueUser:</p>
<div class="sourceCode" id="cb25"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="ot">uniqueUser ::</span> <span class="dt">Connection</span> <span class="ot">-&gt;</span> <span class="dt">Form</span> <span class="dt">Html</span> <span class="dt">IO</span> <span class="dt">String</span></span></code></pre></div>
<p>In order to query against the database we will need to pass the
connection handle along. Or will we? I propose a ReaderT monad!</p>
<div class="sourceCode" id="cb26"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Monad.Reader</span></span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">SQLM</span> <span class="ot">=</span> <span class="dt">ReaderT</span> <span class="dt">Connection</span> <span class="dt">IO</span></span></code></pre></div>
<p>Our computation also needs to be an instance of Applicative to work
with Formlets, so we define an instance for all ReaderT types:</p>
<div class="sourceCode" id="cb27"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> <span class="dt">Applicative</span> (<span class="dt">ReaderT</span> s m) <span class="kw">where</span></span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a>    <span class="fu">pure</span> <span class="ot">=</span> <span class="fu">return</span>; (<span class="op">&lt;*&gt;</span>) <span class="ot">=</span> ap</span></code></pre></div>
<p>We’ll define a simple utility function which will take the connection
from the monad and use it for a query:</p>
<div class="sourceCode" id="cb28"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="ot">query ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> [<span class="dt">SqlValue</span>] <span class="ot">-&gt;</span> <span class="dt">SQLM</span> [[<span class="dt">SqlValue</span>]]</span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a>query statement values <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a>  conn <span class="ot">&lt;-</span> ask</span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a>  liftIO <span class="op">$</span> quickQuery conn statement values</span></code></pre></div>
<p>A demonstration might be something like:</p>
<div class="sourceCode" id="cb29"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><span class="dt">Register</span><span class="op">&gt;</span> runReaderT (query <span class="st">&quot;SELECT * FROM `customer`&quot;</span> []) con</span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a>[[<span class="dt">SqlNull</span>,<span class="dt">SqlString</span> <span class="st">&quot;Christopher Done&quot;</span>,</span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">SqlString</span> <span class="st">&quot;c60ce6776f224600bb33e463aa68d138&quot;</span>],</span>
<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a> [<span class="dt">SqlNull</span>,<span class="dt">SqlString</span> <span class="st">&quot;Peyton `Simon` Jones&quot;</span>,</span>
<span id="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a> <span class="dt">SqlString</span> <span class="st">&quot;085b1b14b7212a61ab8bffe89b02c254&quot;</span>]]</span></code></pre></div>
<p>Therefore we can make a very neat definition of uniqueUser:</p>
<div class="sourceCode" id="cb30"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="ot">uniqueUser ::</span> <span class="dt">Form</span> <span class="dt">Html</span> <span class="dt">SQLM</span> <span class="dt">String</span></span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a>uniqueUser <span class="ot">=</span> user <span class="ot">`F.checkM`</span> F.ensureM valid <span class="fu">error</span> <span class="kw">where</span></span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a>valid name <span class="ot">=</span> <span class="fu">null</span> <span class="op">&lt;$&gt;</span> query statement [toSql name]</span>
<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a>statement <span class="ot">=</span> <span class="st">&quot;SELECT * FROM `customer` WHERE `username` LIKE ?&quot;</span></span>
<span id="cb30-5"><a href="#cb30-5" aria-hidden="true" tabindex="-1"></a><span class="fu">error</span> <span class="ot">=</span> <span class="st">&quot;Username already exists in the database!&quot;</span></span></code></pre></div>
<p>I warn the reader of potential heart failure, excretions or other
effects due to viewing the next section. Let us now test our monadic
validating formlet:</p>
<div class="sourceCode" id="cb31"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><span class="dt">Register</span><span class="op">&gt;</span> <span class="op">:</span>load <span class="st">&quot;/var/www/chrisdone/blog/db/static/Register.hs&quot;</span></span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a>[<span class="dv">1</span> <span class="kw">of</span> <span class="dv">1</span>] <span class="dt">Compiling</span> <span class="dt">Register</span> ( Register.hs, interpreted )</span>
<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a><span class="dt">Ok</span>, modules loaded<span class="op">:</span> <span class="dt">Register</span><span class="op">.</span></span>
<span id="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><span class="dt">Register</span><span class="op">&gt;</span> <span class="kw">let</span> env <span class="ot">=</span> <span class="fu">map</span> ((<span class="st">&quot;input&quot;</span><span class="op">++</span>) <span class="op">.</span> <span class="fu">show</span>) [<span class="dv">0</span><span class="op">..</span>] <span class="ot">`zip`</span></span>
<span id="cb31-5"><a href="#cb31-5" aria-hidden="true" tabindex="-1"></a>                     <span class="fu">map</span> <span class="dt">Left</span> [<span class="st">&quot;chris&quot;</span>,<span class="st">&quot;mypassword&quot;</span>,<span class="st">&quot;mypassword&quot;</span>]</span>
<span id="cb31-6"><a href="#cb31-6" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><span class="dt">Register</span><span class="op">&gt;</span> con <span class="ot">&lt;-</span> connectSqlite3 <span class="st">&quot;customer.db&quot;</span></span>
<span id="cb31-7"><a href="#cb31-7" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><span class="dt">Register</span><span class="op">&gt;</span> <span class="kw">let</span> (result,xml,_) <span class="ot">=</span> runFormState env <span class="st">&quot;&quot;</span> register</span>
<span id="cb31-8"><a href="#cb31-8" aria-hidden="true" tabindex="-1"></a>           <span class="kw">in</span> runReaderT result con</span>
<span id="cb31-9"><a href="#cb31-9" aria-hidden="true" tabindex="-1"></a><span class="dt">Success</span> (<span class="dt">Registration</span> {regUser <span class="ot">=</span> <span class="st">&quot;chris&quot;</span>, regPass <span class="ot">=</span> <span class="st">&quot;mypassword&quot;</span>})</span>
<span id="cb31-10"><a href="#cb31-10" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><span class="dt">Register</span><span class="op">&gt;</span> <span class="kw">let</span> env <span class="ot">=</span> <span class="fu">map</span> ((<span class="st">&quot;input&quot;</span><span class="op">++</span>) <span class="op">.</span> <span class="fu">show</span>) [<span class="dv">0</span><span class="op">..</span>] <span class="ot">`zip`</span></span>
<span id="cb31-11"><a href="#cb31-11" aria-hidden="true" tabindex="-1"></a>                     <span class="fu">map</span> <span class="dt">Left</span> [<span class="st">&quot;christopher done&quot;</span>,<span class="st">&quot;mypassword&quot;</span>,<span class="st">&quot;mypassword&quot;</span>]</span>
<span id="cb31-12"><a href="#cb31-12" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><span class="dt">Register</span><span class="op">&gt;</span> <span class="kw">let</span> (result,xml,_) <span class="ot">=</span> runFormState env <span class="st">&quot;&quot;</span> register</span>
<span id="cb31-13"><a href="#cb31-13" aria-hidden="true" tabindex="-1"></a>           <span class="kw">in</span> runReaderT result con</span>
<span id="cb31-14"><a href="#cb31-14" aria-hidden="true" tabindex="-1"></a><span class="dt">Failure</span> [<span class="st">&quot;Username already exists in the database!&quot;</span>]</span>
<span id="cb31-15"><a href="#cb31-15" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><span class="dt">Register</span><span class="op">&gt;</span></span></code></pre></div>
<p>I shall summarise what has been covered in this section. We have
familiarised ourselves with monadic version of check and ensure. We have
happily combined pure and impure formlets, and kept each formlet
contained, doing one thing well. ’Tis the beauty of abstraction in
programming at its most clear. We have established how to run a formlet
with a monad such as ReaderT, and we can see how this might be done with
StateT, for instance.</p>
<h2 id="example-3-custom-form-inputs">Example 3: Custom form inputs</h2>
<p>Earlier, we touched upon producing custom mark-up for a formlet, by
wrapping around an existing one. We will now create our own (simple)
form input from scratch; that which is not provided in the
Text.XHtml.Formlets library; a checkbox.</p>
<p>A checkbox can only return two values, checked or unchecked,
therefore Bool is completely satisfactory as a return value for our
formlet. To help us think about the type, let’s look at an existing form
input’s type:</p>
<div class="sourceCode" id="cb32"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a><span class="ot">radio ::</span> <span class="dt">Monad</span> m</span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a>      <span class="ot">=&gt;</span> [(<span class="dt">String</span>,<span class="dt">String</span>)] <span class="ot">-&gt;</span> <span class="dt">Maybe</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">XHtmlForm</span> m <span class="dt">String</span></span></code></pre></div>
<p>It takes a list of (name,value) pairs, a default value, and returns a
choice of radio buttons.</p>
<p>It is worth noting that the type XHtmlForm is simply an alias for
specifying the Text.XHtml.Strict.html type, defined as type XHtmlForm m
a = Form Html m a.</p>
<p>Our type should be as follows:</p>
<div class="sourceCode" id="cb33"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a><span class="ot">checkbox ::</span> <span class="dt">Monad</span> m</span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a>         <span class="ot">=&gt;</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Maybe</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">XHtmlForm</span> m <span class="dt">String</span></span></code></pre></div>
<p>Take, a caption for the checkbox, maybe a default value, and return a
checkbox which returns “yes” or “no”.</p>
<p>To implement a form input, we need the input’ function:</p>
<div class="sourceCode" id="cb34"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a><span class="ot">input&#39; ::</span> <span class="dt">Monad</span> m</span>
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a>       <span class="ot">=&gt;</span> (<span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">String</span> <span class="ot">-&gt;</span> xml) <span class="ot">-&gt;</span> <span class="dt">Maybe</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Form</span> xml m <span class="dt">String</span></span></code></pre></div>
<p>input’ takes a function that takes a name for the element in markup,
and a value, input’ also takes maybe default value for the element, and
finally returns a formlet.</p>
<div class="sourceCode" id="cb35"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a><span class="ot">checkbox ::</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Maybe</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">XHtmlForm</span> m <span class="dt">String</span></span>
<span id="cb35-2"><a href="#cb35-2" aria-hidden="true" tabindex="-1"></a>checkbox caption def <span class="ot">=</span> input&#39; box def <span class="kw">where</span></span>
<span id="cb35-3"><a href="#cb35-3" aria-hidden="true" tabindex="-1"></a>    box name value <span class="ot">=</span> X.input <span class="op">!</span> ([X.thetype <span class="st">&quot;checkbox&quot;</span>, X.name name] <span class="op">++</span> checked)</span>
<span id="cb35-4"><a href="#cb35-4" aria-hidden="true" tabindex="-1"></a>                     <span class="op">+++</span> caption</span>
<span id="cb35-5"><a href="#cb35-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">where</span> checked <span class="op">|</span> value <span class="op">==</span> <span class="st">&quot;yes&quot;</span> <span class="op">||</span> value <span class="op">==</span> <span class="st">&quot;on&quot;</span> <span class="ot">=</span> [X.checked]</span>
<span id="cb35-6"><a href="#cb35-6" aria-hidden="true" tabindex="-1"></a>                      <span class="op">|</span> <span class="fu">otherwise</span>  <span class="ot">=</span> []</span></code></pre></div>
<p>It is quite simple. There is nothing fancy to be done. Merely produce
the correct markup. We can test it in GHCi to confirm:</p>
<div class="sourceCode" id="cb36"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb36-1"><a href="#cb36-1" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><span class="dt">Register</span><span class="op">&gt;</span> <span class="kw">let</span> env <span class="ot">=</span> <span class="fu">map</span> ((<span class="st">&quot;input&quot;</span><span class="op">++</span>) <span class="op">.</span> <span class="fu">show</span>) [<span class="dv">0</span><span class="op">..</span>] <span class="ot">`zip`</span> <span class="fu">map</span> <span class="dt">Left</span> [<span class="st">&quot;yes&quot;</span>]</span>
<span id="cb36-2"><a href="#cb36-2" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><span class="dt">Register</span><span class="op">&gt;</span> <span class="kw">let</span> (result,xml,_) <span class="ot">=</span></span>
<span id="cb36-3"><a href="#cb36-3" aria-hidden="true" tabindex="-1"></a>             runFormState env <span class="st">&quot;&quot;</span> (checkbox <span class="st">&quot;Send me spam?&quot;</span> <span class="dt">Nothing</span>)</span>
<span id="cb36-4"><a href="#cb36-4" aria-hidden="true" tabindex="-1"></a>           <span class="kw">in</span> <span class="kw">do</span> r <span class="ot">&lt;-</span> result; x <span class="ot">&lt;-</span> xml; <span class="fu">return</span> (r,x)</span>
<span id="cb36-5"><a href="#cb36-5" aria-hidden="true" tabindex="-1"></a>(<span class="dt">Success</span> <span class="st">&quot;yes&quot;</span>,<span class="op">&lt;</span>input <span class="kw">type</span><span class="ot">=</span><span class="st">&quot;checkbox&quot;</span></span>
<span id="cb36-6"><a href="#cb36-6" aria-hidden="true" tabindex="-1"></a>name<span class="ot">=</span><span class="st">&quot;input0&quot;</span> checked<span class="ot">=</span><span class="st">&quot;checked&quot;</span> <span class="op">/&gt;</span><span class="dt">Send</span> me spam<span class="op">?</span>)</span>
<span id="cb36-7"><a href="#cb36-7" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><span class="dt">Register</span><span class="op">&gt;</span> <span class="kw">let</span> env <span class="ot">=</span> <span class="fu">map</span> ((<span class="st">&quot;input&quot;</span><span class="op">++</span>) <span class="op">.</span> <span class="fu">show</span>) [<span class="dv">0</span><span class="op">..</span>] <span class="ot">`zip`</span> <span class="fu">map</span> <span class="dt">Left</span> [<span class="st">&quot;no&quot;</span>]</span>
<span id="cb36-8"><a href="#cb36-8" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><span class="dt">Register</span><span class="op">&gt;</span> <span class="kw">let</span> (result,xml,_) <span class="ot">=</span></span>
<span id="cb36-9"><a href="#cb36-9" aria-hidden="true" tabindex="-1"></a>             runFormState env <span class="st">&quot;&quot;</span> (checkbox <span class="st">&quot;Send me spam?&quot;</span> <span class="dt">Nothing</span>)</span>
<span id="cb36-10"><a href="#cb36-10" aria-hidden="true" tabindex="-1"></a>           <span class="kw">in</span> <span class="kw">do</span> r <span class="ot">&lt;-</span> result; x <span class="ot">&lt;-</span> xml; <span class="fu">return</span> (r,x)</span>
<span id="cb36-11"><a href="#cb36-11" aria-hidden="true" tabindex="-1"></a>(<span class="dt">Success</span> <span class="st">&quot;no&quot;</span>,<span class="op">&lt;</span>input <span class="kw">type</span><span class="ot">=</span><span class="st">&quot;checkbox&quot;</span></span>
<span id="cb36-12"><a href="#cb36-12" aria-hidden="true" tabindex="-1"></a>name<span class="ot">=</span><span class="st">&quot;input0&quot;</span><span class="op">/&gt;</span><span class="dt">Send</span> me spam<span class="op">?</span>)</span>
<span id="cb36-13"><a href="#cb36-13" aria-hidden="true" tabindex="-1"></a><span class="op">*</span><span class="dt">Register</span><span class="op">&gt;</span></span></code></pre></div>
<p>Of course, we have only demonstrated a very simple example. However,
most form elements are simple. The point here is that one can use
arbitary markup in a formlet and then compose that with any other.
Consider a clever Javascript colour selector, and such things like
that.</p>
<h2 id="formlets-in-a-real-cgi-program">Formlets in a real CGI
program</h2>
<p>We have now covered the lovely features of the Haskell Formlets.
Finally, I have put our demonstration code into practise in a live
server application which simply accepts registrations and lists the
usernames. You can view the page and view the raw source code or a
syntax highlighted version. Forgive the messy code; it was written in
about ten minutes; the code around it isn’t really important. It is the
formlets themselves.</p>
<p><strong>UPDATE: 11 April 09:</strong> Also, I have an example of
using formlets in a real project with time constraints etc.</p>
<h2 id="summary">Summary</h2>
<p>I think I have covered, quite fully, the idea of formlets. Formlets
are composable pieces which contain (1) presentation, (2) validation,
(3) parsing, (4) success and (5) failure. Formlets are useful because
these five points are kept in one place and thus consistent, without any
manual ‘synching’. We can compose formlets, and a formlet’s definition
contains all the required information. We can customise the presentation
of existing formlets, or create our own new input methods. A
self-contained formlet can validate with and perform side-effects, in a
safe, composable manner. Formlets parse validated values into proper
program values (such as the Registration type). Formlets are an
excellent example of the kind of abstractions that Haskellers use all
the time.</p>
<h2 id="notes">Notes</h2>
<p>Please email me about any typing mistakes or inconsistencies that you
notice.</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Formlets, Parsec, Text.XHtml, the
various monads, are some of my favourite examples.<a href="#fnref1"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p>This is a type, defined in
Control.Applicative.Error, with a definition that will make clear to you
why it is used:</p>
<pre><code> data Failing a = Success a | Failure [ErrorMsg]</code></pre>
<a href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></li>
<li id="fn3" role="doc-endnote"><p>Which I wrote in one go, compiled,
and found that it worked first time. I am clearly reaching Haskell
Satori.<a href="#fnref3" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn4" role="doc-endnote"><p>One could easily leave it ambiguous,
using the NoMonomorphismRestriction pragma, thus allowing us to use
register in the IO monad, or the CGI monad, etc.<a href="#fnref4"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn5" role="doc-endnote"><p>“GHC supports overloaded string
literals. Normally a string literal has type String, but with overloaded
string literals enabled (with <code>-XOverloadedStrings</code>) a string
literal has type <code>(IsString a) =&gt;   a</code>.” See the GHC
documentation for <code>-XOverloadedStrings</code> for more
information.<a href="#fnref5" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2008-11-14 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Fri, 14 Nov 2008 00:00:00 +0000
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[New Kibro]]></title><link>https://chrisdone.com/posts/new-kibro</link><guid>https://chrisdone.com/posts/new-kibro</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>New Kibro</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>New Kibro</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>The latest Kibro release is 0.3. The version is 0.3, but it’s really
still unstable/Alpha. If it works on your computer it’s generally a
miracle. Anyway.</p>
<h2 id="whats-new">What’s new</h2>
<p>Quoting directly from the CHANGELOG in README:</p>
<ul>
<li><p>DONE: Add persistent state value to Kibro monad (with default as
())</p></li>
<li><p>DONE: Add perl-like regexps</p></li>
<li><p>DONE: Option for whether or not to launch Lighttpd</p></li>
<li><p>DONE: Strip Sqlite3</p></li>
<li><p>DONE: custom.conf Lighttpd include</p></li>
</ul>
<p>I’m quite sure these satisfy all the solutions that were mentioned in
my previous Kibro blog post.</p>
<h2 id="how-to-get-it">How to get it</h2>
<p>Make sure you have cabal-install.</p>
<h3 id="install-from-hackage">Install from Hackage</h3>
<pre><code>$ cabal install kibro</code></pre>
<h3 id="install-from-git-repository">Install from git repository</h3>
<pre><code>cd kibro &amp;&amp; cabal install</code></pre>
<p>That’s it.</p>
<h2 id="example">Example</h2>
<p>I have started a bit of work on a Lojban interface. I made a little
“screencast”-type video about using Kibro (but without a microphone, so
you will have to read me typing little messages to you). Check out the
example page.</p>
<p>At some point Firefox started sending the PC speaker beep constantly
and so I had to end the video. Still, it was a bit of fun and maybe it
could be helpful.</p>
<p>Get the source code:</p>
<pre><code>$ git clone git://github.com/chrisdone/jboborei.git</code></pre>
<h1 id="whats-next">What’s next</h1>
<p>For me; sleep.</p>
<p>For Kibro; I need to document it a little more, e.g. how to use it
with an existing server etc.</p>
<p>I was thinking that implementing hooks might be mildly cool. That is,
if Kibro were to run specific shell scripts before and after events like
restarting, rebuilding, etc.</p>
<p>I also would like to add cabal support at some point. That way, you
can write a web site that works as a package that is cabal-installable.
Good for sharing with friends and such.</p>
<p>If you have questions/comments/ideas, feel free to e-mail me at
chrisdone@gmail.com or comment on this blog post.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2008-10-14 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Tue, 14 Oct 2008 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[Kibro refactoring]]></title><link>https://chrisdone.com/posts/kibro-refactoring</link><guid>https://chrisdone.com/posts/kibro-refactoring</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Kibro refactoring</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>Kibro refactoring</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>I am refactoring Kibro, my web development “framework”. The release
on Hackage does bare bones things, and Jinjing Wang, what a legend,
created this Panda software out of it. In doing so he has helped me
notice what Kibro needs. I myself have found things that Kibro does not
support in my projects that I will be addressing. I am writing this post
so that anyone who cares will know that this project is being worked on,
and because for those actually using Kibro it will help to know the
reasoning behind the changes. The code needed refactoring anyway, it had
!OMGPROTOTYPE! written all over it.</p>
<h2 id="problems-and-solutions">Problems and solutions</h2>
<h3 id="lighttpd.conf-configuration">Lighttpd.conf configuration</h3>
<p>Panda comes with a script to modify the lighttpd.conf which adds
mime-types and things like that. It’s a problem that you have to do
this.</p>
<p>I have discovered that Lighttpd config files support an #include
directive and it is therefore my solution that all settings that are not
dependant on the path of the project<a href="#fn1" class="footnote-ref"
id="fnref1" role="doc-noteref"><sup>1</sup></a> be moved to a
custom.conf in the lighttpd directory.</p>
<h3 id="database-not-used">Database not used</h3>
<p>The Kibro library requires you to specify a database, but your web
site might not always want a database (like Panda). I am removing the
Sqlite interface from Kibro for now for this reason, and others<a
href="#fn2" class="footnote-ref" id="fnref2"
role="doc-noteref"><sup>2</sup></a>. You ought to feel free to use the
MonadIO instance of the Kibro monad to open connections to whichever
database library you like.</p>
<h3 id="adding-persistent-state">Adding persistent state</h3>
<p>Furthmore addressing the problem of the Kibro library, perhaps adding
custom state may be useful. For example, your main web site code might
be:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Kibro</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">MyWebSiteStuff</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="ot">main ::</span> <span class="dt">IO</span> ()</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>  someResource <span class="ot">&lt;-</span> getMyResource</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>  startKibro someResource pages</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="ot">pages ::</span> [<span class="dt">PageAssign</span>]</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>pages <span class="ot">=</span> <span class="op">...</span></span></code></pre></div>
<p>This lets us connect to a database or generate some resources that
are too expensive to create for every page load. Typically it can be a
pure value or an MVar or TVar or whatnot.</p>
<h3 id="kibro-command-line-program-is-rubbish">Kibro command line
program is rubbish</h3>
<p>It is generally rubbish (e.g. doesn’t even support a help function).
I’ve changed this, and lots of other things. The code before was awful.
It now uses a Command monad (of course). I guarentee it.</p>
<h3 id="settings">Settings</h3>
<p>There needs to be a way to configure Kibro for the project. Another
thing I noticed was that Panda changed where to output the .fcgi file.
This should be configurable. Thus, Kibro now reads settings from the
.kibro file in the directory, the same as Cabal. Here is a real sample
config<a href="#fn3" class="footnote-ref" id="fnref3"
role="doc-noteref"><sup>3</sup></a> file:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="dt">KibroProject</span> { projName <span class="ot">=</span> <span class="st">&quot;test&quot;</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>             , projDirs <span class="ot">=</span> [(<span class="st">&quot;app&quot;</span>,<span class="st">&quot;app&quot;</span>)</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>                          ,(<span class="st">&quot;lighttpd&quot;</span>,<span class="st">&quot;app/lighttpd&quot;</span>)</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>                          ,(<span class="st">&quot;fastcgi&quot;</span>,<span class="st">&quot;app/fastcgi&quot;</span>)</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>                          ,(<span class="st">&quot;public&quot;</span>,<span class="st">&quot;public&quot;</span>)</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>                          ,(<span class="st">&quot;src&quot;</span>,<span class="st">&quot;src&quot;</span>)]</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>             , projOutDir <span class="ot">=</span> <span class="st">&quot;public&quot;</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>             , projMainIs <span class="ot">=</span> <span class="st">&quot;src/Main.hs&quot;</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>             }</span></code></pre></div>
<p>The project name (projName) is important, that decides what .fcgi
file name is outputted, what .sock file name is outputted, and etc.</p>
<p>projDirs tells Kibro where everything is. It is a list of
(place,relative path) tuples. app refers to where the Kibro stuff like
Lighttpd and FastCGI should go, among other things that may be added in
future. lighttpd refers to where lighttpd.conf is, and where
lighttpd.pid and custom.conf should be written. fastcgi is where
fastcgi.pid should be written, and $projName.sock will be put. public is
the public httpd directory (aka www-root or static), and $projName.fcgi
will be put here so that Lighttpd can access it. (You can make it not
directly accessible from the outside, read below). And finally, src is
where your web site’s source code is (i.e. where to cd to when
performing the build).</p>
<p>projOutDir tells Kibro where to output $projName.fcgi. projMainIs
tells Kibro where the main web site file is.</p>
<p>All these paths are accessed relative to the project directory.</p>
<h3
id="integrating-your-fastcgi-process-with-an-existing-web-site">Integrating
your FastCGI process with an existing web site</h3>
<p>This is one old Kibro does not address at all. It’s great to work in
a confined directory on a special port like 3000, but at some point you
need to deploy it on a real existing web server. Panda has this problem.
It expects to be in the root directory. So that when I wanted to setup
this blog as /blog, I had issues. All of the links on the blog software
refer to a root directory (/), so I can’t simply change the Kibro page
regexes. However, Panda’s issue is not solvable by Kibro, because it is
just a problem of hard coding paths. Kibro’s issue is integrating
nicely, which is really the question of how to deal with the Lighttpd
configuration.</p>
<p>My solution is that seeing as Kibro can output your .fcgi program
anywhere, you can therefore put it in your web server’s root directory
(actually, I don’t think you have to do this for Lighttpd to be able to
access it<a href="#fn4" class="footnote-ref" id="fnref4"
role="doc-noteref"><sup>4</sup></a>). After reading about Lighttpd’s
configuration syntax a little more, I discovered a very nice way to get
your FastCGI application onto an existing server under a directory.</p>
<p>The obvious way is to simply directly access foo.fcgi.</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>fastcgi<span class="op">.</span>server <span class="ot">=</span> (<span class="st">&quot;blog.fcgi&quot;</span> <span class="ot">=&gt;</span> ((<span class="st">&quot;socket&quot;</span> <span class="ot">=&gt;</span> <span class="st">&quot;/var/www/chrisdone/blog/app/fastcgi/blog.sock&quot;</span>))</span></code></pre></div>
<p>But then how can you have multiple pages on your FastCGI application?
You need the 404-handler.</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>server<span class="op">.</span><span class="fu">error</span><span class="op">-</span>handler<span class="op">-</span><span class="dv">404</span> <span class="ot">=</span> <span class="st">&quot;/blog/public/blog.fcgi&quot;</span></span></code></pre></div>
<p>But if we set a 404-handler to a particular FastCGI application, what
about the others? What if I want this blog, and another FastCGI
application which can handle any path under some directory? Then I can
use the $HTTP[“url”] syntax:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>fastcgi<span class="op">.</span>server <span class="ot">=</span> (<span class="st">&quot;blog.fcgi&quot;</span> <span class="ot">=&gt;</span> ((<span class="st">&quot;socket&quot;</span> <span class="ot">=&gt;</span> <span class="st">&quot;/var/www/chrisdone/blog/app/fastcgi/blog.sock&quot;</span>))</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>                 ,<span class="st">&quot;test.fcgi&quot;</span> <span class="ot">=&gt;</span> ((<span class="st">&quot;socket&quot;</span> <span class="ot">=&gt;</span> <span class="st">&quot;/var/www/chrisdone/test.sock&quot;</span>)))</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>server<span class="op">.</span><span class="fu">error</span><span class="op">-</span>handler<span class="op">-</span><span class="dv">404</span> <span class="ot">=</span> <span class="st">&quot;/blog/public/blog.fcgi&quot;</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="op">$</span><span class="dt">HTTP</span>[<span class="st">&quot;url&quot;</span>] <span class="op">=~</span> <span class="st">&quot;^/peanuts&quot;</span> {</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>   server<span class="op">.</span><span class="fu">error</span><span class="op">-</span>handler<span class="op">-</span><span class="dv">404</span> <span class="ot">=</span> <span class="st">&quot;/test.fcgi&quot;</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
<p>This means that any URL that starts with ^/peanuts will be handled by
test.fcgi, as seen in the link just above! This will work with any
regex. And, of course, if Panda wasn’t so greedy, it could be nudged
into a path like ^/blog.</p>
<p>For those curious my full lighttpd.conf entry for chrisdone.com
is:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="st">&quot; =&gt; &quot;</span><span class="op">/</span><span class="dv">1</span><span class="st">&quot;) # Page 1 of blog</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="st">   server.error-handler-404 = &quot;</span><span class="op">/</span>blog<span class="op">/</span>public<span class="op">/</span>blog<span class="op">.</span>fcgi<span class="st">&quot;</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="st">   $HTTP[&quot;</span>url<span class="st">&quot;] =~ &quot;</span><span class="op">^/</span>peanuts<span class="st">&quot; {</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="st">      server.error-handler-404 = &quot;</span><span class="op">/</span>test<span class="op">.</span>fcgi<span class="st">&quot;</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="st">   }</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a><span class="st">}</span></span></code></pre></div>
<p>What about kibro start and kibro stop etc? Well, I am going to add a
setting of whether or not to touch Lighttpd. This means that both of
these commands will only deal with building, starting and stopping only
the FastCGI process and you can work happily away on your
application!</p>
<p>##New Kibro</p>
<p>It’s pretty much the same interface. All the commands are the same,
and the directory structure is the same for the most part.</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>chris<span class="op">@</span>chrisdesktop<span class="op">:~$</span> kibro new fooble</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Creating</span> directory structure <span class="op">...</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>  <span class="op">/</span>home<span class="op">/</span>chris<span class="op">/</span>fooble<span class="op">/</span>app</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">/</span>home<span class="op">/</span>chris<span class="op">/</span>fooble<span class="op">/</span>app<span class="op">/</span>lighttpd</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">/</span>home<span class="op">/</span>chris<span class="op">/</span>fooble<span class="op">/</span>app<span class="op">/</span>fastcgi</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">/</span>home<span class="op">/</span>chris<span class="op">/</span>fooble<span class="op">/</span>public</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">/</span>home<span class="op">/</span>chris<span class="op">/</span>fooble<span class="op">/</span>src</span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a><span class="dt">Finished</span> creating directory structure<span class="op">.</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a><span class="dt">Writing</span> Main.hs <span class="op">...</span> done<span class="op">.</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a><span class="dt">Writing</span> lighttpd<span class="op">.</span>conf <span class="op">...</span> done<span class="op">.</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a><span class="dt">Writing</span> fooble<span class="op">.</span>kibro <span class="op">...</span> done<span class="op">.</span></span></code></pre></div>
<p>Starting and stopping is exactly the same.</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>chris<span class="op">@</span>chrisdesktop<span class="op">:~$</span> cd fooble<span class="op">/</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>chris<span class="op">@</span>chrisdesktop<span class="op">:~/</span>fooble<span class="op">$</span> kibro start</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="dt">Reading</span> config file fooble<span class="op">.</span>kibro <span class="op">...</span> done<span class="op">.</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="dt">Not</span> yet built, building <span class="op">...</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>[<span class="dv">1</span> <span class="kw">of</span> <span class="dv">1</span>] <span class="dt">Compiling</span> <span class="dt">Main</span>             ( <span class="op">/</span>home<span class="op">/</span>chris<span class="op">/</span>fooble<span class="op">/</span>src<span class="op">/</span>Main.hs, <span class="op">/</span>home<span class="op">/</span>chris<span class="op">/</span>fooble<span class="op">/</span>src<span class="op">/</span>Main.o )</span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a><span class="dt">Linking</span> public<span class="op">/</span>fooble<span class="op">.</span>fcgi <span class="op">...</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a><span class="dt">Finished</span> building<span class="op">.</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a><span class="dt">Spawning</span> <span class="dt">FastCGI</span> daemon <span class="op">...</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>spawn<span class="op">-</span>fcgi<span class="op">.</span>c<span class="op">.</span><span class="dv">197</span><span class="op">:</span> child spawned successfully<span class="op">:</span> <span class="dt">PID</span><span class="op">:</span> <span class="dv">26287</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a><span class="dt">Done</span><span class="op">.</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a><span class="dt">Spawning</span> <span class="dt">Lighttpd</span> daemon <span class="op">...</span></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a><span class="dt">Lighttpd</span> daemon started<span class="op">.</span></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a>chris<span class="op">@</span>chrisdesktop<span class="op">:~/</span>fooble<span class="op">$</span> kibro stop</span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a><span class="dt">Reading</span> config file fooble<span class="op">.</span>kibro <span class="op">...</span> done<span class="op">.</span></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a><span class="dt">Stopping</span> <span class="dt">Lighttpd</span> <span class="op">...</span></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a><span class="dt">Stopping</span> <span class="dt">FastCGI</span> <span class="op">...</span></span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true" tabindex="-1"></a>chris<span class="op">@</span>chrisdesktop<span class="op">:~/</span>fooble<span class="op">$</span></span></code></pre></div>
<p>Examples</p>
<p>Once I have finished refactoring the library and the executable, I am
going to make a couple examples.</p>
<ul>
<li>An interface to all the Lojban library goodies I’ve been working on.
This will require a couple interesting kinds of state 1) Maintaining a
database that takes a while to generate, 2) maintaining a pipe to a
process.</li>
<li>Maybe I can patch Panda to support a path other than /.</li>
</ul>
<p>I’ll blog about those later and provide all source code etc so that
you can Try It At Home<a href="#fn5" class="footnote-ref" id="fnref5"
role="doc-noteref"><sup>5</sup></a> and comment on the blog about how it
doesn’t work on your Macs. :-P</p>
<section class="footnotes footnotes-end-of-document"
role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>The paths that you provide in
Lighttpd’s configuration need to be absolute paths or else it fails. For
this reason I have made Kibro be the maintainer of those values.<a
href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p>I had some locking problems with the
HDBC Sqlite3 library and generally I don’t feel very happy with it. I’ll
probably try Postgres next.<a href="#fnref2" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn3" role="doc-endnote"><p>Yeah, I know. It’s just the output of
Show. Cheeky, huh? ;D … I may write a different one later, if called
for, but it’s not a priority.<a href="#fnref3" class="footnote-back"
role="doc-backlink">↩︎</a></p></li>
<li id="fn4" role="doc-endnote"><p>document-root combined with
$HTTP[“url”]? I’ll have to test this.<a href="#fnref4"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn5" role="doc-endnote"><p>No Windows support. (Does it matter?
Who runs web servers on Windows anyway?)<a href="#fnref5"
class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2008-10-12 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Sun, 12 Oct 2008 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>
<item><title><![CDATA[GHCi on Acid]]></title><link>https://chrisdone.com/posts/ghci-on-acid</link><guid>https://chrisdone.com/posts/ghci-on-acid</guid><description><![CDATA[<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>GHCi on Acid</title>
    <style>
    h1 a, h2 a,h3 a,h4 a,h5 a {
      text-decoration: none;
}
h1 a:hover, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover {
      text-decoration: underline;
      color: #1a6e8e;
}

.footnote-back {
  margin-left: 0.5em;
}
      #footnotes li:target {
          background: #eeeeee;
          border-radius: 0.5em;
          padding: 1px 1em;
      }
      body {
      max-width: 40em;
      margin: .5in auto;
      font-size: 18px;
      font-family: serif;
      line-height: 1.5;
      }
      pre, code {
      font-size: 16px;
      word-wrap: break-word;
      }
      pre {
      padding-left: 1em;
      line-height: 1.5em;
      border-left: 5px solid #efefef;
      }
      a {
      color: #1a6e8e
      }
      .menu a {
      margin-right: 1em;
      }
      h1,h2,h3,h4,h5,h6 {
      font-family: Helvetica;
      }

      h1 a,h2 a,h3 a,h4 a {
      color: inherit;
      }

      .post-1,.post-2{
      margin-bottom: 0.5em;
      }

      .author {
      display: none;
      }

      footer {
      margin-top: 1.5em;
      padding-top: 1.5em;
          border-top: 1px solid #ccc;
      margin-bottom: 2em
      }
    hr {
  border: 0.5px solid #ccc;
}

      footer span {
      display: none;
      }

      img {
      max-width: 100%
      }
      pre.sourceCode span.st {
      color: #366354
      }
      pre.sourceCode span.kw {
      color: #397460
      }
      pre.sourceCode span.fu {
      color: #8f4e8b
      }
      pre.sourceCode span.ot {
      color: #2e659c
      }
      pre.sourceCode span.dt {
      color: #4F4371
      }
      pre.sourceCode span.co {
      color: #666
      }
      @media(max-width:767px){
      body { margin: 1px 4px; }
      h1, h2, .menu { margin: 0; }
      h1 { font-size: 1.5em; }
      h2 { font-size: 1.125em; }
      h3 { font-size: 1.0125em; }
      .menu a { margin-right: 0.1em; }
      #archive { margin-left: 1em; margin-top: 0; padding: 0}
      #archive .post-1, #archive .post-2 {
      margin-bottom: 0.1em;
      }
      }
      .footnote-ref { text-decoration: none; }
    li { margin-top: 0.5em; margin-bottom: 0.5em; }
      .human {color: grey}
    </style>
  </head>
  <body>
    <div class="page-wrap">

<h1>GHCi on Acid</h1>

<p><small class='human'>Note: An LLM was not used in writing this article.</small></p>

<p>GHCi on Acid is an extension to GHCi (Interactive GHC) for adding
useful lambdabot features. This post details how to use it.</p>
<p>I use GHCi inside Emacs, so having GOA additionally.. increases my
productivity.</p>
<h2 id="what-does-it-do">What does it do?</h2>
<p>Here are some examples of the commands that can be used.</p>
<p>The :instances command shows all the instances of a class:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="dt">GOA</span><span class="op">&gt;</span> <span class="op">:</span>instances <span class="dt">Monad</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a> ((<span class="ot">-&gt;</span>) r), <span class="dt">ArrowMonad</span> a, <span class="dt">Cont</span> r, <span class="dt">ContT</span> r m, <span class="dt">Either</span> e, <span class="dt">ErrorT</span> e m, <span class="dt">IO</span>,</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> <span class="dt">Maybe</span>, <span class="dt">RWS</span> r w s, <span class="dt">RWST</span> r w s m, <span class="dt">Reader</span> r, <span class="dt">ReaderT</span> r m, <span class="dt">ST</span> s, <span class="dt">State</span> s,</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a> <span class="dt">StateT</span> s m, <span class="dt">Writer</span> w, <span class="dt">WriterT</span> w m, []</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="dt">GOA</span><span class="op">&gt;</span> <span class="op">:</span>instances <span class="dt">Arrow</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a> (<span class="ot">-&gt;</span>), <span class="dt">Kleisli</span> m</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="dt">GOA</span><span class="op">&gt;</span> <span class="op">:</span>instances <span class="dt">Num</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a> <span class="dt">Double</span>, <span class="dt">Float</span>, <span class="dt">Int</span>, <span class="dt">Integer</span></span></code></pre></div>
<p>Here we have the :hoogle command, for querying the Hoogle database.
Great for looking for functions of a specific type:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="dt">GOA</span><span class="op">&gt;</span> <span class="op">:</span>hoogle <span class="dt">Arrow</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a> <span class="dt">Control.Arrow</span><span class="ot"> ::</span> <span class="kw">module</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="dt">Control.Arrow.Arrow</span><span class="ot"> ::</span> <span class="kw">class</span> <span class="dt">Arrow</span> a</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="dt">Control.Arrow.ArrowZero</span><span class="ot"> ::</span> <span class="kw">class</span> <span class="dt">Arrow</span> a <span class="ot">=&gt;</span> <span class="dt">ArrowZero</span> a</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="dt">GOA</span><span class="op">&gt;</span> <span class="op">:</span>hoogle b <span class="ot">-&gt;</span> (a <span class="ot">-&gt;</span> b) <span class="ot">-&gt;</span> <span class="dt">Maybe</span> a <span class="ot">-&gt;</span> b</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a> Prelude.maybe<span class="ot"> ::</span> b <span class="ot">-&gt;</span> (a <span class="ot">-&gt;</span> b) <span class="ot">-&gt;</span> <span class="dt">Maybe</span> a <span class="ot">-&gt;</span> b</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>Data.Maybe.maybe<span class="ot"> ::</span> b <span class="ot">-&gt;</span> (a <span class="ot">-&gt;</span> b) <span class="ot">-&gt;</span> <span class="dt">Maybe</span> a <span class="ot">-&gt;</span> b</span></code></pre></div>
<p>The :source command gives a link to the source code of a module
(sometimes you are curious):</p>
<p>GOA&gt; :source Data.Maybe
http://darcs.haskell.org/packages/base/Data/Maybe.hs Similarly, :docs
gives a link to the documentation of a module.</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="dt">GOA</span><span class="op">&gt;</span> <span class="op">:</span>docs <span class="dt">Data.Maybe</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a> http<span class="op">://</span>haskell<span class="op">.</span>org<span class="op">/</span>ghc<span class="op">/</span>docs<span class="op">/</span>latest<span class="op">/</span>html<span class="op">/</span>libraries<span class="op">/</span>base<span class="op">/</span><span class="dt">Data</span><span class="op">-</span><span class="dt">Maybe</span><span class="op">.</span>html</span></code></pre></div>
<p>:index is a nice way to search modules.</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="dt">GOA</span><span class="op">&gt;</span> <span class="op">:</span><span class="fu">index</span> <span class="dt">Monad</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a> <span class="dt">Control.Monad</span>, <span class="dt">Prelude</span>, <span class="dt">Control.Monad.Reader</span>,</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a> <span class="dt">Control.Monad.Writer</span>, <span class="dt">Control.Monad.State</span>, <span class="dt">Control.Monad.RWS</span>,</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a> <span class="dt">Control.Monad.Identity</span>, <span class="dt">Control.Monad.Cont</span>, <span class="dt">Control.Monad.Error</span>,</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a> <span class="dt">Control.Monad.List</span></span></code></pre></div>
<p>Then we have :pl, which shows the pointless (or: point-free) way of
writing a function, which is very useful for learning and sometimes for
fun:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="dt">GOA</span><span class="op">&gt;</span> <span class="op">:</span>pl (\x <span class="ot">-&gt;</span> x <span class="op">*</span> x)</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a> join (<span class="op">*</span>)</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="dt">GOA</span><span class="op">&gt;</span> <span class="op">:</span>pl (\x y <span class="ot">-&gt;</span> (x <span class="op">*</span> <span class="dv">5</span>) <span class="op">+</span> (y <span class="op">*</span> <span class="dv">5</span>))</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a> (<span class="op">.</span> (<span class="dv">5</span> <span class="op">*</span>)) <span class="op">.</span> (<span class="op">+</span>) <span class="op">.</span> (<span class="dv">5</span> <span class="op">*</span>)</span></code></pre></div>
<p>And finally, the best of them all; :bs:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="dt">GOA</span><span class="op">&gt;</span> <span class="op">:</span>bs</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a> <span class="op">:</span>)</span></code></pre></div>
<p>Botsnack.</p>
<h2 id="how-to-install-it">How to install it</h2>
<p>You need to download and install lamdabot. This is easier than it
sounds.</p>
<h3 id="install-happy">Install happy</h3>
<p>First, we need “happy”, which is a parser:</p>
<pre><code>sudo cabal install happy</code></pre>
<p>Right, that’s installed to ~/.cabal/bin, so you need to make sure
~/.cabal/bin is in your PATH. In Bash, you can do this by adding</p>
<pre><code>export PATH=&quot;~/.cabal/bin:$PATH&quot;</code></pre>
<p>to your .bashrc.</p>
<h3 id="try-it-out">Try it out:</h3>
<div class="sourceCode" id="cb9"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>chris<span class="op">@</span>chrisdesktop<span class="op">:~$</span> happy <span class="co">--version</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Happy</span> <span class="dt">Version</span> <span class="fl">1.17</span> <span class="dt">Copyright</span> (c) <span class="dv">1993</span><span class="op">-</span><span class="dv">1996</span> <span class="dt">Andy</span> <span class="dt">Gill</span>, <span class="dt">Simon</span> <span class="dt">Marlow</span> (c) <span class="dv">1997</span><span class="op">-</span><span class="dv">2005</span> <span class="dt">Simon</span> <span class="dt">Marlow</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="dt">Happy</span> is a <span class="dt">Yacc</span> for <span class="dt">Haskell</span>, <span class="fu">and</span> comes with <span class="dt">ABSOLUTELY</span> <span class="dt">NO</span> <span class="dt">WARRANTY</span><span class="op">.</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a><span class="dt">This</span> program is free software; you can redistribute it <span class="fu">and</span><span class="op">/</span><span class="fu">or</span> modify</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>it under the terms given <span class="kw">in</span> the file <span class="dt">&#39;LICENSE&#39;</span> distributed with</span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>the <span class="dt">Happy</span> sources<span class="op">.</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a><span class="dt">If</span> yours isn’t found, you need to restart bash, <span class="fu">or</span> <span class="kw">type</span> export <span class="dt">PATH</span><span class="ot">=</span><span class="st">&quot;~/.cabal/bin:$PATH&quot;</span><span class="op">.</span></span></code></pre></div>
<h3 id="grab-hoogle">Grab Hoogle</h3>
<p>We need Hoogle for lambdabot’s Hoogle functionality.</p>
<pre><code>sudo cabal install hoogle</code></pre>
<h3 id="download-and-build-lambdabot">Download and build lambdabot</h3>
<p>You need darcs. We’re using darcs. It should be on your package
manager, otherwise install it from the web site. I don’t know why it’s
not on Hackage.</p>
<p>Now, we grab lambdabot from code.haskell.org:</p>
<pre><code>darcs get http://code.haskell.org/lambdabot/

cd lambdabot &amp;&amp; sudo ./build</code></pre>
<p>./build downloads and installs everything we need, and builds
lambdabot for us.</p>
<p>Once that’s built, we can install GOA.</p>
<h3 id="download-build-and-install-goa">Download, build and install
GOA</h3>
<p>Just install with your usual cabal install goa method. :)</p>
<p>Finally, copy the dot-ghci from goa/ to your ~/.ghci file, and edit
the lambdabot home directory to where your lambdabot directory is. Mine
looks like this:</p>
<div class="sourceCode" id="cb12"><pre
class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="op">:</span>m <span class="op">-</span> <span class="dt">Prelude</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="op">:</span>m <span class="op">+</span> <span class="dt">GOA</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>setLambdabotHome <span class="st">&quot;/var/www/chrisdone/lambdabot-personal&quot;</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a><span class="op">:</span>def bs        lambdabot <span class="st">&quot;botsnack&quot;</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a><span class="op">:</span>def pl        lambdabot <span class="st">&quot;pl&quot;</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a><span class="op">:</span>def <span class="fu">index</span>     lambdabot <span class="st">&quot;index&quot;</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a><span class="op">:</span>def docs      lambdabot <span class="st">&quot;docs&quot;</span></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a><span class="op">:</span>def instances lambdabot <span class="st">&quot;instances&quot;</span></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a><span class="op">:</span>def hoogle    lambdabot <span class="st">&quot;hoogle&quot;</span></span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a><span class="op">:</span>def source    lambdabot <span class="st">&quot;fptools&quot;</span></span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a><span class="op">:</span>def <span class="kw">where</span>     lambdabot <span class="st">&quot;where&quot;</span></span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true" tabindex="-1"></a><span class="op">:</span>def version   lambdabot <span class="st">&quot;version&quot;</span></span></code></pre></div>
<p>Now when you run ghci, you will have GOA! Tip: if you accidentally
unload the GOA module, use :m + GOA to load it.</p>


<footer>
  <table style="width:100%">
    <tr>
      <td>© 2008-08-01 <a href="/">Chris Done</a></td>
      <td style="text-align:right"><a href="/posts">Read more posts →</a></td>
    </tr>
  </table>
</footer>

    </div>
    <script>
      var headers = document.querySelectorAll('h1, h2, h3, h4, h5');
    headers.forEach(function(header) {
        var headerId = header.id;
        if (headerId) {
            var anchor = document.createElement('a');
            anchor.href = '#' + headerId;
            anchor.textContent = header.textContent;
            header.textContent = '';
            header.appendChild(anchor);
        }
    });
    </script>
  </body>
</html>
]]></description><pubDate>Fri, 01 Aug 2008 00:00:00 +0100
</pubDate><dc:creator>Chris Done</dc:creator></item>

</channel>
</rss>
