<?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>jaspervdj - All posts</title>
        <link>http://jaspervdj.be</link>
        <description><![CDATA[Personal blog of jaspervdj]]></description>
        <atom:link href="http://jaspervdj.be/rss.xml" rel="self"
                   type="application/rss+xml" />
        <lastBuildDate>Wed, 21 Aug 2024 00:00:00 UT</lastBuildDate>
        <item>
    <title>Turnstyle</title>
    <link>http://jaspervdj.be/posts/2024-08-21-turnstyle.html</link>
    <description><![CDATA[<p>I am delighted and horrified to announce a new graphical programming language
called <a href="https://jaspervdj.be/turnstyle/">Turnstyle</a>. You can see an example below (click to run).</p>
<style type="text/css">
    img.turnstyle, .interpreter svg {
        max-width: 90%;
        margin-bottom: .5em; /* Some space in between svg and terminal */
    }

    .interpreter .terminal {
        text-align: left;
        display: block;
        overflow-y: scroll;
        max-height: 5em;
        background-color: #2228;
        color: #fff;
        padding: .5em;
    }

    .interpreter .terminal pre {
        margin: 0px;
    }

    .interpreter .terminal textarea {
        padding: 0px;
        margin: 0px;
        opacity: 0;
        width: 0px;
        height: 0px;
        border: none;
    }

    .interpreter .terminal:has(textarea:focus) .cursor {
        animation: cursor 1s linear infinite;
    }

    .interpreter .terminal .cursor {
        display: inline-block;
        height: 1.2em;
        margin-bottom: -0.1em;
        width: 0.5em;
        background: #fff;
    }

    @keyframes cursor {
        0%  {  background: transparent; }
        50% {  background: inherit;     }
    }
</style>
<p><img class="turnstyle" src="/images/2024-08-21-turnstyle-loop.svg"></p>
<hr />
<p>In the time leading up to <a href="https://zfoh.ch/zurihac2024">ZuriHac 2024</a> earlier this year, I had been thinking
about <a href="https://www.dangermouse.net/esoteric/piet.html">Piet</a> a little. We ended up working on something else during the
Hackathon, but this was still in the back of my mind.</p>
<p>Some parts of Piets design are utter genius (using areas for number literals,
using hue/lightness as cycles). There are also things I don’t like, such as the
limited amount of colors, the difficulty reusing code, and the lack of a
way to extend it with new primitive operations. I suspect these are part of the
reason nobody has yet tried to write, say, an RDBMS or a web browser in Piet.</p>
<p>Given the amount of attention going to programming languages in the functional
programming community, I was quite surprised nobody had ever tried to do a
functional variant of it (as far as I could find).</p>
<p>I wanted to create something based on <a href="https://en.wikipedia.org/wiki/Lambda_calculus">Lambda Calculus</a>. It forms a nice basis
for a minimal specification, and I knew that while code would still be somewhat
frustrating to write, there is the comforting thought of being able to reuse
almost everything once it’s written.</p>
<figure>
<img src="/images/2024-08-21-turnstyle-cheatsheet.svg" alt="Cheatsheet for the specification" />
<figcaption aria-hidden="true">Cheatsheet for the specification</figcaption>
</figure>
<p>You can see the <a href="https://jaspervdj.be/turnstyle/spec/">full specification here</a>.</p>
<p>After playing around with different designs this is what I landed on. The
guiding principle was to search for a specification that was as simple as
possible, while still covering lambda calculus extended with primitives that,
you know, allow you to interact with computers.</p>
<p>One interesting aspect that I discovered (not invented) is that it’s actually
somewhat more expressive than Lambda Calculus, since you can build Abstract
Syntax Graphs (rather than just Trees). This is illustrated in the loop example
above, which recurses without the need for a fixed-point combinator.</p>
<p>For the full specification and more examples take a look at the <a href="https://jaspervdj.be/turnstyle/">Turnstyle
website</a> and feel free to play around with the sources on <a href="https://github.com/jaspervdj/turnstyle/">GitHub</a>.</p>
<p>Thanks to <a href="https://mazzo.li/">Francesco Mazzoli</a> for useful feedback on the
specification and website.</p>
<script type="text/JavaScript" src="/files/2024-08-21-turnstyle.js"></script>
<script type="text/JavaScript">
    window.onload = () => {
        const examples = document.querySelectorAll("img.turnstyle");
        for (const example of examples) {
            const source = example.src.replace(".svg", ".png");
            example.onclick = async (event) => {
                event.preventDefault();
                const itp = new Interpreter(document, source);
                await itp.load();
                example.replaceWith(itp.element);
                itp.run();
            };
        }
    };
</script>]]></description>
    <pubDate>Wed, 21 Aug 2024 00:00:00 UT</pubDate>
    <guid>http://jaspervdj.be/posts/2024-08-21-turnstyle.html</guid>
    <dc:creator>Jasper Van der Jeugt</dc:creator>
</item>
<item>
    <title>Lazy Layout</title>
    <link>http://jaspervdj.be/posts/2023-07-22-lazy-layout.html</link>
    <description><![CDATA[<h1 id="prelude">Prelude</h1>
<p>This blogpost is written in <a href="https://github.com/jaspervdj/jaspervdj/blob/master/posts/2023-07-22-lazy-layout.nix">reproducible</a> <a href="https://wiki.haskell.org/Literate_programming">Literate Haskell</a>, so we need some
imports first.</p>
<details>
<summary>
Show me the exact imports…
</summary>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE DeriveFoldable    #-}</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE DeriveFunctor     #-}</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE DeriveTraversable #-}</span></span>
<span id="cb1-4"><a href="#cb1-4" 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-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Codec.Picture</span>          <span class="kw">as</span> <span class="dt">JP</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Codec.Picture.Types</span>    <span class="kw">as</span> <span class="dt">JP</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span>           <span class="dt">Control.Monad.ST</span>       (runST)</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span>           <span class="dt">Data.Bool</span>              (bool)</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span>           <span class="dt">Data.Foldable</span>          (for_)</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span>           <span class="dt">Data.List</span>              (isSuffixOf, partition)</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span>           <span class="dt">Data.List.NonEmpty</span>     (<span class="dt">NonEmpty</span> (..))</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span>           <span class="dt">System.Environment</span>     (getArgs)</span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span>           <span class="dt">System.Random</span>          (<span class="dt">RandomGen</span>, newStdGen)</span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span>           <span class="dt">System.Random.Stateful</span> (randomM, runStateGen)</span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span>           <span class="dt">Text.Read</span>              (readMaybe)</span></code></pre></div>
</details>
<h1 id="introduction">Introduction</h1>
<p>Haskell is not my only interest — I have also been quite into photography for
the past decade. Recently, I was considering moving some of the stuff I have
on various social networks to a self-hosted solution.</p>
<p>Tumblr in particular has a fairly nice way to do photo sets, where these can
be organised in rows and columns. I wanted to see if I could mimic this in a
recursive way, where rows and columns can be subdivided further.</p>
<p>One important constraint is that is that we want to present each picture as
the photographer envisioned it: concretely, we can scale it up or down
(preserving the aspect ratio), but we can’t crop out parts.</p>
<p>Order is also important in photo essays, so we want the author to specify the
photo collage in a declarative way by indicating if horizontal (H) or vertical
(V) subdivision should be used, creating a tree. For example:</p>
<pre><code>H img1.jpg
  (V img2.jpg
     (H img3.jpg
        img4.jpg))</code></pre>
<p>The program should then determine the exact size and position of each image,
so that we get a fully filled rectangle without any borders or filler:</p>
<p><img src="/images/2023-07-22-lazy-layout-example-1.jpg" /></p>
<p>We will use a technique called <em>circular programming</em> that builds on Haskell’s
laziness to achieve this in an elegant way.
These days, it is maybe more commonly referred to as the <code>repmin</code> problem.
This was first described by Richard S. Bird in <em>“Using circular programs to
eliminate multiple traversals of data”</em> in 1984, which <strong>predates Haskell!</strong></p>
<details>
<summary>
Give me a refresher on <code>repmin</code> please…
</summary>
<h2 id="interlude-repmin">Interlude: repmin</h2>
<p>Given a simple tree type:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell literate"><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">Tree</span> a</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>  <span class="ot">=</span> <span class="dt">Leaf</span> a</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>  <span class="op">|</span> <span class="dt">Branch</span> (<span class="dt">Tree</span> a) (<span class="dt">Tree</span> a)</span></code></pre></div>
<p>We would like to write a function <code>repmin</code> which replaces each value in each
<code>Leaf</code> with the global minimum in the tree. This is easily done by first
finding the global minimum, and then replacing it everywhere:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ot">repmin_2pass ::</span> <span class="dt">Ord</span> a <span class="ot">=&gt;</span> <span class="dt">Tree</span> a <span class="ot">-&gt;</span> <span class="dt">Tree</span> a</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>repmin_2pass t <span class="ot">=</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">let</span> globalmin <span class="ot">=</span> findmin t <span class="kw">in</span> rep globalmin t</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>  findmin (<span class="dt">Leaf</span> x)     <span class="ot">=</span> x</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>  findmin (<span class="dt">Branch</span> l r) <span class="ot">=</span> <span class="fu">min</span> (findmin l) (findmin r)</span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>  rep x (<span class="dt">Leaf</span> _)     <span class="ot">=</span> <span class="dt">Leaf</span> x</span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>  rep x (<span class="dt">Branch</span> l r) <span class="ot">=</span> <span class="dt">Branch</span> (rep x l) (rep x r)</span></code></pre></div>
<p>However, this requires two passes over the tree. We can do better by using
Haskell’s laziness:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ot">repmin_1pass ::</span> <span class="dt">Ord</span> a <span class="ot">=&gt;</span> <span class="dt">Tree</span> a <span class="ot">-&gt;</span> <span class="dt">Tree</span> a</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>repmin_1pass t <span class="ot">=</span> t&#39;</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>  (t&#39;, globalmin) <span class="ot">=</span> repmin t</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>  repmin (<span class="dt">Leaf</span>   x)   <span class="ot">=</span> (<span class="dt">Leaf</span> globalmin, x)</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>  repmin (<span class="dt">Branch</span> l r) <span class="ot">=</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>    (<span class="dt">Branch</span> l&#39; r&#39;, <span class="fu">min</span> lmin rmin)</span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>   <span class="kw">where</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>    (l&#39;, lmin) <span class="ot">=</span> repmin l</span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>    (r&#39;, rmin) <span class="ot">=</span> repmin r</span></code></pre></div>
<p>There is an apparent circular dependency here, where <code>repmin</code> uses <code>globalmin</code>,
but also computes it. This is possible because we never need to evaluate
<code>globalmin</code> – it can be stored as a <a href="https://www.youtube.com/watch?v=I4lnCG18TaY">thunk</a>.
For more details, please see the very accessible original paper
(<code>https://doi.org/10.1007/BF00264249</code>).</p>
</details>
<h1 id="starting-out-with-some-types">Starting out with some types</h1>
<p>We start out by giving an elegant algebraic definition for a collage:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Collage</span> a</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>  <span class="ot">=</span> <span class="dt">Singleton</span>  a</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>  <span class="op">|</span> <span class="dt">Horizontal</span> (<span class="dt">Collage</span> a) (<span class="dt">Collage</span> a)</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">|</span> <span class="dt">Vertical</span>   (<span class="dt">Collage</span> a) (<span class="dt">Collage</span> a)</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">deriving</span> (<span class="dt">Foldable</span>, <span class="dt">Functor</span>, <span class="dt">Show</span>, <span class="dt">Traversable</span>)</span></code></pre></div>
<p>We use a higher-order type, which allows us to work with collages of filepaths
as well as actual images (among other things). <code>deriving</code> instructs the compiler
to generate some boilerplate code for us. This allows us to concisely read all
images using <code>traverse</code>:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>readCollage</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="ot">  ::</span> <span class="dt">Collage</span> <span class="dt">FilePath</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> <span class="dt">IO</span> (<span class="dt">Collage</span> (<span class="dt">JP.Image</span> <span class="dt">JP.PixelRGB8</span>))</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>readCollage <span class="ot">=</span> <span class="fu">traverse</span> <span class="op">$</span> \path <span class="ot">-&gt;</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>  JP.readImage path <span class="op">&gt;&gt;=</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>  <span class="fu">either</span> <span class="fu">fail</span> (<span class="fu">pure</span> <span class="op">.</span> JP.convertRGB8)</span></code></pre></div>
<p>We use the <a href="https://hackage.haskell.org/package/JuicyPixels">JuicyPixels</a> library to read and write images.
The image type in this library can be a bit verbose since it is parameterised
around the colour space.</p>
<p>During the layout pass, we don’t really care about this complexity.
We only need the relative sizes of the images and not their content.
We introduce a typeclass to do just that:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode haskell literate"><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">Size</span> <span class="ot">=</span> <span class="dt">Sz</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>  {<span class="ot"> szWidth  ::</span> <span class="dt">Rational</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>  ,<span class="ot"> szHeight ::</span> <span class="dt">Rational</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>  } <span class="kw">deriving</span> (<span class="dt">Show</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">class</span> <span class="dt">Sized</span> a <span class="kw">where</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- | Retrieve the width and height of an image.</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Both numbers must be strictly positive.</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a><span class="ot">  sizeOf ::</span> a <span class="ot">-&gt;</span> <span class="dt">Size</span></span></code></pre></div>
<p>We use the <code>Rational</code> type for width and height.
We are only subdividing the 2D space, so we do not need irrational numbers,
and having infinite precision is convenient.</p>
<p>The instance for the JuicyPixels image type is simple:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Sized</span> (<span class="dt">JP.Image</span> p) <span class="kw">where</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>  sizeOf img <span class="ot">=</span> <span class="dt">Sz</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>    { szWidth  <span class="ot">=</span> <span class="fu">fromIntegral</span> <span class="op">$</span> JP.imageWidth  img</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>    , szHeight <span class="ot">=</span> <span class="fu">fromIntegral</span> <span class="op">$</span> JP.imageHeight img</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>    }</span></code></pre></div>
<h1 id="laying-out-two-images">Laying out two images</h1>
<p>If we look at the finished image, it may seem like a hard problem to find a
configuration that fits all the images with a correct aspect ratio.</p>
<p>But we can use induction to arrive at a fairly straightforward solution. Given
two images, it is always possible to put them beside or above each other by
scaling them up or down to match them in height or width respectively. This
creates a bigger image. We can then repeat this process until just one image is
left.</p>
<p><img src="/images/2023-07-22-lazy-layout-tree.jpg" /></p>
<p>However, this is quite a naive approach since we end up making way too many
copies, and the repeated resizing could also result in a loss of resolution. We
would like to compute the entire layout first, and then render everything in one
go. Still, we can start by formalising what happens for two images and then
work our way up.</p>
<p>We can represent the layout of an individual image by its position and size.
We use simple <em>(x, y)</em> coordinates for the position and a scaling factor
(relative to the original size of the image) for its size.</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Transform</span> <span class="ot">=</span> <span class="dt">Tr</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>  {<span class="ot"> trX     ::</span> <span class="dt">Rational</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>  ,<span class="ot"> trY     ::</span> <span class="dt">Rational</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>  ,<span class="ot"> trScale ::</span> <span class="dt">Rational</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>  } <span class="kw">deriving</span> (<span class="dt">Show</span>)</span></code></pre></div>
<p>Armed with the <code>Size</code> and <code>Transform</code> types, we have enough to tackle the
“mathy” bits.</p>
<p>Let’s look at the horizontal case first and write a function that computes a
transform for both left and right images, as well as the size of the result.</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="ot">horizontal ::</span> <span class="dt">Size</span> <span class="ot">-&gt;</span> <span class="dt">Size</span> <span class="ot">-&gt;</span> (<span class="dt">Transform</span>, <span class="dt">Transform</span>, <span class="dt">Size</span>)</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>horizontal (<span class="dt">Sz</span> lw lh) (<span class="dt">Sz</span> rw rh) <span class="ot">=</span></span></code></pre></div>
<p>We want to place image <code>l</code> beside image <code>r</code>, producing a nicely filled
rectangle. Intuitively, we should be matching the height of both images.</p>
<p><img src="/images/2023-07-22-lazy-layout-lwlh-rwrh.png" /></p>
<p>There are different ways to do this — we could shrink the taller image,
enlarge the shorter image, or something in between. We make a choice to always
shrink the taller image, as this doesn’t compromise the sharpness of the result.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>  <span class="kw">let</span> height <span class="ot">=</span> <span class="fu">min</span> lh rh</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>      lscale <span class="ot">=</span> height <span class="op">/</span> lh</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>      rscale <span class="ot">=</span> height <span class="op">/</span> rh</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>      width  <span class="ot">=</span> lscale <span class="op">*</span> lw <span class="op">+</span> rscale <span class="op">*</span> rw <span class="kw">in</span></span></code></pre></div>
<p>With the scale for both left and right images, we can compute the left
and right transforms. The left image is simply placed at <em>(0, 0)</em> and we need
to offset the right image depending on the (scaled) size of the left image.</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a>  ( <span class="dt">Tr</span> <span class="dv">0</span>             <span class="dv">0</span> lscale</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>  , <span class="dt">Tr</span> (lscale <span class="op">*</span> lw) <span class="dv">0</span> rscale</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>  , <span class="dt">Sz</span> width height</span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>  )</span></code></pre></div>
<p>Composing images vertically is similar, just matching the widths rather than the
heights of the two images and moving the bottom image below the top one:</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="ot">vertical ::</span> <span class="dt">Size</span> <span class="ot">-&gt;</span> <span class="dt">Size</span> <span class="ot">-&gt;</span> (<span class="dt">Transform</span>, <span class="dt">Transform</span>, <span class="dt">Size</span>)</span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>vertical (<span class="dt">Sz</span> tw th) (<span class="dt">Sz</span> bw bh) <span class="ot">=</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">let</span> width  <span class="ot">=</span> <span class="fu">min</span> tw bw</span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>      tscale <span class="ot">=</span> width <span class="op">/</span> tw</span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>      bscale <span class="ot">=</span> width <span class="op">/</span> bw</span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>      height <span class="ot">=</span> tscale <span class="op">*</span> th <span class="op">+</span> bscale <span class="op">*</span> bh <span class="kw">in</span></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a>  ( <span class="dt">Tr</span> <span class="dv">0</span> <span class="dv">0</span>             tscale</span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a>  , <span class="dt">Tr</span> <span class="dv">0</span> (tscale <span class="op">*</span> th) bscale</span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a>  , <span class="dt">Sz</span> width height</span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a>  )</span></code></pre></div>
<h1 id="composing-transformations">Composing transformations</h1>
<p>Now that we’ve solved the problem of combining two images and placing them,
we can apply this to our tree of images. To this end, we need to compose
multiple transformations.</p>
<p>Whenever we think about composing things in Haskell, it’s good to ask ourselves
if what we’re trying to compose is a <a href="https://typeclasses.com/monoid">Monoid</a>. A Monoid needs an identity
element (<code>mempty</code>) and a Semigroup instance, the latter of which contains just
an associative binary operator (<code>&lt;&gt;</code>).</p>
<p>The identity transform is just offsetting by 0 and scaling by 1:</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Monoid</span> <span class="dt">Transform</span> <span class="kw">where</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>  <span class="fu">mempty</span> <span class="ot">=</span> <span class="dt">Tr</span> <span class="dv">0</span> <span class="dv">0</span> <span class="dv">1</span></span></code></pre></div>
<p>Composing two transformations using <code>&lt;&gt;</code> requires a bit more thinking.
In this case, <code>a &lt;&gt; b</code> means applying transformation <code>a</code> after transformation
<code>b</code>, so we will need to apply the scale of <code>b</code> to all parts of <code>a</code>:</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Semigroup</span> <span class="dt">Transform</span> <span class="kw">where</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Tr</span> ax ay as <span class="op">&lt;&gt;</span> <span class="dt">Tr</span> bx by bs <span class="ot">=</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Tr</span> (ax <span class="op">*</span> bs <span class="op">+</span> bx) (ay <span class="op">*</span> bs <span class="op">+</span> by) (as <span class="op">*</span> bs)</span></code></pre></div>
<p>Readers who are familiar with linear algebra may recognise the connection to
a sort of restricted affine 2D <a href="https://en.wikipedia.org/wiki/Transformation_matrix">transformation matrix</a>.</p>
<p>Proving that the identity holds on <code>mempty</code> is simple so we will only do one
side, namely <code>a &lt;&gt; mempty == a</code>.</p>
<details>
<summary>
Proof of Monoid right identity…
</summary>
<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">Tr</span> ax ay as <span class="op">&lt;&gt;</span> <span class="fu">mempty</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a><span class="co">-- Definition of mempy</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a><span class="ot">=</span> <span class="dt">Tr</span> ax ay as <span class="op">&lt;&gt;</span> <span class="dt">Tr</span> <span class="dv">0</span> <span class="dv">0</span> <span class="dv">1</span></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a><span class="co">-- Definition of &lt;&gt;</span></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a><span class="ot">=</span> <span class="dt">Tr</span> (ax <span class="op">*</span> <span class="dv">1</span> <span class="op">+</span> <span class="dv">0</span>) (ay <span class="op">*</span> <span class="dv">1</span> <span class="op">+</span> <span class="dv">0</span>) (as <span class="op">*</span> <span class="dv">1</span>)</span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a><span class="co">-- Cancellative property of 0 over +</span></span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a><span class="co">-- Identity of 1 over *</span></span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a><span class="ot">=</span> <span class="dt">Tr</span> ax ay as</span></code></pre></div>
</details>
<p>Next, we want to prove that the <code>&lt;&gt;</code> operator is associative, meaning
<code>a &lt;&gt; (b &lt;&gt; c) == (a &lt;&gt; b) &lt;&gt; c</code>.</p>
<details>
<summary>
Proof of associativity…
</summary>
<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="dt">Tr</span> ax ay as <span class="op">&lt;&gt;</span> (<span class="dt">Tr</span> bx by bs <span class="op">&lt;&gt;</span> <span class="dt">Tr</span> cx cy cs)</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="co">-- Definition of &lt;&gt;</span></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a><span class="ot">=</span> <span class="dt">Tr</span> (ax <span class="op">*</span> (bs <span class="op">*</span> cs) <span class="op">+</span> (bx <span class="op">*</span> cs <span class="op">+</span> cx))</span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a>     (ay <span class="op">*</span> (bs <span class="op">*</span> cs) <span class="op">+</span> (by <span class="op">*</span> cs <span class="op">+</span> cy))</span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a>     (as <span class="op">*</span> (bs <span class="op">*</span> cs))</span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a><span class="co">-- Associativity of * and +</span></span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a><span class="ot">=</span> <span class="dt">Tr</span> (ax <span class="op">*</span> bs <span class="op">*</span> cs <span class="op">+</span> bx <span class="op">*</span> cs <span class="op">+</span> cx)</span>
<span id="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a>     (ay <span class="op">*</span> bs <span class="op">*</span> cs <span class="op">+</span> by <span class="op">*</span> cs <span class="op">+</span> cy)</span>
<span id="cb18-11"><a href="#cb18-11" aria-hidden="true" tabindex="-1"></a>     ((as <span class="op">*</span> bs) <span class="op">*</span> cs)</span>
<span id="cb18-12"><a href="#cb18-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-13"><a href="#cb18-13" aria-hidden="true" tabindex="-1"></a><span class="co">-- Distributivity of * over +</span></span>
<span id="cb18-14"><a href="#cb18-14" aria-hidden="true" tabindex="-1"></a><span class="ot">=</span> <span class="dt">Tr</span> ((ax <span class="op">*</span> bs <span class="op">+</span> bx) <span class="op">*</span> cs <span class="op">+</span> cx)</span>
<span id="cb18-15"><a href="#cb18-15" aria-hidden="true" tabindex="-1"></a>     ((ay <span class="op">*</span> bs <span class="op">+</span> by) <span class="op">*</span> cs <span class="op">+</span> cy)</span>
<span id="cb18-16"><a href="#cb18-16" aria-hidden="true" tabindex="-1"></a>     ((as <span class="op">*</span> bs) <span class="op">*</span> cs)</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="co">-- Definition of &lt;&gt;</span></span>
<span id="cb18-19"><a href="#cb18-19" aria-hidden="true" tabindex="-1"></a><span class="ot">=</span> (<span class="dt">Tr</span> ax ay as <span class="op">&lt;&gt;</span> <span class="dt">T</span> b by bs) <span class="op">&lt;&gt;</span> <span class="dt">Tr</span> cx cy cs</span></code></pre></div>
</details>
<p>Now that we have a valid Monoid instance, we can use the higher-level <code>&lt;&gt;</code>
and <code>mempty</code> concepts in our core layout algorithm, rather than worrying over
details like <em>(x, y)</em> coordinates and scaling factors.</p>
<h1 id="the-lazy-layout">The lazy layout</h1>
<p>Our main <code>layoutCollage</code> function takes the user-specified tree as input,
and annotates each element with a <code>Transform</code>.
In addition to that, we also produce the <code>Size</code> of the final image so we can
allocate space for it.</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a>layoutCollage</span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a><span class="ot">  ::</span> <span class="dt">Sized</span> img</span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>  <span class="ot">=&gt;</span> <span class="dt">Collage</span> img</span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> (<span class="dt">Collage</span> (img, <span class="dt">Transform</span>), <span class="dt">Size</span>)</span></code></pre></div>
<p>All <code>layoutCollage</code> does is call <code>layout</code> — our <em>circular</em> program — with
the identity transformation:</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a>layoutCollage <span class="ot">=</span> layout <span class="fu">mempty</span></span></code></pre></div>
<p><code>layout</code> takes the size and position of the current element as an argument,
and determines the sizes and positions of a tree recursively.</p>
<p>There are some similarities with the algorithms present in browser engines,
where a parent element will first lay out its children, and then use their
properties to determine its own width.</p>
<p>However, we will use Haskell’s laziness to do this in a single top-down pass.
We provide a declarative algorithm and we leave the decision about what to
calculate when — more concretely, propagating the requested sizes of the
children back up the tree before constructing the transformations — to the
compiler!</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a>layout</span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a><span class="ot">  ::</span> <span class="dt">Sized</span> img</span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>  <span class="ot">=&gt;</span> <span class="dt">Transform</span></span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> <span class="dt">Collage</span> img</span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> (<span class="dt">Collage</span> (img, <span class="dt">Transform</span>), <span class="dt">Size</span>)</span></code></pre></div>
<p>Placing a single image is easy, since we are receiving the transformation
directly as an argument.
We return the <em>requested</em> size — which is just the original size of the image.
This is an important detail in making the laziness work here: if we tried to
return the <em>final</em> size (including the passed in transformation) rather than the
<em>requested</em> size, the computation would diverge (i.e. recurse infinitely).</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a>layout trans (<span class="dt">Singleton</span> img) <span class="ot">=</span></span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>  (<span class="dt">Singleton</span> (img, trans), sizeOf img)</span></code></pre></div>
<p>In the recursive case for horizontal composition, we call the <code>horizontal</code>
helper we defined earlier with the left and right image sizes as arguments.
This gives us both transformations, that we can then pass in as arguments to
<code>layout</code> again – returning the left and right image sizes we pass in to the
<code>horizontal</code> helper, forming our apparent circle.</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a>layout trans (<span class="dt">Horizontal</span> l r) <span class="ot">=</span></span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>  (<span class="dt">Horizontal</span> l&#39; r&#39;, size)</span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a>  (l&#39;, lsize)            <span class="ot">=</span> layout (ltrans <span class="op">&lt;&gt;</span> trans) l</span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a>  (r&#39;, rsize)            <span class="ot">=</span> layout (rtrans <span class="op">&lt;&gt;</span> trans) r</span>
<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a>  (ltrans, rtrans, size) <span class="ot">=</span> horizontal lsize rsize</span></code></pre></div>
<p>The same happens for the vertical case:</p>
<div class="sourceCode" id="cb24"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a>layout trans (<span class="dt">Vertical</span> t b) <span class="ot">=</span></span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>  (<span class="dt">Vertical</span> t&#39; b&#39;, size)</span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a>  (t&#39;, tsize)            <span class="ot">=</span> layout (ttrans <span class="op">&lt;&gt;</span> trans) t</span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a>  (b&#39;, bsize)            <span class="ot">=</span> layout (btrans <span class="op">&lt;&gt;</span> trans) b</span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a>  (ttrans, btrans, size) <span class="ot">=</span> vertical tsize bsize</span></code></pre></div>
<p>It’s worth thinking about why this works: the intuitive explanation is that
we can “delay” the execution of the transformations until the very end of the
computation, and then fill them in everywhere. This works since no other parts
of the algorithm <em>depend</em> on the transformation, only on the requested sizes.</p>
<h1 id="conclusion">Conclusion</h1>
<p>We’ve written a circular program! Although I was aware of <code>repmin</code> for a long
time, it’s not a technique I’ve applied often. To me, it is quite interesting
because, compared to <code>repmin</code>:</p>
<ul>
<li>it is easier to explain to a novice why this is useful;</li>
<li>it is perhaps easier to understand due to the visual aspect; and</li>
<li>it is an example outside of the realm of parsers and compilers.</li>
</ul>
<p>The structure is also somewhat different; rather than having a circular step at
the top-level function invocation, we have it at every step of the recursion.</p>
<p>Thanks to <a href="https://mazzo.li/">Francesco Mazzoli</a> and
<a href="https://github.com/tivervac">Titouan Vervack</a> reading a draft of this blogpost
and suggesting improvements. And thanks to you for reading!</p>
<p>What follows below are a number of relatively small functions that take care of
various tasks, included so this can function as a standalone program:</p>
<ul>
<li><a href="#rendering-the-result">Actually rendering the layout back to an image</a></li>
<li><a href="#parsing-a-collage-description">Parsing a collage description</a></li>
<li><a href="#generating-random-collages">Generating random collages</a></li>
<li><a href="#putting-together-the-cli">Putting together the CLI</a></li>
<li><a href="#resizing-the-result">Resizing the result</a></li>
</ul>
<p><img src="/images/2023-07-22-lazy-layout-example-2.jpg" /></p>
<h1 id="appendices">Appendices</h1>
<h2 id="rendering-the-result">Rendering the result</h2>
<p>Once we’ve determined the layout, we still need to apply it and draw all
the images using the computed transformations. We use simple nearest-neighbour
scaling since that is not the focus of this program, you could consider <a href="https://mazzo.li/posts/lanczos.html">Lánczos
interpolation</a> in a real application.</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a>render</span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a><span class="ot">  ::</span> <span class="dt">Foldable</span> f</span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a>  <span class="ot">=&gt;</span> <span class="dt">Size</span></span>
<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> f (<span class="dt">JP.Image</span> <span class="dt">JP.PixelRGB8</span>, <span class="dt">Transform</span>)</span>
<span id="cb25-5"><a href="#cb25-5" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> <span class="dt">JP.Image</span> <span class="dt">JP.PixelRGB8</span></span>
<span id="cb25-6"><a href="#cb25-6" aria-hidden="true" tabindex="-1"></a>render (<span class="dt">Sz</span> width height) images <span class="ot">=</span> runST <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb25-7"><a href="#cb25-7" aria-hidden="true" tabindex="-1"></a>  canvas <span class="ot">&lt;-</span> JP.createMutableImage (<span class="fu">round</span> width) (<span class="fu">round</span> height) black</span>
<span id="cb25-8"><a href="#cb25-8" aria-hidden="true" tabindex="-1"></a>  for_ images <span class="op">$</span> transform canvas</span>
<span id="cb25-9"><a href="#cb25-9" aria-hidden="true" tabindex="-1"></a>  JP.unsafeFreezeImage canvas</span>
<span id="cb25-10"><a href="#cb25-10" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb25-11"><a href="#cb25-11" aria-hidden="true" tabindex="-1"></a>  black <span class="ot">=</span> <span class="dt">JP.PixelRGB8</span> <span class="dv">0</span> <span class="dv">0</span> <span class="dv">0</span></span>
<span id="cb25-12"><a href="#cb25-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-13"><a href="#cb25-13" aria-hidden="true" tabindex="-1"></a>  transform canvas (img, <span class="dt">Tr</span> dstX dstY dstS) <span class="ot">=</span></span>
<span id="cb25-14"><a href="#cb25-14" aria-hidden="true" tabindex="-1"></a>    for_ [<span class="fu">round</span> dstX <span class="op">..</span> <span class="fu">round</span> (dstX <span class="op">+</span> dstW) <span class="op">-</span> <span class="dv">1</span>] <span class="op">$</span> \outX <span class="ot">-&gt;</span></span>
<span id="cb25-15"><a href="#cb25-15" aria-hidden="true" tabindex="-1"></a>    for_ [<span class="fu">round</span> dstY <span class="op">..</span> <span class="fu">round</span> (dstY <span class="op">+</span> dstH) <span class="op">-</span> <span class="dv">1</span>] <span class="op">$</span> \outY <span class="ot">-&gt;</span></span>
<span id="cb25-16"><a href="#cb25-16" aria-hidden="true" tabindex="-1"></a>      <span class="kw">let</span> inX <span class="ot">=</span> <span class="fu">min</span> (JP.imageWidth img <span class="op">-</span> <span class="dv">1</span>) <span class="op">$</span> <span class="fu">round</span> <span class="op">$</span></span>
<span id="cb25-17"><a href="#cb25-17" aria-hidden="true" tabindex="-1"></a>                <span class="fu">fromIntegral</span> (outX <span class="op">-</span> <span class="fu">round</span> dstX) <span class="op">/</span> dstS</span>
<span id="cb25-18"><a href="#cb25-18" aria-hidden="true" tabindex="-1"></a>          inY <span class="ot">=</span> <span class="fu">min</span> (JP.imageHeight img <span class="op">-</span> <span class="dv">1</span>) <span class="op">$</span> <span class="fu">round</span> <span class="op">$</span></span>
<span id="cb25-19"><a href="#cb25-19" aria-hidden="true" tabindex="-1"></a>                <span class="fu">fromIntegral</span> (outY <span class="op">-</span> <span class="fu">round</span> dstY) <span class="op">/</span> dstS <span class="kw">in</span></span>
<span id="cb25-20"><a href="#cb25-20" aria-hidden="true" tabindex="-1"></a>      JP.writePixel canvas outX outY <span class="op">$</span> JP.pixelAt img inX inY</span>
<span id="cb25-21"><a href="#cb25-21" aria-hidden="true" tabindex="-1"></a>   <span class="kw">where</span></span>
<span id="cb25-22"><a href="#cb25-22" aria-hidden="true" tabindex="-1"></a>    dstW <span class="ot">=</span> <span class="fu">fromIntegral</span> (JP.imageWidth img)  <span class="op">*</span> dstS</span>
<span id="cb25-23"><a href="#cb25-23" aria-hidden="true" tabindex="-1"></a>    dstH <span class="ot">=</span> <span class="fu">fromIntegral</span> (JP.imageHeight img) <span class="op">*</span> dstS</span></code></pre></div>
<h2 id="parsing-a-collage-description">Parsing a collage description</h2>
<p>We use a simple parser to allow the user to specify collages as a string, for
example on the command line. This is a natural fit for <a href="https://en.wikipedia.org/wiki/Polish_notation">polish notation</a> as
using parentheses in command line arguments is very awkward.</p>
<p>As an example, we want to parse the following arguments:</p>
<pre><code>H img1.jpg V img2.jpg H img3.jpg img4.jpg</code></pre>
<p>Into this tree:</p>
<pre><code>(Horizontal &quot;img1.jpg&quot;
  (Vertical &quot;img2.jpg&quot;)
  (Horizontal &quot;img3.jpg&quot; &quot;img4.jpg&quot;))</code></pre>
<p>We don’t even need a parser library, we can just treat the arguments as a stack:</p>
<div class="sourceCode" id="cb28"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="ot">parseCollage ::</span> [<span class="dt">String</span>] <span class="ot">-&gt;</span> <span class="dt">Maybe</span> (<span class="dt">Collage</span> <span class="dt">FilePath</span>)</span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a>parseCollage args <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a>  (tree, []) <span class="ot">&lt;-</span> parseTree args</span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a>  <span class="fu">pure</span> tree</span>
<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a>  parseTree []             <span class="ot">=</span> <span class="dt">Nothing</span></span>
<span id="cb28-7"><a href="#cb28-7" aria-hidden="true" tabindex="-1"></a>  parseTree (<span class="st">&quot;H&quot;</span> <span class="op">:</span> stack0) <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb28-8"><a href="#cb28-8" aria-hidden="true" tabindex="-1"></a>    (x, stack1) <span class="ot">&lt;-</span> parseTree stack0</span>
<span id="cb28-9"><a href="#cb28-9" aria-hidden="true" tabindex="-1"></a>    (y, stack2) <span class="ot">&lt;-</span> parseTree stack1</span>
<span id="cb28-10"><a href="#cb28-10" aria-hidden="true" tabindex="-1"></a>    <span class="fu">pure</span> (<span class="dt">Horizontal</span> x y, stack2)</span>
<span id="cb28-11"><a href="#cb28-11" aria-hidden="true" tabindex="-1"></a>  parseTree (<span class="st">&quot;V&quot;</span> <span class="op">:</span> stack0) <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb28-12"><a href="#cb28-12" aria-hidden="true" tabindex="-1"></a>    (x, stack1) <span class="ot">&lt;-</span> parseTree stack0</span>
<span id="cb28-13"><a href="#cb28-13" aria-hidden="true" tabindex="-1"></a>    (y, stack2) <span class="ot">&lt;-</span> parseTree stack1</span>
<span id="cb28-14"><a href="#cb28-14" aria-hidden="true" tabindex="-1"></a>    <span class="fu">pure</span> (<span class="dt">Vertical</span> x y, stack2)</span>
<span id="cb28-15"><a href="#cb28-15" aria-hidden="true" tabindex="-1"></a>  parseTree (x   <span class="op">:</span> stack0) <span class="ot">=</span> <span class="dt">Just</span> (<span class="dt">Singleton</span> x, stack0)</span></code></pre></div>
<h2 id="generating-random-collages">Generating random collages</h2>
<p>In order to test this program, I also added some functionality to generate
random collages.</p>
<div class="sourceCode" id="cb29"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="ot">randomCollage ::</span> <span class="dt">RandomGen</span> g <span class="ot">=&gt;</span> <span class="dt">NonEmpty</span> a <span class="ot">-&gt;</span> g <span class="ot">-&gt;</span> (<span class="dt">Collage</span> a, g)</span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a>randomCollage ne gen <span class="ot">=</span> runStateGen gen <span class="op">$</span> \g <span class="ot">-&gt;</span> go g ne</span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span></code></pre></div>
<p>The utility <code>rc</code> picks a <strong>r</strong>andom <strong>c</strong>onstructor.</p>
<div class="sourceCode" id="cb30"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a>  rc g <span class="ot">=</span> bool <span class="dt">Horizontal</span> <span class="dt">Vertical</span> <span class="op">&lt;$&gt;</span> randomM g</span></code></pre></div>
<p>In our worker function, we keep one item on the side (<code>x</code>), and randomly decide
if other items will go in the left or right subtree:</p>
<div class="sourceCode" id="cb31"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a>  go g (x <span class="op">:|</span> xs) <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a>    (lts, rts) <span class="ot">&lt;-</span> partition <span class="fu">snd</span> <span class="op">&lt;$&gt;</span></span>
<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a>      <span class="fu">traverse</span> (\y <span class="ot">-&gt;</span> (,) y <span class="op">&lt;$&gt;</span> randomM g) xs</span></code></pre></div>
<p>Then, we look at the random partitioning we just created. If they’re both
empty, the only thing we can do is create a singleton collage:</p>
<div class="sourceCode" id="cb32"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a>    <span class="kw">case</span> (<span class="fu">map</span> <span class="fu">fst</span> lts, <span class="fu">map</span> <span class="fu">fst</span> rts) <span class="kw">of</span></span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a>      ([],       [])       <span class="ot">-&gt;</span> <span class="fu">pure</span> <span class="op">$</span> <span class="dt">Singleton</span> x</span></code></pre></div>
<p>If either of them is empty, we put <code>x</code> in the other partition to ensure we don’t
create invalid empty trees:</p>
<div class="sourceCode" id="cb33"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a>      ((l <span class="op">:</span> ls), [])       <span class="ot">-&gt;</span> rc g <span class="op">&lt;*&gt;</span> go g (l <span class="op">:|</span> ls) <span class="op">&lt;*&gt;</span> go g (x <span class="op">:|</span> [])</span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a>      ([],       (r <span class="op">:</span> rs)) <span class="ot">-&gt;</span> rc g <span class="op">&lt;*&gt;</span> go g (x <span class="op">:|</span> []) <span class="op">&lt;*&gt;</span> go g (r <span class="op">:|</span> rs)</span></code></pre></div>
<p>Otherwise, we decide at random which partition <code>x</code> goes into:</p>
<div class="sourceCode" id="cb34"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a>      ((l <span class="op">:</span> ls), (r <span class="op">:</span> rs)) <span class="ot">-&gt;</span> <span class="kw">do</span></span>
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a>        xLeft <span class="ot">&lt;-</span> randomM g</span>
<span id="cb34-3"><a href="#cb34-3" aria-hidden="true" tabindex="-1"></a>        <span class="kw">if</span> xLeft</span>
<span id="cb34-4"><a href="#cb34-4" aria-hidden="true" tabindex="-1"></a>          <span class="kw">then</span> rc g <span class="op">&lt;*&gt;</span> go g (x <span class="op">:|</span> l <span class="op">:</span> ls) <span class="op">&lt;*&gt;</span> go g (r <span class="op">:|</span> rs)</span>
<span id="cb34-5"><a href="#cb34-5" aria-hidden="true" tabindex="-1"></a>          <span class="kw">else</span> rc g <span class="op">&lt;*&gt;</span> go g (l <span class="op">:|</span> ls)     <span class="op">&lt;*&gt;</span> go g (x <span class="op">:|</span> r <span class="op">:</span> rs)</span></code></pre></div>
<h2 id="putting-together-the-cli">Putting together the CLI</h2>
<p>We support two modes of operation for our little CLI:</p>
<ul>
<li>Using a user-specified collage using the parser we wrote before.</li>
<li>Generating a random collage from a number of images.</li>
</ul>
<p>In both cases, we also take an output file as the first argument, so we know
where we want to write the image to. We also take an optional <code>-fit</code> flag so
we can resize the final image down to a requested size.</p>
<div class="sourceCode" id="cb35"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Command</span> <span class="ot">=</span> <span class="dt">Command</span></span>
<span id="cb35-2"><a href="#cb35-2" aria-hidden="true" tabindex="-1"></a>  {<span class="ot"> cmdOut     ::</span> <span class="dt">FilePath</span></span>
<span id="cb35-3"><a href="#cb35-3" aria-hidden="true" tabindex="-1"></a>  ,<span class="ot"> cmdFit     ::</span> <span class="dt">Maybe</span> <span class="dt">Int</span></span>
<span id="cb35-4"><a href="#cb35-4" aria-hidden="true" tabindex="-1"></a>  ,<span class="ot"> cmdCollage ::</span> <span class="dt">CommandCollage</span></span>
<span id="cb35-5"><a href="#cb35-5" aria-hidden="true" tabindex="-1"></a>  }</span>
<span id="cb35-6"><a href="#cb35-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-7"><a href="#cb35-7" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">CommandCollage</span></span>
<span id="cb35-8"><a href="#cb35-8" aria-hidden="true" tabindex="-1"></a>  <span class="ot">=</span> <span class="dt">User</span>   (<span class="dt">Collage</span> <span class="dt">FilePath</span>)</span>
<span id="cb35-9"><a href="#cb35-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">|</span> <span class="dt">Random</span> (<span class="dt">NonEmpty</span> <span class="dt">FilePath</span>)</span>
<span id="cb35-10"><a href="#cb35-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">deriving</span> (<span class="dt">Show</span>)</span></code></pre></div>
<p>There is some setup to parse the output and a <code>-fit</code> flag. The important
bit happens in <code>parseCommandCollage</code> further down.</p>
<div class="sourceCode" id="cb36"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb36-1"><a href="#cb36-1" aria-hidden="true" tabindex="-1"></a><span class="ot">parseCommand ::</span> [<span class="dt">String</span>] <span class="ot">-&gt;</span> <span class="dt">Maybe</span> <span class="dt">Command</span></span>
<span id="cb36-2"><a href="#cb36-2" aria-hidden="true" tabindex="-1"></a>parseCommand cmd <span class="ot">=</span> <span class="kw">case</span> cmd <span class="kw">of</span></span>
<span id="cb36-3"><a href="#cb36-3" aria-hidden="true" tabindex="-1"></a>  [] <span class="ot">-&gt;</span> <span class="dt">Nothing</span></span>
<span id="cb36-4"><a href="#cb36-4" aria-hidden="true" tabindex="-1"></a>  (<span class="st">&quot;-fit&quot;</span> <span class="op">:</span> num <span class="op">:</span> args) <span class="op">|</span> <span class="dt">Just</span> n <span class="ot">&lt;-</span> readMaybe num <span class="ot">-&gt;</span> <span class="kw">do</span></span>
<span id="cb36-5"><a href="#cb36-5" aria-hidden="true" tabindex="-1"></a>    cmd&#39; <span class="ot">&lt;-</span> parseCommand args</span>
<span id="cb36-6"><a href="#cb36-6" aria-hidden="true" tabindex="-1"></a>    <span class="fu">pure</span> cmd&#39; {cmdFit <span class="ot">=</span> <span class="dt">Just</span> n}</span>
<span id="cb36-7"><a href="#cb36-7" aria-hidden="true" tabindex="-1"></a>  (o <span class="op">:</span> args) <span class="ot">-&gt;</span> <span class="dt">Command</span> o <span class="dt">Nothing</span> <span class="op">&lt;$&gt;</span> parseCommandCollage args</span></code></pre></div>
<p>We’ll use <code>R</code> for a random collage, and <code>H</code>/<code>V</code> will be parsed by
<code>parseCollage</code>.</p>
<div class="sourceCode" id="cb37"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb37-1"><a href="#cb37-1" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb37-2"><a href="#cb37-2" aria-hidden="true" tabindex="-1"></a>  parseCommandCollage (<span class="st">&quot;R&quot;</span> <span class="op">:</span> x <span class="op">:</span> xs) <span class="ot">=</span> <span class="dt">Just</span> <span class="op">$</span> <span class="dt">Random</span> (x <span class="op">:|</span> xs)</span>
<span id="cb37-3"><a href="#cb37-3" aria-hidden="true" tabindex="-1"></a>  parseCommandCollage spec           <span class="ot">=</span> <span class="dt">User</span> <span class="op">&lt;$&gt;</span> parseCollage spec</span></code></pre></div>
<p>Time to put everything together in the <code>main</code> function. First, we do some
parsing:</p>
<div class="sourceCode" id="cb38"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb38-1"><a href="#cb38-1" aria-hidden="true" tabindex="-1"></a><span class="ot">main ::</span> <span class="dt">IO</span> ()</span>
<span id="cb38-2"><a href="#cb38-2" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb38-3"><a href="#cb38-3" aria-hidden="true" tabindex="-1"></a>  args <span class="ot">&lt;-</span> getArgs</span>
<span id="cb38-4"><a href="#cb38-4" aria-hidden="true" tabindex="-1"></a>  command <span class="ot">&lt;-</span> <span class="fu">maybe</span> (<span class="fu">fail</span> <span class="st">&quot;invalid command&quot;</span>) <span class="fu">pure</span> <span class="op">$</span></span>
<span id="cb38-5"><a href="#cb38-5" aria-hidden="true" tabindex="-1"></a>    parseCommand args</span>
<span id="cb38-6"><a href="#cb38-6" aria-hidden="true" tabindex="-1"></a>  pathsCollage <span class="ot">&lt;-</span> <span class="kw">case</span> cmdCollage command <span class="kw">of</span></span>
<span id="cb38-7"><a href="#cb38-7" aria-hidden="true" tabindex="-1"></a>    <span class="dt">User</span> explicit <span class="ot">-&gt;</span> <span class="fu">pure</span> explicit</span>
<span id="cb38-8"><a href="#cb38-8" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Random</span> paths <span class="ot">-&gt;</span> <span class="kw">do</span></span>
<span id="cb38-9"><a href="#cb38-9" aria-hidden="true" tabindex="-1"></a>      gen <span class="ot">&lt;-</span> newStdGen</span>
<span id="cb38-10"><a href="#cb38-10" aria-hidden="true" tabindex="-1"></a>      <span class="kw">let</span> (random, _) <span class="ot">=</span> randomCollage paths gen</span>
<span id="cb38-11"><a href="#cb38-11" aria-hidden="true" tabindex="-1"></a>      <span class="fu">pure</span> random</span></code></pre></div>
<p>Followed by actually reading in all the images:</p>
<div class="sourceCode" id="cb39"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb39-1"><a href="#cb39-1" aria-hidden="true" tabindex="-1"></a>  imageCollage <span class="ot">&lt;-</span> readCollage pathsCollage</span></code></pre></div>
<p>This gives us the <code>Collage (JP.Image JP.PixelRGB8)</code>. We can pass that to our
<code>layout</code> function and write it to the output, after optionally applying our
<code>fit</code>:</p>
<div class="sourceCode" id="cb40"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb40-1"><a href="#cb40-1" aria-hidden="true" tabindex="-1"></a>  <span class="kw">let</span> (result, box) <span class="ot">=</span> <span class="kw">case</span> cmdFit command <span class="kw">of</span></span>
<span id="cb40-2"><a href="#cb40-2" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Nothing</span> <span class="ot">-&gt;</span> layoutCollage imageCollage</span>
<span id="cb40-3"><a href="#cb40-3" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Just</span> f  <span class="ot">-&gt;</span> fit f <span class="op">$</span> layoutCollage imageCollage</span>
<span id="cb40-4"><a href="#cb40-4" aria-hidden="true" tabindex="-1"></a>  write (cmdOut command) <span class="op">$</span> <span class="dt">JP.ImageRGB8</span> <span class="op">$</span> render box result</span>
<span id="cb40-5"><a href="#cb40-5" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb40-6"><a href="#cb40-6" aria-hidden="true" tabindex="-1"></a>  write output</span>
<span id="cb40-7"><a href="#cb40-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">|</span> <span class="st">&quot;.jpg&quot;</span> <span class="ot">`isSuffixOf`</span> output <span class="ot">=</span> JP.saveJpgImage <span class="dv">80</span> output</span>
<span id="cb40-8"><a href="#cb40-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">|</span> <span class="fu">otherwise</span>                  <span class="ot">=</span> JP.savePngImage output</span></code></pre></div>
<h2 id="resizing-the-result">Resizing the result</h2>
<p>Most of the time I don’t want to host full-resolution pictures for web viewing.
This is an addition I added later on to resize an image down to a requested
“long edge” (i.e. a requested maximum width or height, whichever is bigger).</p>
<p>Interestingly I think this can also be done by having an additional parameter
to <code>layout</code>, and using circular programming once again to link the initial
transformation to the requested size. However, the core algorithm is harder
to understand that way, so I left it as a separate utility:</p>
<div class="sourceCode" id="cb41"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb41-1"><a href="#cb41-1" aria-hidden="true" tabindex="-1"></a>fit</span>
<span id="cb41-2"><a href="#cb41-2" aria-hidden="true" tabindex="-1"></a><span class="ot">  ::</span> <span class="dt">Int</span></span>
<span id="cb41-3"><a href="#cb41-3" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> (<span class="dt">Collage</span> (img, <span class="dt">Transform</span>), <span class="dt">Size</span>)</span>
<span id="cb41-4"><a href="#cb41-4" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> (<span class="dt">Collage</span> (img, <span class="dt">Transform</span>), <span class="dt">Size</span>)</span>
<span id="cb41-5"><a href="#cb41-5" aria-hidden="true" tabindex="-1"></a>fit longEdge (collage, <span class="dt">Sz</span> w h)</span>
<span id="cb41-6"><a href="#cb41-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">|</span> long <span class="op">&lt;=</span> <span class="fu">fromIntegral</span> longEdge <span class="ot">=</span> (collage, <span class="dt">Sz</span> w h)</span>
<span id="cb41-7"><a href="#cb41-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">|</span> <span class="fu">otherwise</span>                     <span class="ot">=</span></span>
<span id="cb41-8"><a href="#cb41-8" aria-hidden="true" tabindex="-1"></a>      (<span class="fu">fmap</span> (<span class="op">&lt;&gt;</span> tr) <span class="op">&lt;$&gt;</span> collage, <span class="dt">Sz</span> (w <span class="op">*</span> scale) (h <span class="op">*</span> scale))</span>
<span id="cb41-9"><a href="#cb41-9" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb41-10"><a href="#cb41-10" aria-hidden="true" tabindex="-1"></a>  long  <span class="ot">=</span> <span class="fu">max</span> w h</span>
<span id="cb41-11"><a href="#cb41-11" aria-hidden="true" tabindex="-1"></a>  scale <span class="ot">=</span> <span class="fu">fromIntegral</span> longEdge <span class="op">/</span> long</span>
<span id="cb41-12"><a href="#cb41-12" aria-hidden="true" tabindex="-1"></a>  tr    <span class="ot">=</span> <span class="dt">Tr</span> <span class="dv">0</span> <span class="dv">0</span> scale</span></code></pre></div>]]></description>
    <pubDate>Sat, 22 Jul 2023 00:00:00 UT</pubDate>
    <guid>http://jaspervdj.be/posts/2023-07-22-lazy-layout.html</guid>
    <dc:creator>Jasper Van der Jeugt</dc:creator>
</item>
<item>
    <title>Haskell Puzzles</title>
    <link>http://jaspervdj.be/posts/2023-06-19-haskell-puzzles.html</link>
    <description><![CDATA[<p>At <a href="https://zfoh.ch/zurihac2023">ZuriHac 2023</a>, I worked on some Haskell Puzzles
together with
<a href="https://www.asayers.com/">Alex</a>,
<a href="https://mazzo.li/">Francesco</a>,
<a href="https://github.com/joamaki">Jussi</a> and
<a href="https://github.com/chpatrick">Patrick</a>.
You are given some Haskell tokens and a goal term, and you need to <strong>rearrange
the tokens into an expression that produces the goal</strong>.</p>
<p>Here a simple warmup exercise just to get an idea of how it works:</p>
<style type="text/css">.puzzle {margin-bottom: 4em;}</style>
<div id="puzzle_iterate" class="puzzle" data-puzzle="{
    &quot;goal&quot;: &quot;[0,1,2,3,4]&quot;,
    &quot;tokens&quot;: [
        {&quot;text&quot;: &quot;iterate&quot;, &quot;x&quot;: 70,  &quot;y&quot;: 40,  &quot;hint&quot;: &quot;(a → a) → a → [a]&quot;},
        {&quot;text&quot;: &quot;0&quot;,       &quot;x&quot;: 150, &quot;y&quot;: 100                             },
        {&quot;text&quot;: &quot;succ&quot;,    &quot;x&quot;: 100, &quot;y&quot;: 100, &quot;hint&quot;: &quot;n → n&quot;            },
        {&quot;text&quot;: &quot;take&quot;,    &quot;x&quot;: 180, &quot;y&quot;: 40,  &quot;hint&quot;: &quot;Int → [a] → [a]&quot;  },
        {&quot;text&quot;: &quot;5&quot;,       &quot;x&quot;: 70,  &quot;y&quot;: 160                             },
        {&quot;text&quot;: &quot;(&quot;,       &quot;x&quot;: 260, &quot;y&quot;: 40                              },
        {&quot;text&quot;: &quot;)&quot;,       &quot;x&quot;: 30,  &quot;y&quot;: 160                             }
    ]
}">

</div>
<p>Let’s continue with <code>iterate</code> but do a real puzzle next. What Monad are we
looking for?</p>
<div id="puzzle_join" class="puzzle" data-puzzle="{
    &quot;goal&quot;: &quot;32&quot;,
    &quot;tokens&quot;: [
        {&quot;text&quot;: &quot;5&quot;,       &quot;x&quot;: 50,  &quot;y&quot;: 80                              },
        {&quot;text&quot;: &quot;1&quot;,       &quot;x&quot;: 30,  &quot;y&quot;: 140                             },
        {&quot;text&quot;: &quot;(+)&quot;,     &quot;x&quot;: 200, &quot;y&quot;: 150                             },
        {&quot;text&quot;: &quot;(&quot;,       &quot;x&quot;: 120, &quot;y&quot;: 160                             },
        {&quot;text&quot;: &quot;)&quot;,       &quot;x&quot;: 240, &quot;y&quot;: 30                              },
        {&quot;text&quot;: &quot;iterate&quot;, &quot;x&quot;: 120, &quot;y&quot;: 30,  &quot;hint&quot;: &quot;(a → a) → a → [a]&quot;},
        {&quot;text&quot;: &quot;join&quot;,    &quot;x&quot;: 150, &quot;y&quot;: 100, &quot;hint&quot;: &quot;m (m a) → m a&quot;    },
        {&quot;text&quot;: &quot;!!&quot;,      &quot;x&quot;: 240, &quot;y&quot;: 100, &quot;hint&quot;: &quot;[a] → Int → a&quot;    }
    ]
}">

</div>
<p>How is <em>e</em> defined again?</p>
<div id="puzzle_e" class="puzzle" data-puzzle="{
    &quot;goal&quot;: &quot;2.7182818284590455&quot;,
    &quot;tokens&quot;: [
        {&quot;text&quot;: &quot;sum&quot;,      &quot;x&quot;: 260, &quot;y&quot;: 140, &quot;hint&quot;: &quot;[n] → n&quot;                },
        {&quot;text&quot;: &quot;(/)&quot;,      &quot;x&quot;: 150, &quot;y&quot;: 150                                   },
        {&quot;text&quot;: &quot;scanl1&quot;,   &quot;x&quot;: 100, &quot;y&quot;: 70,  &quot;hint&quot;: &quot;(a → a → a) → [a] → [a]&quot;},
        {&quot;text&quot;: &quot;succ&quot;,     &quot;x&quot;: 50,  &quot;y&quot;: 160, &quot;hint&quot;: &quot;n → n&quot;                  },
        {&quot;text&quot;: &quot;$&quot;,        &quot;x&quot;: 90,  &quot;y&quot;: 160                                   },
        {&quot;text&quot;: &quot;[1..100]&quot;, &quot;x&quot;: 250, &quot;y&quot;: 50                                    },
        {&quot;text&quot;: &quot;$&quot;,        &quot;x&quot;: 200, &quot;y&quot;: 150                                   }
    ]
}">

</div>
<p><code>let</code> allows us to reuse code. This is very useful if you don’t have enough
tokens to make a sensible program.</p>
<div id="puzzle_let" class="puzzle" data-puzzle="{
    &quot;goal&quot;: &quot;8&quot;,
    &quot;tokens&quot;: [
        {&quot;text&quot;: &quot;2 + 2&quot;, &quot;x&quot;: 60,  &quot;y&quot;: 40 },
        {&quot;text&quot;: &quot;*&quot;,     &quot;x&quot;: 110, &quot;y&quot;: 40 },
        {&quot;text&quot;: &quot;2&quot;,     &quot;x&quot;: 140, &quot;y&quot;: 40 },
        {&quot;text&quot;: &quot;in&quot;,    &quot;x&quot;: 200, &quot;y&quot;: 70 },
        {&quot;text&quot;: &quot;a&quot;,     &quot;x&quot;: 235, &quot;y&quot;: 70 },
        {&quot;text&quot;: &quot;+&quot;,     &quot;x&quot;: 270, &quot;y&quot;: 70 },
        {&quot;text&quot;: &quot;+&quot;,     &quot;x&quot;: 200, &quot;y&quot;: 120},
        {&quot;text&quot;: &quot;=&quot;,     &quot;x&quot;: 235, &quot;y&quot;: 120},
        {&quot;text&quot;: &quot;b&quot;,     &quot;x&quot;: 270, &quot;y&quot;: 120},
        {&quot;text&quot;: &quot;let&quot;,   &quot;x&quot;: 200, &quot;y&quot;: 170},
        {&quot;text&quot;: &quot;a&quot;,     &quot;x&quot;: 235, &quot;y&quot;: 170},
        {&quot;text&quot;: &quot;b&quot;,     &quot;x&quot;: 270, &quot;y&quot;: 170}
    ]
}">

</div>
<p>Here is the final puzzle – but how can we produce a string from a bunch of
numbers?</p>
<div id="puzzle_fin" class="puzzle" data-puzzle="{
    &quot;goal&quot;: &quot;\&quot;fin\&quot;&quot;,
    &quot;tokens&quot;: [
        {&quot;text&quot;: &quot;0&quot;,    &quot;x&quot;: 75,  &quot;y&quot;: 30 },
        {&quot;text&quot;: &quot;1&quot;,    &quot;x&quot;: 125, &quot;y&quot;: 30 },
        {&quot;text&quot;: &quot;2&quot;,    &quot;x&quot;: 175, &quot;y&quot;: 30 },
        {&quot;text&quot;: &quot;3&quot;,    &quot;x&quot;: 225, &quot;y&quot;: 30 },
        {&quot;text&quot;: &quot;$&quot;,    &quot;x&quot;: 50,  &quot;y&quot;: 150},
        {&quot;text&quot;: &quot;$&quot;,    &quot;x&quot;: 40,  &quot;y&quot;: 100},
        {&quot;text&quot;: &quot;$&quot;,    &quot;x&quot;: 80,  &quot;y&quot;: 110},
        {&quot;text&quot;: &quot;take&quot;, &quot;x&quot;: 200, &quot;y&quot;: 110},
        {&quot;text&quot;: &quot;drop&quot;, &quot;x&quot;: 260, &quot;y&quot;: 90 },
        {&quot;text&quot;: &quot;show&quot;, &quot;x&quot;: 180, &quot;y&quot;: 160},
        {&quot;text&quot;: &quot;/&quot;,    &quot;x&quot;: 250, &quot;y&quot;: 160}
    ]
}">

</div>
<hr />
<p>Haskell evaluation powered by <a href="https://tryhaskell.org">tryhaskell.org</a>.
UI powered by <a href="/files/2023-06-19-haskell-puzzles.js">some messy JavaScript</a>.</p>
<p>We playtested these puzzles with simple pieces of paper during the event.
At the final presentation we played a web-based multiplayer version where each
player controls only one token.</p>
<p>We actually found the single player to be more fun, and since we already had
some client code I decided to clean it up a bit and make a single player version
available here.</p>
<p>Thanks for playing!</p>
<script type="text/JavaScript" src="/files/2023-06-19-haskell-puzzles.js"></script>]]></description>
    <pubDate>Mon, 19 Jun 2023 00:00:00 UT</pubDate>
    <guid>http://jaspervdj.be/posts/2023-06-19-haskell-puzzles.html</guid>
    <dc:creator>Jasper Van der Jeugt</dc:creator>
</item>
<item>
    <title>Lazy Sort: Counting Comparisons</title>
    <link>http://jaspervdj.be/posts/2020-09-17-lazysort.html</link>
    <description><![CDATA[<h2 id="introduction">Introduction</h2>
<div style="display: none">
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE BangPatterns #-}</span></span>
<span id="cb1-2"><a href="#cb1-2" 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-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="kw">import</span> <span class="dt">Data.IORef</span> (<span class="dt">IORef</span>)</span>
<span id="cb1-5"><a href="#cb1-5" 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="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.IORef</span> <span class="kw">as</span> <span class="dt">IORef</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Monad</span> (replicateM, forM_, unless, forM)</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.List</span> (sort, intercalate, foldl&#39;)</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">System.Random</span> (randomIO)</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">System.IO.Unsafe</span> (unsafePerformIO)</span></code></pre></div>
</div>
<p>Haskell’s laziness allows you to do
<a href="https://www.reddit.com/r/haskell/comments/5xge0v/today_i_used_laziness_for/">many cool things</a>.
I’ve talked about
<a href="/posts/2017-01-17-lazy-io-graphs.html">searching an infinite graph before</a>.
Another commonly mentioned example is finding the smallest N items in a list.</p>
<p>Because programmers are lazy as well, this is often defined as:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ot">smallestN_lazy ::</span> <span class="dt">Ord</span> a <span class="ot">=&gt;</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> [a] <span class="ot">-&gt;</span> [a]</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>smallestN_lazy n <span class="ot">=</span> <span class="fu">take</span> n <span class="op">.</span> <span class="fu">sort</span></span></code></pre></div>
<p>This happens regardless of the language of choice if we’re confident that the
list will not be too large. It’s more important to be correct than it is to
be fast.</p>
<p>However, in strict languages we’re really sorting the entire list before taking
the first N items. We can implement this in Haskell by forcing the length of
the sorted list.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ot">smallestN_strict ::</span> <span class="dt">Ord</span> a <span class="ot">=&gt;</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> [a] <span class="ot">-&gt;</span> [a]</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>smallestN_strict n l0 <span class="ot">=</span> <span class="kw">let</span> l1 <span class="ot">=</span> <span class="fu">sort</span> l0 <span class="kw">in</span> <span class="fu">length</span> l1 <span class="ot">`seq`</span> <span class="fu">take</span> n l1</span></code></pre></div>
<p>If you’re at least somewhat familiar with the concept of laziness, you may
intuitively realize that the lazy version of <code>smallestN</code> is much better since
it’ll only sort as far as it needs.</p>
<p>But how much better does it actually do, with Haskell’s default <code>sort</code>?</p>
<h2 id="a-better-algorithm">A better algorithm?</h2>
<p>For the sake of the comparison, we can introduce a third algorithm, which does
a slightly smarter thing by keeping a heap of the smallest elements it has seen
so far. This code is far more complex than <code>smallestN_lazy</code>, so if it performs
better, we should still ask ourselves if the additional complexity is worth it.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ot">smallestN_smart ::</span> <span class="dt">Ord</span> a <span class="ot">=&gt;</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> [a] <span class="ot">-&gt;</span> [a]</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>smallestN_smart maxSize list <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>    (item, n) <span class="ot">&lt;-</span> Map.toList heap</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>    <span class="fu">replicate</span> n item</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">where</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>    <span class="co">-- A heap is a map of the item to how many times it occurs in</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>    <span class="co">-- the heap, like a frequency counter.  We also keep the current</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>    <span class="co">-- total count of the heap.</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>    heap <span class="ot">=</span> <span class="fu">fst</span> <span class="op">$</span> foldl&#39; (\acc x <span class="ot">-&gt;</span> insert x acc) (Map.empty, <span class="dv">0</span>) list</span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>    insert x (heap0, count)</span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>        <span class="op">|</span> count <span class="op">&lt;</span> maxSize <span class="ot">=</span> (Map.insertWith (<span class="op">+</span>) x <span class="dv">1</span> heap0, count <span class="op">+</span> <span class="dv">1</span>)</span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>        <span class="op">|</span> <span class="fu">otherwise</span> <span class="ot">=</span> <span class="kw">case</span> Map.maxViewWithKey heap0 <span class="kw">of</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>            <span class="dt">Nothing</span> <span class="ot">-&gt;</span> (Map.insertWith (<span class="op">+</span>) x <span class="dv">1</span> heap0, count <span class="op">+</span> <span class="dv">1</span>)</span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>            <span class="dt">Just</span> ((y, yn), _) <span class="ot">-&gt;</span> <span class="kw">case</span> <span class="fu">compare</span> x y <span class="kw">of</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a>                <span class="dt">EQ</span> <span class="ot">-&gt;</span> (heap0, count)</span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a>                <span class="dt">GT</span> <span class="ot">-&gt;</span> (heap0, count)</span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a>                <span class="dt">LT</span> <span class="ot">-&gt;</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">let</span> heap1 <span class="ot">=</span> Map.insertWith (<span class="op">+</span>) x <span class="dv">1</span> heap0 <span class="kw">in</span></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">if</span> yn <span class="op">&gt;</span> <span class="dv">1</span></span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">then</span> (Map.insert y (yn <span class="op">-</span> <span class="dv">1</span>) heap1, count)</span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">else</span> (Map.delete y heap1, count)</span></code></pre></div>
<p>So, we get to the main trick I wanted to talk about: how do we benchmark this,
and can we add unit tests to confirm these benchmark results in CI? Benchmark
execution times are very fickle. <a href="https://github.com/nh2/haskell-cpu-instruction-counter">Instruction counting</a> is awesome but perhaps
a little overkill.</p>
<p>Instead, we can just count the number of comparisons.</p>
<h2 id="counting-comparisons">Counting comparisons</h2>
<p>We can use a new type that holds a value and a number of ticks. We can increase
the number of ticks, and also read the ticks that have occurred.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell literate"><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">Ticks</span> a <span class="ot">=</span> <span class="dt">Ticks</span> {<span class="ot">ref ::</span> <span class="op">!</span>(<span class="dt">IORef</span> <span class="dt">Int</span>),<span class="ot"> unTicks ::</span> <span class="op">!</span>a}</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="ot">mkTicks ::</span> a <span class="ot">-&gt;</span> <span class="dt">IO</span> (<span class="dt">Ticks</span> a)</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>mkTicks x <span class="ot">=</span> <span class="dt">Ticks</span> <span class="op">&lt;$&gt;</span> IORef.newIORef <span class="dv">0</span> <span class="op">&lt;*&gt;</span> <span class="fu">pure</span> x</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">tick ::</span> <span class="dt">Ticks</span> a <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>tick t <span class="ot">=</span> IORef.atomicModifyIORef&#39; (ref t) <span class="op">$</span> \i <span class="ot">-&gt;</span> (i <span class="op">+</span> <span class="dv">1</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="ot">ticks ::</span> <span class="dt">Ticks</span> a <span class="ot">-&gt;</span> <span class="dt">IO</span> <span class="dt">Int</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>ticks <span class="ot">=</span> IORef.readIORef <span class="op">.</span> ref</span></code></pre></div>
<p><code>smallestN</code> has an <code>Ord</code> constraint, so if we want to count the number of
comparisons we’ll want to do that for both <code>==</code> and <code>compare</code>.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell literate"><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">Eq</span> a <span class="ot">=&gt;</span> <span class="dt">Eq</span> (<span class="dt">Ticks</span> a) <span class="kw">where</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>    (<span class="op">==</span>) <span class="ot">=</span> tick2 (<span class="op">==</span>)</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Ord</span> a <span class="ot">=&gt;</span> <span class="dt">Ord</span> (<span class="dt">Ticks</span> a) <span class="kw">where</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>    <span class="fu">compare</span> <span class="ot">=</span> tick2 <span class="fu">compare</span></span></code></pre></div>
<p>The actual ticking code goes in <code>tick2</code>, which applies a binary operation and
increases the counters of both arguments. We need <code>unsafePerformIO</code> for that
but it’s fine since this lives only in our testing code and not our actual
<code>smallestN</code> implementation.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="ot">tick2 ::</span> (a <span class="ot">-&gt;</span> a <span class="ot">-&gt;</span> b) <span class="ot">-&gt;</span> <span class="dt">Ticks</span> a <span class="ot">-&gt;</span> <span class="dt">Ticks</span> a <span class="ot">-&gt;</span> b</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>tick2 f t1 t2 <span class="ot">=</span> unsafePerformIO <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>    tick t1</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>    tick t2</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>    <span class="fu">pure</span> <span class="op">$</span> f (unTicks t1) (unTicks t2)</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# NOINLINE tick2 #-}</span></span></code></pre></div>
<h2 id="results">Results</h2>
<p>Let’s add some benchmarking that prints an ad-hoc CSV:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ot">main ::</span> <span class="dt">IO</span> ()</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">let</span> listSize <span class="ot">=</span> <span class="dv">100000</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>        impls <span class="ot">=</span> [smallestN_strict, smallestN_lazy, smallestN_smart]</span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>    forM_ [<span class="dv">50</span>, <span class="dv">100</span> <span class="op">..</span> <span class="dv">2000</span>] <span class="op">$</span> \sampleSize <span class="ot">-&gt;</span> <span class="kw">do</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>        l <span class="ot">&lt;-</span> replicateM listSize<span class="ot"> randomIO ::</span> <span class="dt">IO</span> [<span class="dt">Int</span>]</span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>        (nticks, results) <span class="ot">&lt;-</span> <span class="fu">fmap</span> <span class="fu">unzip</span> <span class="op">$</span> forM impls <span class="op">$</span> \f <span class="ot">-&gt;</span> <span class="kw">do</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>            l1 <span class="ot">&lt;-</span> <span class="fu">traverse</span> mkTicks l</span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>            <span class="kw">let</span> <span class="op">!</span>r1 <span class="ot">=</span> <span class="fu">sum</span> <span class="op">.</span> <span class="fu">map</span> unTicks <span class="op">$</span> f sampleSize l1</span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>            t1 <span class="ot">&lt;-</span> <span class="fu">sum</span> <span class="op">&lt;$&gt;</span> <span class="fu">traverse</span> ticks l1</span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>            <span class="fu">pure</span> (t1, r1)</span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a>        unless (equal results) <span class="op">.</span> <span class="fu">fail</span> <span class="op">$</span></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a>            <span class="st">&quot;Different results: &quot;</span> <span class="op">++</span> <span class="fu">show</span> results</span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a>        <span class="fu">putStrLn</span> <span class="op">.</span> intercalate <span class="st">&quot;,&quot;</span> <span class="op">.</span> <span class="fu">map</span> <span class="fu">show</span> <span class="op">$</span> sampleSize <span class="op">:</span> nticks</span></code></pre></div>
<p>Plug that CSV into a spreadsheet and we get this graph. What conclusions can
we draw?</p>
<p><img src="/images/2020-09-17-lazysort1.png" /></p>
<p>Clearly, both the lazy version as well as the “smart” version are able to
avoid a large number of comparisons. Let’s remove the strict version so we
can zoom in.</p>
<p><img src="/images/2020-09-17-lazysort2.png" /></p>
<p>What does this mean?</p>
<ul>
<li><p>If the <code>sampleSize</code> is small, the heap implementation does less comparions.
This makes sense: even if treat <code>sort</code> as a black box, and don’t look at
it’s implementation, we can assume that it is not <em>optimally lazy</em>; so it
will always sort “a bit too much”.</p></li>
<li><p>As <code>sampleSize</code> gets bigger, the insertion into the bigger and bigger heap
starts to matter more and more and eventually the naive lazy implementation
is faster!</p></li>
<li><p>Laziness is awesome and <code>take N . sort</code> is absolutely the first
implementation you should write, even if you replace it with a more
efficient version later.</p></li>
<li><p>Code where you count a number of calls is very easy to do in a test suite.
It doesn’t pollute the application code if we can patch in counting through
a typeclass (<code>Ord</code> in this case).</p></li>
</ul>
<p>Can we say something about the complexity?</p>
<ul>
<li><p>The complexity of <code>smallestN_smart</code> is basically inserting into a heap
<code>listSize</code> times. This gives us <code>O(listSize * log(sampleSize))</code>.</p>
<p>That is of course the worst case complexity, which only occurs in the
special case where we need to insert into the heap at each step. That’s
only true when the list is sorted, so for a random list the average
complexity will be a lot better.</p></li>
<li><p>The complexity of <code>smallestN_lazy</code> is far harder to reason about.
Intuitively, and with the information that <code>Data.List.sort</code> is a merge sort,
I came to something like <code>O(listSize * max(sampleSize, log(listSize)))</code>.
I’m not sure if this is correct, and the case with a random list seems to be
faster.</p>
<p>I would be very interested in knowing the actual complexity of the lazy
version, so if you have any insights, be sure to let me know!</p>
<p><strong>Update</strong>: <a href="https://twitter.com/kmett">Edward Kmett</a> corrected me:
the complexity of <code>smallestN_lazy</code> is actually
<code>O(listSize * min(sampleSize, listSize))</code>, with
<code>O(listSize * min(sampleSize, log(listSize))</code> in
expectation for a random list.</p></li>
</ul>
<p>Thanks to <a href="https://github.com/HuwCampbell">Huw Campbell</a> for pointing out a bug
in the implementation of <code>smallestN_smart</code> – this is now fixed in the code
above.</p>
<h2 id="appendix">Appendix</h2>
<p>Helper function: check if all elements in a list are equal.</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="ot">equal ::</span> <span class="dt">Eq</span> a <span class="ot">=&gt;</span> [a] <span class="ot">-&gt;</span> <span class="dt">Bool</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>equal (x <span class="op">:</span> y <span class="op">:</span> zs) <span class="ot">=</span> x <span class="op">==</span> y <span class="op">&amp;&amp;</span> equal (y <span class="op">:</span> zs)</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>equal _            <span class="ot">=</span> <span class="dt">True</span></span></code></pre></div>]]></description>
    <pubDate>Thu, 17 Sep 2020 00:00:00 UT</pubDate>
    <guid>http://jaspervdj.be/posts/2020-09-17-lazysort.html</guid>
    <dc:creator>Jasper Van der Jeugt</dc:creator>
</item>
<item>
    <title>Photoessay: Pilatus</title>
    <link>http://jaspervdj.be/posts/2020-08-19-photoessay-pilatus.html</link>
    <description><![CDATA[<p>Now that we’re in a global pandemic, I’ve been doing significantly more hiking
in Switzerland. Around a month ago we climbed the Pilatus mountain near
Lucerne.</p>
<p>Unfortunately, there was a thick layer of clouds so we didn’t get the amazing
panoramic views from the top. On the flip side, this really works well with
black-and-white photography: the clouds add a lot of drama and character.
This is a selection of six photographs.</p>
<div class="photograph">
<p><img src="/images/2020-08-19-pilatus-01.jpg" /></p>
<p>This is the view from where we got of the gondola, looking towards the top. As
you can see, it’s possible to take gondolas all the way up as well.</p>
</div>
<div class="photograph">
<p><img src="/images/2020-08-19-pilatus-02.jpg" /></p>
<p>I did the climb together with three friends. We actually went there with a
larger group but split up near the start as some people wanted to do a longer
hike and decided to get off the gondola earlier.</p>
</div>
<div class="photograph">
<p><img src="/images/2020-08-19-pilatus-03.jpg" /></p>
<p>The first part was mostly easy and led us through some woods.</p>
</div>
<div class="photograph">
<p><img src="/images/2020-08-19-pilatus-04.jpg" /></p>
<p>After that the ascent was very steep. We took a lunch break near the
<em>Klimsenkapelle</em> chapel, visible in the background.</p>
</div>
<div class="photograph">
<p><img src="/images/2020-08-19-pilatus-05.jpg" /></p>
<p>This is another view looking up towards the top: after the lunch break, there
was only one part of the climb remaining, but it looked very intimidating.</p>
</div>
<div class="photograph">
<p><img src="/images/2020-08-19-pilatus-06.jpg" /></p>
<p>This final photograph is looking back to the <em>Klimsenkapelle</em>. It was taken
shortly before we made it to the peak.</p>
</div>]]></description>
    <pubDate>Wed, 19 Aug 2020 00:00:00 UT</pubDate>
    <guid>http://jaspervdj.be/posts/2020-08-19-photoessay-pilatus.html</guid>
    <dc:creator>Jasper Van der Jeugt</dc:creator>
</item>
<item>
    <title>Visual Arrow Syntax</title>
    <link>http://jaspervdj.be/posts/2020-03-12-visual-arrow-syntax.html</link>
    <description><![CDATA[<p><em>Not to be taken seriously.</em></p>
<p>Haskell is great building at DSLs – which are perhaps the ultimate
form of slacking off at work. Rather than actually doing the work your
manager tells you to, you can build DSLs to delegate this back to your
manager so you can focus on finally writing up that GHC proposal for
<code>MultilinePostfixTypeOperators</code> (which could have come in useful for this
blogpost).</p>
<p>So, we’ll build a visual DSL that’s so simple even your manager can use it!
<a href="https://github.com/jaspervdj/jaspervdj/blob/master/posts/2020-03-12-visual-arrow-syntax.lhs">This blogpost is a literate Haskell file</a> so you can run it directly
in GHCi. Note that some code is located in a <a href="https://github.com/jaspervdj/jaspervdj/blob/master/files/2020-03-12-demo.hs">second module</a> because of
compilation stage restrictions.</p>
<p>Let’s get started. We’ll need a few language extensions – not too much, just
enough to guarantee job security for the forseeable future.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE DataKinds #-}</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE GADTs #-}</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE KindSignatures #-}</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE LambdaCase #-}</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE PolyKinds #-}</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE TypeFamilies #-}</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE TypeOperators #-}</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="kw">module</span> <span class="dt">Visual</span> <span class="kw">where</span></span></code></pre></div>
<p>And then some imports, not much going on here.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell literate"><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="kw">qualified</span> <span class="dt">Codec.Picture</span> <span class="kw">as</span> <span class="dt">JP</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Codec.Picture.Types</span> <span class="kw">as</span> <span class="dt">JP</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Arrow</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Category</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.ST</span> (runST)</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Char</span> (isUpper)</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Foldable</span> (for_)</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.List</span> (sort, partition)</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Language.Haskell.TH</span> <span class="kw">as</span> <span class="dt">TH</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Prelude</span> <span class="kw">hiding</span> (id, (.))</span></code></pre></div>
<p>All Haskell tutorials that use some form of dependent typing seem to start
with the <code>HList</code> type. So I suppose we’ll do that as well.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell literate"><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">HList</span> (<span class="ot">things ::</span> [<span class="op">*</span>]) <span class="kw">where</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Nil</span><span class="ot">  ::</span> <span class="dt">HList</span> &#39;[]</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Cons</span><span class="ot"> ::</span> x <span class="ot">-&gt;</span> <span class="dt">HList</span> xs <span class="ot">-&gt;</span> <span class="dt">HList</span> (x &#39;<span class="op">:</span> xs)</span></code></pre></div>
<p>I think <code>HList</code> is short for hype list. There’s a lot of hype around this
because it allows you to put even more types in your types.</p>
<p>We’ll require two auxiliary functions for our hype list. Because of all the
hype, they each require a type family in order for us to even express their
types. The first one just takes the last element from a list.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ot">hlast ::</span> <span class="dt">HList</span> (thing &#39;<span class="op">:</span> things) <span class="ot">-&gt;</span> <span class="dt">Last</span> (thing &#39;<span class="op">:</span> things)</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>hlast (<span class="dt">Cons</span> x <span class="dt">Nil</span>)         <span class="ot">=</span> x</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>hlast (<span class="dt">Cons</span> _ (<span class="dt">Cons</span> y zs)) <span class="ot">=</span> hlast (<span class="dt">Cons</span> y zs)</span></code></pre></div>
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="kw">family</span> <span class="dt">Last</span> (<span class="ot">l ::</span> [<span class="op">*</span>])<span class="ot"> ::</span> <span class="op">*</span> <span class="kw">where</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Last</span> (x &#39;<span class="op">:</span> &#39;[]) <span class="ot">=</span> x</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Last</span> (x &#39;<span class="op">:</span> xs)  <span class="ot">=</span> <span class="dt">Last</span> xs</span></code></pre></div>
<p>Readers may wonder if this is safe, since <code>last</code> is usually a partial function.
Well, it turns out that partial functions are safe if you type them using
partial type families. So one takeaway is that partial functions can just be
fixed by adding more partial stuff on top. This explains things like <code>Prelude</code>.</p>
<p>Anyway, the second auxiliary function drops the last element from a list.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="ot">hinit ::</span> <span class="dt">HList</span> (thing &#39;<span class="op">:</span> things) <span class="ot">-&gt;</span> <span class="dt">HList</span> (<span class="dt">Init</span> (thing &#39;<span class="op">:</span> things))</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>hinit (<span class="dt">Cons</span> _ <span class="dt">Nil</span>)         <span class="ot">=</span> <span class="dt">Nil</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>hinit (<span class="dt">Cons</span> x (<span class="dt">Cons</span> y zs)) <span class="ot">=</span> <span class="dt">Cons</span> x (hinit (<span class="dt">Cons</span> y zs))</span></code></pre></div>
<div class="sourceCode" id="cb7"><pre class="sourceCode haskell literate"><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="kw">family</span> <span class="dt">Init</span> (<span class="ot">l ::</span> [<span class="op">*</span>])<span class="ot"> ::</span> [<span class="op">*</span>] <span class="kw">where</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Init</span> (_ &#39;<span class="op">:</span> &#39;[])     <span class="ot">=</span> &#39;[]</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Init</span> (x &#39;<span class="op">:</span> y &#39;<span class="op">:</span> zs) <span class="ot">=</span> x &#39;<span class="op">:</span> <span class="dt">Init</span> (y &#39;<span class="op">:</span> zs)</span></code></pre></div>
<p>And that’s enough boilerplate! Let’s get right to it.</p>
<p>It’s always good to pretend that your DSL is built on solid foundations. As I
alluded to in the title, we’ll pick Arrows. One reason for that is that they’re
easier to explain to your manager than Applicative (stuff goes in, other stuff
comes out, see? They’re like the coffee machine in the hallway). Secondly,
they are less powerful than Monads and we prefer to keep that good stuff to
ourselves.</p>
<p>Unfortunately, it seems like the Arrow module was contributed by an operator
fetishism cult, and anyone who’s ever done non-trivial work with Arrows now
has a weekly therapy session to talk about how <code>&amp;&amp;&amp;</code> and <code>***</code> hurt them.</p>
<p>This is not syntax we want anyone to use. Instead, we’ll, erm, <em>slightly</em>
bend Haskell’s syntax to get something that is “much nicer” and “definitely
not an abomination”.</p>
<p>We’ll build something that appeals to both Category Theorists (for street
cred) and Corporate Managers (for our bonus). These two groups have many
things in common. Apart from talking a lot about abstract nonsense and
getting paid for it, both <strong>love</strong> drawing boxes and arrows.</p>
<p><img src="/images/2020-03-12-industry-academia.jpg" /></p>
<p>Yeah, so I guess we can call this visual DSL a <code>Diagram</code>. The main drawback
of arrows is that they can only have a single input and output. This leads to a
lot of tuple abuse.</p>
<p>We’ll “fix” that by having extra <code>ins</code> and <code>outs</code>. We are wrapping an arbitrary
<code>Arrow</code>, referred to as <code>f</code> in the signature:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode haskell literate"><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">Diagram</span> (<span class="ot">ins ::</span> [<span class="op">*</span>]) (<span class="ot">outs ::</span> [<span class="op">*</span>]) f a b <span class="kw">where</span></span></code></pre></div>
<p>We can create a diagram from a normal arrow, that’s easy.</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Diagram</span><span class="ot"> ::</span> f a b <span class="ot">-&gt;</span> <span class="dt">Diagram</span> &#39;[] &#39;[] f a b</span></code></pre></div>
<p>And we can add another normal function at the back. No biggie.</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Then</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="ot">    ::</span> <span class="dt">Diagram</span> ins outs f a b <span class="ot">-&gt;</span> f b c</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>    <span class="ot">-&gt;</span> <span class="dt">Diagram</span> ins outs f a c</span></code></pre></div>
<p>Of course, we need to be able to use our extra input and outputs. <code>Output</code>
wraps an existing <code>Diagram</code> and redirects the second element of a tuple to the
<code>outs</code>; and <code>Input</code> does it the other way around.</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Output</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="ot">    ::</span> <span class="dt">Diagram</span> ins outs f a (b, o)</span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>    <span class="ot">-&gt;</span> <span class="dt">Diagram</span> ins (o &#39;<span class="op">:</span> outs) f a b</span></code></pre></div>
<div class="sourceCode" id="cb12"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Input</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="ot">    ::</span> <span class="dt">Diagram</span> ins outs f a b</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>    <span class="ot">-&gt;</span> <span class="dt">Diagram</span> (i &#39;<span class="op">:</span> ins) outs f a (b, i)</span></code></pre></div>
<p>The hardest part is connecting two existing diagrams. This is really where
the magic happens:</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Below</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="ot">    ::</span> <span class="dt">Diagram</span> ins1 outs1 f a b</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>    <span class="ot">-&gt;</span> <span class="dt">Diagram</span> (<span class="dt">Init</span> (b &#39;<span class="op">:</span> outs1)) outs2 f (<span class="dt">Last</span> (b &#39;<span class="op">:</span> outs1)) c</span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>    <span class="ot">-&gt;</span> <span class="dt">Diagram</span> ins1 outs2 f a c</span></code></pre></div>
<p>Is this correct? What does it even mean? The answer to both questions is: “I
don’t know”. It typechecks, which is what really matters when you’re doing
Haskell. And there’s something about <code>ins</code> matching <code>outs</code> in there, yeah.</p>
<p>Concerned readers of this blog may at this point be wondering why we used
reasonable names for the constructors of <code>Diagram</code> rather than just operators.</p>
<p>Well, it’s only because it’s a GADT which makes this impossible. But fear
not, we can claim our operators back. Shout out to Unicode’s <a href="https://en.wikipedia.org/wiki/Box-drawing_character">Box-drawing
characters</a>: they provide various charaters with thick <em>and</em> thin lines.
This lets us do an, uhm, <em>super intuitive syntax</em> where tuples are taken apart
as extra inputs/outputs, or reified back into tuples.</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a>(━►)   <span class="ot">=</span> <span class="dt">Then</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>l ┭► r <span class="ot">=</span> <span class="dt">Output</span> l ━► r</span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>l ┳► r <span class="ot">=</span> (l ━► arr (\x <span class="ot">-&gt;</span> (x, x))) ┭► r</span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>l ┶► r <span class="ot">=</span> <span class="dt">Input</span> l ━► r</span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>l ╆► r <span class="ot">=</span> <span class="dt">Output</span> (<span class="dt">Input</span> l ━► arr (\x <span class="ot">-&gt;</span> (x, x))) ━► r</span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>l ┳ c  <span class="ot">=</span> l ┳► arr (<span class="fu">const</span> c)</span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a>l ┓ r  <span class="ot">=</span> <span class="dt">Below</span> l r</span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a>l ┧ r  <span class="ot">=</span> <span class="dt">Input</span> l ┓ r</span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a>l ┃ r  <span class="ot">=</span> <span class="dt">Input</span> l ━► arr <span class="fu">snd</span> ┓ r</span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a><span class="kw">infixl</span> <span class="dv">5</span> ━►, ┳►, ┭►, ┶►, ╆►, ┳</span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a><span class="kw">infixr</span> <span class="dv">4</span> ┓, ┧, ┃</span></code></pre></div>
<p>Finally, while we’re at it, we’ll also include an operator to clearly indicate
to our manager how our valuation will change if we adopt this DSL.</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a>(📈) <span class="ot">=</span> <span class="dt">Diagram</span></span></code></pre></div>
<p>This lets us do the basics. If we start from regular Arrow syntax:</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a>horribleExample01 <span class="ot">=</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>  partition <span class="fu">isUpper</span> <span class="op">&gt;&gt;&gt;</span> <span class="fu">reverse</span> <span class="op">***</span> <span class="fu">sort</span> <span class="op">&gt;&gt;&gt;</span> <span class="fu">uncurry</span> <span class="fu">mappend</span></span></code></pre></div>
<p>We can now turn this into:</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a>amazingExample01 <span class="ot">=</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a> (📈) (partition <span class="fu">isUpper</span>)┭►reverse┓</span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a> (📈)                   <span class="fu">sort</span>      ┶►(<span class="fu">uncurry</span> <span class="fu">mappend</span>)</span></code></pre></div>
<p>The trick to decrypting these diagrams is that each line in the source code
consists of an arrow where values flow from the left to the right; with possible
extra inputs and ouputs in between. These lines are then composed using a few
operators that use <code>Below</code> such as <code>┓</code> and <code>┧</code>.</p>
<p>To improve readability even further, it should also be possible to add
right-to-left and top-to-bottom operators. I asked my manager if they wanted
these extra operators but they’ve been ignoring all my Slack messages since I
showed them my original prototype. Probably just busy?</p>
<p>Anyway, there are other simple improvements we can make to the visual DSL first.
Most Haskellers prefer nicely aligning things over producing working code,
so it would be nice if we could draw longer lines like <code>━━━━┳━►</code> rather than
just <code>┳►</code>. And any Haskeller worth their salt will tell you that this is where
Template Haskell comes in.</p>
<p>Template Haskell gets a bad rep, but that’s only because it is mostly misused.
Originally, it was designed to avoid copying and pasting a lot of code, which is
<strong>exactly</strong> what we’ll do here. Nothing to be grossed out about.</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="ot">extensions ::</span> <span class="dt">Maybe</span> <span class="dt">Char</span> <span class="ot">-&gt;</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Maybe</span> <span class="dt">Char</span> <span class="ot">-&gt;</span> [<span class="dt">String</span>]</span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>extensions mbLeft operator mbRight <span class="ot">=</span></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>  [operator] <span class="op">&gt;&gt;=</span> <span class="fu">maybe</span> <span class="fu">pure</span> goR mbRight <span class="op">&gt;&gt;=</span> <span class="fu">maybe</span> <span class="fu">pure</span> goL mbLeft</span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a>  goL l op <span class="ot">=</span> [<span class="fu">replicate</span> n l <span class="op">++</span> op <span class="op">|</span> n <span class="ot">&lt;-</span> [<span class="dv">1</span> <span class="op">..</span> <span class="dv">19</span>]]</span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a>  goR r op <span class="ot">=</span> [<span class="fu">init</span> op <span class="op">++</span> <span class="fu">replicate</span> n r <span class="op">++</span> [<span class="fu">last</span> op] <span class="op">|</span> n <span class="ot">&lt;-</span> [<span class="dv">1</span> <span class="op">..</span> <span class="dv">19</span>]]</span></code></pre></div>
<div class="sourceCode" id="cb19"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a>industryStandardBoilerplate</span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a><span class="ot">  ::</span> <span class="dt">Maybe</span> <span class="dt">Char</span> <span class="ot">-&gt;</span> <span class="dt">TH.Name</span> <span class="ot">-&gt;</span> <span class="dt">Maybe</span> <span class="dt">Char</span> <span class="ot">-&gt;</span> <span class="dt">TH.Q</span> [<span class="dt">TH.Dec</span>]</span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>industryStandardBoilerplate l name r <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a>  sig <span class="ot">&lt;-</span> TH.reify name <span class="op">&gt;&gt;=</span> \<span class="kw">case</span></span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">TH.VarI</span> _ sig _ <span class="ot">-&gt;</span> <span class="fu">pure</span> sig</span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a>    _               <span class="ot">-&gt;</span> <span class="fu">fail</span> <span class="st">&quot;no info&quot;</span></span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a>  fixity <span class="ot">&lt;-</span> TH.reifyFixity name <span class="op">&gt;&gt;=</span> <span class="fu">maybe</span> (<span class="fu">fail</span> <span class="st">&quot;no fixity&quot;</span>) <span class="fu">pure</span></span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a>  <span class="fu">pure</span></span>
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a>    [ decl</span>
<span id="cb19-10"><a href="#cb19-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">|</span> name&#39; <span class="ot">&lt;-</span> <span class="fu">fmap</span> TH.mkName <span class="op">$</span> extensions l (TH.nameBase name) r</span>
<span id="cb19-11"><a href="#cb19-11" aria-hidden="true" tabindex="-1"></a>    , decl  <span class="ot">&lt;-</span></span>
<span id="cb19-12"><a href="#cb19-12" aria-hidden="true" tabindex="-1"></a>        [ <span class="dt">TH.SigD</span> name&#39; sig</span>
<span id="cb19-13"><a href="#cb19-13" aria-hidden="true" tabindex="-1"></a>        , <span class="dt">TH.FunD</span> name&#39; [<span class="dt">TH.Clause</span> [] (<span class="dt">TH.NormalB</span> (<span class="dt">TH.VarE</span> name)) []]</span>
<span id="cb19-14"><a href="#cb19-14" aria-hidden="true" tabindex="-1"></a>        , <span class="dt">TH.InfixD</span> fixity name&#39;</span>
<span id="cb19-15"><a href="#cb19-15" aria-hidden="true" tabindex="-1"></a>        ]</span>
<span id="cb19-16"><a href="#cb19-16" aria-hidden="true" tabindex="-1"></a>    ]</span></code></pre></div>
<p>We can then invoke this industry standard boilerplate to extend and copy/paste
an operator like this:</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">$</span>(industryStandardBoilerplate (<span class="dt">Just</span> <span class="ch">&#39;━&#39;</span>) &#39;(┭►) (<span class="dt">Just</span> <span class="ch">&#39;─&#39;</span>))</span></code></pre></div>
<p>We’re now equipped to silence even the harshest syntax critics:</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>example02 <span class="ot">=</span></span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>  (📈) (partition <span class="fu">isUpper</span>)━┭─►(<span class="fu">reverse</span>)━┓</span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>  (📈)                   (<span class="fu">sort</span>)─────────┶━►(<span class="fu">uncurry</span> <span class="fu">mappend</span>)</span></code></pre></div>
<p>Beautiful! If you’ve ever wondered what people mean when they say functional
programs “compose elegantly”, well, this is what they mean.</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>example03 <span class="ot">=</span></span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>  (📈) (<span class="op">+</span><span class="dv">1</span>)━┳━►(<span class="op">+</span><span class="dv">1</span>)━┓</span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a>  (📈)      (<span class="op">+</span><span class="dv">1</span>)━━━━╆━►add━┓</span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a>  (📈)              add────┶━►add</span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a>  add <span class="ot">=</span> <span class="fu">uncurry</span> (<span class="op">+</span>)</span></code></pre></div>
<p>Type inference is excellent and running is easy. In GHCi:</p>
<pre><code>*Main&gt; :t example03
example04 :: Diagram &#39;[] &#39;[] (-&gt;) Integer Integer
*Main&gt; run example03 1
12</code></pre>
<p>Let’s look at a more complicated example.</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>lambda <span class="ot">=</span></span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>  (📈)  (<span class="fu">id</span>)━┭─►(<span class="fu">subtract</span> <span class="fl">0.5</span>)━┳━━━━━━━━►(<span class="op">&lt;</span> <span class="dv">0</span>)━━━━━━━━━━┓</span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>  (📈)    (<span class="fu">subtract</span> <span class="fl">0.5</span>)───────╆━►(add)━►(<span class="fu">abs</span>)━►(<span class="op">&lt;</span> <span class="fl">0.1</span>)─┶━━━━━━━►(<span class="fu">and</span>)━━━━━━━┓</span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a>  (📈)                      (swap)━┭─►(<span class="op">*</span> <span class="fu">pi</span>)━━►(<span class="fu">sin</span>)┳()                      ┃</span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a>  (📈)                           (<span class="op">*</span> <span class="dv">2</span>)──────────────┶━►(sub)━►(<span class="fu">abs</span>)━►(<span class="op">&lt;</span> <span class="fl">0.2</span>)─┧</span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a>  (📈)                                                                      (<span class="fu">or</span>)━►(bool bg fg)</span>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb24-8"><a href="#cb24-8" aria-hidden="true" tabindex="-1"></a>  add <span class="ot">=</span> <span class="fu">uncurry</span> (<span class="op">+</span>)</span>
<span id="cb24-9"><a href="#cb24-9" aria-hidden="true" tabindex="-1"></a>  sub <span class="ot">=</span> <span class="fu">uncurry</span> (<span class="op">-</span>)</span>
<span id="cb24-10"><a href="#cb24-10" aria-hidden="true" tabindex="-1"></a>  <span class="fu">and</span> <span class="ot">=</span> <span class="fu">uncurry</span> (<span class="op">&amp;&amp;</span>)</span>
<span id="cb24-11"><a href="#cb24-11" aria-hidden="true" tabindex="-1"></a>  <span class="fu">or</span>  <span class="ot">=</span> <span class="fu">uncurry</span> (<span class="op">||</span>)</span>
<span id="cb24-12"><a href="#cb24-12" aria-hidden="true" tabindex="-1"></a>  fg  <span class="ot">=</span> <span class="dt">JP.PixelRGB8</span> <span class="dv">69</span>  <span class="dv">58</span>  <span class="dv">98</span></span>
<span id="cb24-13"><a href="#cb24-13" aria-hidden="true" tabindex="-1"></a>  bg  <span class="ot">=</span> <span class="dt">JP.PixelRGB8</span> <span class="dv">255</span> <span class="dv">255</span> <span class="dv">255</span></span></code></pre></div>
<p>This renders everyone’s favorite greek letter:</p>
<p><img src="/images/2020-03-12-lambda.png" style="width:30.0%" /></p>
<p>Amazing! Math!</p>
<p>While the example diagrams in this post all use the pure function arrow <code>-&gt;</code>,
it is my duty as a Haskeller to note that it is really parametric in <code>f</code> or
something. What this means is that thanks to this famous guy called <a href="https://hackage.haskell.org/package/base-4.12.0.0/docs/Control-Arrow.html#t:Kleisli">Kleisli</a>,
you can immediately start using this with <code>IO</code> in production. Thanks for
reading!</p>
<p><strong>Update</strong>: <a href="https://twitter.com/CarlHedgren">CarlHedgren</a> pointed out to me
that a similar DSL is provided by <a href="https://hackage.haskell.org/package/needle-0.1.0.1">Control.Arrow.Needle</a>. However, that
package uses Template Haskell to just parse the diagram. In this blogpost, the
point of the exercise is to bend Haskell’s syntax and type system to achieve
the notation.</p>
<h2 id="appendix-1-run-implementation">Appendix 1: run implementation</h2>
<p>The implementation of <code>run</code> uses a helper function that lets us convert
a diagram back to a normal <code>Arrow</code> that uses <code>HList</code> to pass extra inputs
and outputs:</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a>fromDiagram</span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a><span class="ot">  ::</span> <span class="dt">Arrow</span> f <span class="ot">=&gt;</span> <span class="dt">Diagram</span> ins outs f a b</span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> f (a, <span class="dt">HList</span> ins) (b, <span class="dt">HList</span> outs)</span></code></pre></div>
<p>We can then have a specialized version for when there’s zero extra inputs
and outputs. This great simplifies the type signatures and gives us a
“normal” <code>f a b</code>:</p>
<div class="sourceCode" id="cb26"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><span class="ot">run ::</span> <span class="dt">Arrow</span> f <span class="ot">=&gt;</span> <span class="dt">Diagram</span> &#39;[] &#39;[] f a b <span class="ot">-&gt;</span> f a b</span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a>run d <span class="ot">=</span> <span class="fu">id</span> <span class="op">&amp;&amp;&amp;</span> (arr (<span class="fu">const</span> <span class="dt">Nil</span>)) <span class="op">&gt;&gt;&gt;</span> fromDiagram d <span class="op">&gt;&gt;&gt;</span> arr <span class="fu">fst</span></span></code></pre></div>
<p>The definition for <code>fromDiagram</code> is as follows:</p>
<div class="sourceCode" id="cb27"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a>fromDiagram (<span class="dt">Diagram</span> f) <span class="ot">=</span> f <span class="op">***</span> arr (<span class="fu">const</span> <span class="dt">Nil</span>)</span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a>fromDiagram (<span class="dt">Then</span> l r) <span class="ot">=</span> fromDiagram l <span class="op">&gt;&gt;&gt;</span> first r</span>
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a>fromDiagram (<span class="dt">Output</span> l) <span class="ot">=</span></span>
<span id="cb27-4"><a href="#cb27-4" aria-hidden="true" tabindex="-1"></a>  fromDiagram l <span class="op">&gt;&gt;&gt;</span> arr (\((x, y), things) <span class="ot">-&gt;</span> (x, <span class="dt">Cons</span> y things))</span>
<span id="cb27-5"><a href="#cb27-5" aria-hidden="true" tabindex="-1"></a>fromDiagram (<span class="dt">Input</span> l) <span class="ot">=</span></span>
<span id="cb27-6"><a href="#cb27-6" aria-hidden="true" tabindex="-1"></a>  arr (\(x, <span class="dt">Cons</span> a things) <span class="ot">-&gt;</span> ((x, things), a)) <span class="op">&gt;&gt;&gt;</span></span>
<span id="cb27-7"><a href="#cb27-7" aria-hidden="true" tabindex="-1"></a>  first (fromDiagram l) <span class="op">&gt;&gt;&gt;</span></span>
<span id="cb27-8"><a href="#cb27-8" aria-hidden="true" tabindex="-1"></a>  arr (\((y, outs), a) <span class="ot">-&gt;</span> ((y, a), outs))</span>
<span id="cb27-9"><a href="#cb27-9" aria-hidden="true" tabindex="-1"></a>fromDiagram (<span class="dt">Below</span> l r) <span class="ot">=</span></span>
<span id="cb27-10"><a href="#cb27-10" aria-hidden="true" tabindex="-1"></a>  fromDiagram l <span class="op">&gt;&gt;&gt;</span></span>
<span id="cb27-11"><a href="#cb27-11" aria-hidden="true" tabindex="-1"></a>  arr (\(x, outs) <span class="ot">-&gt;</span> (hlast (<span class="dt">Cons</span> x outs), hinit (<span class="dt">Cons</span> x outs))) <span class="op">&gt;&gt;&gt;</span></span>
<span id="cb27-12"><a href="#cb27-12" aria-hidden="true" tabindex="-1"></a>  fromDiagram r</span></code></pre></div>
<h2 id="appendix-2-some-type-signatures">Appendix 2: some type signatures</h2>
<p>We wouldn’t want these to get in our way in the middle of the prose, but GHC
complains if we don’t put them somewhere.</p>
<div class="sourceCode" id="cb28"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a>(┳►)<span class="ot"> ::</span> <span class="dt">Arrow</span> f <span class="ot">=&gt;</span> <span class="dt">Diagram</span> ins outs f a b <span class="ot">-&gt;</span> f b c</span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a>     <span class="ot">-&gt;</span> <span class="dt">Diagram</span> ins (b &#39;<span class="op">:</span> outs) f a c</span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a>(┭►)<span class="ot"> ::</span> <span class="dt">Arrow</span> f <span class="ot">=&gt;</span> <span class="dt">Diagram</span> ins outs f a (b, o) <span class="ot">-&gt;</span> f b c</span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a>     <span class="ot">-&gt;</span> <span class="dt">Diagram</span> ins (o &#39;<span class="op">:</span> outs) f a c</span>
<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a>(┶►)<span class="ot"> ::</span> <span class="dt">Diagram</span> ins outs f a b <span class="ot">-&gt;</span> f (b, i) c</span>
<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a>     <span class="ot">-&gt;</span> <span class="dt">Diagram</span> (i &#39;<span class="op">:</span> ins) outs f a c</span>
<span id="cb28-7"><a href="#cb28-7" aria-hidden="true" tabindex="-1"></a>(╆►)<span class="ot"> ::</span> <span class="dt">Arrow</span> f <span class="ot">=&gt;</span> <span class="dt">Diagram</span> ins outs f a b <span class="ot">-&gt;</span> f (b, u) c</span>
<span id="cb28-8"><a href="#cb28-8" aria-hidden="true" tabindex="-1"></a>     <span class="ot">-&gt;</span> <span class="dt">Diagram</span> (u &#39;<span class="op">:</span> ins) ((b, u) &#39;<span class="op">:</span> outs) f a c</span>
<span id="cb28-9"><a href="#cb28-9" aria-hidden="true" tabindex="-1"></a>(┧)<span class="ot">  ::</span> <span class="dt">Diagram</span> ins1 outs1 f a b</span>
<span id="cb28-10"><a href="#cb28-10" aria-hidden="true" tabindex="-1"></a>     <span class="ot">-&gt;</span> <span class="dt">Diagram</span> (<span class="dt">Init</span> ((b, u) &#39;<span class="op">:</span> outs1)) outs2 f (<span class="dt">Last</span> ((b, u) &#39;<span class="op">:</span> outs1)) c</span>
<span id="cb28-11"><a href="#cb28-11" aria-hidden="true" tabindex="-1"></a>     <span class="ot">-&gt;</span> <span class="dt">Diagram</span> (u &#39;<span class="op">:</span> ins1) outs2 f a c</span></code></pre></div>
<h2 id="appendix-3-image-rendering-boilerplate">Appendix 3: image rendering boilerplate</h2>
<p>This uses a user-supplied <code>Diagram</code> to render an image.</p>
<div class="sourceCode" id="cb29"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a>image</span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a><span class="ot">  ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> <span class="dt">Diagram</span> &#39;[] &#39;[] (<span class="ot">-&gt;</span>) (<span class="dt">Double</span>, <span class="dt">Double</span>) <span class="dt">JP.PixelRGB8</span></span>
<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> <span class="dt">JP.Image</span> <span class="dt">JP.PixelRGB8</span></span>
<span id="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a>image w h diagram <span class="ot">=</span> runST <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb29-6"><a href="#cb29-6" aria-hidden="true" tabindex="-1"></a>  img <span class="ot">&lt;-</span> JP.newMutableImage w h</span>
<span id="cb29-7"><a href="#cb29-7" aria-hidden="true" tabindex="-1"></a>  for_ [<span class="dv">0</span> <span class="op">..</span> h <span class="op">-</span> <span class="dv">1</span>] <span class="op">$</span> \y <span class="ot">-&gt;</span></span>
<span id="cb29-8"><a href="#cb29-8" aria-hidden="true" tabindex="-1"></a>    for_ [<span class="dv">0</span> <span class="op">..</span> w <span class="op">-</span> <span class="dv">1</span>] <span class="op">$</span> \x <span class="ot">-&gt;</span></span>
<span id="cb29-9"><a href="#cb29-9" aria-hidden="true" tabindex="-1"></a>      <span class="kw">let</span> x&#39; <span class="ot">=</span> <span class="fu">fromIntegral</span> x <span class="op">/</span> <span class="fu">fromIntegral</span> (w <span class="op">-</span> <span class="dv">1</span>)</span>
<span id="cb29-10"><a href="#cb29-10" aria-hidden="true" tabindex="-1"></a>          y&#39; <span class="ot">=</span> <span class="fu">fromIntegral</span> y <span class="op">/</span> <span class="fu">fromIntegral</span> (h <span class="op">-</span> <span class="dv">1</span>) <span class="kw">in</span></span>
<span id="cb29-11"><a href="#cb29-11" aria-hidden="true" tabindex="-1"></a>      JP.writePixel img x y <span class="op">$</span> run diagram (x&#39;, y&#39;)</span>
<span id="cb29-12"><a href="#cb29-12" aria-hidden="true" tabindex="-1"></a>  JP.freezeImage img</span></code></pre></div>]]></description>
    <pubDate>Thu, 12 Mar 2020 00:00:00 UT</pubDate>
    <guid>http://jaspervdj.be/posts/2020-03-12-visual-arrow-syntax.html</guid>
    <dc:creator>Jasper Van der Jeugt</dc:creator>
</item>
<item>
    <title>Zero-config MiniDLNA/ReadyMedia</title>
    <link>http://jaspervdj.be/posts/2020-02-26-zero-config-minidlna.html</link>
    <description><![CDATA[<h1 id="tldr">TL;DR:</h1>
<p>You can use <a href="http://minidlna.sourceforge.net/">ReadyMedia</a> without configuring it as a daemon. Just <code>cd</code>
into any directory that has media files, and run this script:</p>
<script src="https://gist.github.com/jaspervdj/64177596eb3aec4fe38ae117fc63db42.js"></script>
<noscript>
<div class="sourceCode" id="cb1"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="co">#!/bin/bash</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="bu">set</span> <span class="at">-o</span> nounset <span class="at">-o</span> errexit <span class="at">-o</span> pipefail</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="co"># Create temporary locations for the configuration and data directories.</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="va">CONFIG</span><span class="op">=</span><span class="st">&quot;</span><span class="va">$(</span><span class="fu">mktemp</span><span class="va">)</span><span class="st">&quot;</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="va">DATADIR</span><span class="op">=</span><span class="st">&quot;</span><span class="va">$(</span><span class="fu">mktemp</span> <span class="at">-d</span><span class="va">)</span><span class="st">&quot;</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="co"># Write the configuration to the temporary location.</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="bu">echo</span> <span class="st">&quot;media_dir=</span><span class="va">$PWD</span><span class="st">&quot;</span> <span class="op">&gt;&gt;</span><span class="st">&quot;</span><span class="va">$CONFIG</span><span class="st">&quot;</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="bu">echo</span> <span class="st">&quot;db_dir=</span><span class="va">$DATADIR</span><span class="st">&quot;</span> <span class="op">&gt;&gt;</span><span class="st">&quot;</span><span class="va">$CONFIG</span><span class="st">&quot;</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="bu">echo</span> <span class="st">&quot;log_dir=</span><span class="va">$DATADIR</span><span class="st">&quot;</span> <span class="op">&gt;&gt;</span><span class="st">&quot;</span><span class="va">$CONFIG</span><span class="st">&quot;</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a><span class="bu">echo</span> <span class="st">&#39;force_sort_criteria=+upnp:class,+upnp:originalTrackNumber,+dc:title&#39;</span> <span class="op">&gt;&gt;</span><span class="st">&quot;</span><span class="va">$CONFIG</span><span class="st">&quot;</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a><span class="fu">cat</span> <span class="va">$CONFIG</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a><span class="co"># Make sure everything is cleaned up when this process is killed.</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a><span class="kw">function</span><span class="fu"> cleanup</span> <span class="kw">{</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>  <span class="fu">rm</span> <span class="at">-r</span> <span class="st">&quot;</span><span class="va">$DATADIR</span><span class="st">&quot;</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>  <span class="fu">rm</span> <span class="st">&quot;</span><span class="va">$CONFIG</span><span class="st">&quot;</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a><span class="kw">}</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a><span class="bu">trap</span> cleanup exit</span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a><span class="co"># Run minidlnad with the following flags:</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a><span class="co">#</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a><span class="co">#  -  `-f &quot;$CONFIG&quot;`: use the configuration we wrote.</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a><span class="co">#  -  `-f &quot;$PWD/minidlnad.pid&quot;`: store the `.pid` in the current directory.</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a><span class="co">#  -  `-d`: don&#39;t daemonize, we&#39;ll kill this when we&#39;re done.  This also</span></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a><span class="co">#     enabled &quot;debug&quot; mode; but I haven&#39;t seen any considerable slowdown</span></span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a><span class="co">#     from this.</span></span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a><span class="ex">minidlnad</span> <span class="at">-f</span> <span class="st">&quot;</span><span class="va">$CONFIG</span><span class="st">&quot;</span> <span class="at">-P</span> <span class="st">&quot;</span><span class="va">$PWD</span><span class="st">/minidlnad.pid&quot;</span> <span class="at">-d</span></span></code></pre></div>
</noscript>
<p>Your television/phone/toaster should see the media server pop up within seconds.</p>
<h1 id="motivation">Motivation</h1>
<p>In this day and age, there are literally thousands of ways to get video on to
your television screen, especially if you have a (somewhat) smart TV. If not,
there is a plethora of devices that will let you stream from different sources.</p>
<p>For simply watching video files on my local disk, I used to just hook my laptop
up to the television using a simple HDMI cable, which always worked – until the
HDMI port on my television broke.</p>
<p>I don’t really want to get any of these devices, and I’m also not sure if I need
a newer television that <a href="https://en.wikipedia.org/wiki/Phoning_home">phones home</a>.</p>
<p>In either case, most televisions that support any kind of networking will
also support the <a href="https://www.dlna.org/">DLNA</a> protocol. For Linux, there’s <a href="http://minidlna.sourceforge.net/">ReadyMedia</a> (formerly
MiniDLNA), a relatively old project. But despite lacking some maintenance,
it is pretty solid and reliable software.</p>
<p>By default, it runs as a daemon that stores a database of media. This makes it
very cumbersome to use. The database gets out of sync easily when you move
files around when it’s not running. The fact that it’s a daemon means that
it could be running when you’re working from a coffee place. The daemon
needs to be managed through a file in <code>/etc/</code>.</p>
<p>I don’t want to go through all that pain! I just want to be able to fire it up
like you can get a quick HTTP server with just running <code>python -m http.server</code>
in any directory. Then I can <code>cd</code> to whatever I want to watch and just run the
thing and then kill it. I don’t care about keeping this media database, since
scanning a single directory should be quick.</p>
<p>Well, it turns out you can do that fairly easily. Just drop the script I linked
to at the top of this post in to your <code>$PATH</code> and you’re good to go.</p>]]></description>
    <pubDate>Wed, 26 Feb 2020 00:00:00 UT</pubDate>
    <guid>http://jaspervdj.be/posts/2020-02-26-zero-config-minidlna.html</guid>
    <dc:creator>Jasper Van der Jeugt</dc:creator>
</item>
<item>
    <title>Mandelbrot &amp; Lovejoy&#39;s Rain Fractals</title>
    <link>http://jaspervdj.be/posts/2020-01-04-mandelbrot-lovejoy-rain.html</link>
    <description><![CDATA[<h1 id="summary">Summary</h1>
<p>At some point during <a href="https://icfp19.sigplan.org/">ICFP2019</a> in Berlin, I came across a completely unrelated
<a href="https://www.tandfonline.com/doi/pdf/10.3402/tellusa.v37i3.11668">old paper</a> by S. Lovejoy and B. B. Mandelbrot called <em>“Fractal properties
of rain, and a fractal model”</em>.</p>
<p>While the model in the paper is primarily meant to model rain<strong>fall</strong>; the
authors explain that it can also be used for rain<strong>clouds</strong>, since these two
phenomena are naturally similarly-shaped. This means it can be used to generate
pretty pictures!</p>
<p><img src="/images/2020-01-04-2d.jpg" /></p>
<p>While it looked cool at first, it turned out to be an extremely pointless and
outdated way to generate pictures like this. But I wanted to write it up anyway
since it is important to document failure as well as success: if you’ve found
this blogpost searching for an implementation of this paper; well, you have
found it, but it probably won’t help you.
<a href="https://github.com/jaspervdj/mandelbrot-lovejoy-rain/.">Here is the GitHub repository</a>.</p>
<h1 id="the-good-parts">The good parts</h1>
<p>I found this paper very intriguing because it promises a fractal model with a
number of very attractive features:</p>
<ul>
<li>is extremely simple</li>
<li>has easy to understand parameters</li>
<li>is truly self-similar at different scales</li>
<li>it has great <a href="https://en.wikipedia.org/wiki/Lacunarity">lacunarity</a>
(I must admit I didn’t know this word before going through this paper)</li>
</ul>
<p>Most excitingly, it’s possible to do a dimension-generic implementation! The
code has examples in 2D as well as 3D (xy, time), but can be used without
modifications for 4D (xyz, time) and beyond. Haskell’s type system allows
capturing the dimension in a type parameter so we don’t need to sacrifice any
type safety in the process.</p>
<p>For example, here the dimension-generic distance function I used with <a href="https://github.com/lehins/massiv/blob/master/README.md">massiv</a>:</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">distance ::</span> <span class="dt">M.Index</span> ix <span class="ot">=&gt;</span> ix <span class="ot">-&gt;</span> ix <span class="ot">-&gt;</span> <span class="dt">Distance</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>distance i j <span class="ot">=</span> <span class="dt">Distance</span> <span class="op">.</span> <span class="fu">sqrt</span> <span class="op">.</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    <span class="fu">fromIntegral</span> <span class="op">.</span>  M.foldlIndex (<span class="op">+</span>) <span class="dv">0</span> <span class="op">$</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    M.liftIndex2 (\p s <span class="ot">-&gt;</span> (p <span class="op">-</span> s) <span class="op">*</span> (p <span class="op">-</span> s)) i j</span></code></pre></div>
<p>Here is a 3D version:</p>
<div style="text-align: center;">
<iframe width="100%" height="315" src="https://www.youtube.com/embed/KRZ_6Rh6prE" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen>
</iframe>
</div>
<h1 id="the-really-bad-parts">The (really) bad parts</h1>
<p>However, there must be a catch, right? If it has all these amazing properties,
why is nobody using it? I didn’t see any existing implementations; and even
though I had a very strong suspicion as to why that was the case, I set out to
implement it during <a href="https://munihac.de/2019.html">Munihac 2019</a>.</p>
<p>As I was working on it, the answer quickly became apparent – the algorithm is
so slow that its speed cannot even be considered a trade-off, its slowness
really cancels out all advantages and then some! BitCoin may even be a better
use of compute resources. The 30 second video clip I embedded earlier took 8
hours to render on a 16-core machine.</p>
<p>This was a bit of a bummer on two fronts: the second one being that I wanted to
use this as a vehicle to learn some GPU programming; and it turned out to be a
bad fit for GPU programming as well.</p>
<p>At a very high-level, the algorithm repeats the following steps many, many
times:</p>
<ol type="1">
<li>At random, pick a position in (or near) the image.</li>
<li>Pick a size for your circular shape in a way that the probability of the
size being larger than <em>P</em> is <em>P⁻¹</em>.</li>
<li>Draw the circular shape onto the image.</li>
</ol>
<p>This sounds great for GPU programming; we could generate a large number of
images and then just sum them together. However, the probability distribution
from step 2 is problematic. Small (≤3x3) shapes are so common that it seems
faster use a CPU (or, you know, 16 CPUs) and just draw that specific region onto
a single image.</p>
<p>The paper proposes 3 shapes (which it calls “pulses”). It starts out with just
drawing plain opaque circles with a hard edge. This causes some interesting but
generally bad-looking edges:</p>
<figure>
<img src="/images/2020-01-04-hard.jpg" alt="Hard circular pulses" />
<figcaption aria-hidden="true">Hard circular pulses</figcaption>
</figure>
<p>It then switches to using circles with smoothed edges; which looks much better,
we’re getting properly puffy clouds here:</p>
<figure>
<img src="/images/2020-01-04-smooth.jpg" alt="Smooth circular pulses" />
<figcaption aria-hidden="true">Smooth circular pulses</figcaption>
</figure>
<p>Finally, the paper discusses drawing smoothed-out <a href="https://en.wikipedia.org/wiki/Annulus_(mathematics)">annuli</a>, which
dramatically changes the shapes of the clouds:</p>
<figure>
<img src="/images/2020-01-04-annuli.jpg" alt="Annular pulses" />
<figcaption aria-hidden="true">Annular pulses</figcaption>
</figure>
<p>It’s mildly interesting that the annuli become hollow spheres in 3D.</p>
<p>Thanks to <a href="https://alexey.kuleshevi.ch/">Alexey</a> for <a href="https://github.com/lehins/massiv/blob/master/README.md">massiv</a> and a massive list of <a href="https://github.com/jaspervdj/mandelbrot-lovejoy-rain/pull/1">suggestions</a> on my
implementation!</p>]]></description>
    <pubDate>Sat, 04 Jan 2020 00:00:00 UT</pubDate>
    <guid>http://jaspervdj.be/posts/2020-01-04-mandelbrot-lovejoy-rain.html</guid>
    <dc:creator>Jasper Van der Jeugt</dc:creator>
</item>
<item>
    <title>Partial application using flip</title>
    <link>http://jaspervdj.be/posts/2019-10-15-flip-partial-application.html</link>
    <description><![CDATA[<p>I have been writing Haskell for a reasonable time now – I believe I am coming
up on ten years – so sadly the frequency with which I discover delightful
things about the language has decreased.</p>
<p>However, I was talking with <a href="https://twitter.com/hvrgnu">HVR</a> about the
<a href="/posts/2018-03-08-handle-pattern.html">Handle</a> pattern, and the topic of <em>argument order</em> came up. This lead
me to a neat use case for <code>flip</code> that I hadn’t seen before.</p>
<p>This blogpost should be approachable for beginners, but when you’re completely
new to Haskell and some terms are confusing, I would recommend looking at the
<a href="https://typeclasses.com/">Type Classes</a> or <a href="http://learnyouahaskell.com/">Learn You a
Haskell</a> materials first.</p>
<p>A few extensions are required to show some intermediary results, but – <em>spoiler
alert</em> – they turn out to be unnecessary in the end:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE MultiParamTypeClasses #-}</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE FlexibleInstances     #-}</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE FlexibleContexts      #-}</span></span></code></pre></div>
<h1 id="currying-and-partial-application">Currying and partial application</h1>
<p>In Haskell, it is idiomatic to specify <em>arguments that are unlikely to change in
between function calls</em> first.</p>
<p>For example, let’s look at the type of <code>M.insertWith</code>:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell literate"><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="kw">qualified</span> <span class="dt">Data.Map</span> <span class="kw">as</span> <span class="dt">M</span></span></code></pre></div>
<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>M.insertWith</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="ot">  ::</span> <span class="dt">Ord</span> k</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>  <span class="ot">=&gt;</span> (a <span class="ot">-&gt;</span> a <span class="ot">-&gt;</span> a)  <span class="co">-- ^ Merge values</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> k              <span class="co">-- ^ Key to insert</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> a              <span class="co">-- ^ Value to insert</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> <span class="dt">M.Map</span> k a      <span class="co">-- ^ Map to insert into</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> <span class="dt">M.Map</span> k a      <span class="co">-- ^ New map</span></span></code></pre></div>
<p>This function allows us to insert an item into a map, or if it’s already there,
merge it with an existing element. When we’re doing something related to
counting items, we can <em>“specialize”</em> this function by <em>partially applying</em> it
to obtain a function which adds a count:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>increaseCount</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="ot">  ::</span> <span class="dt">Ord</span> k</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>  <span class="ot">=&gt;</span> k            <span class="co">-- ^ Key to increment</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> <span class="dt">Int</span>          <span class="co">-- ^ Amount to increment</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> <span class="dt">M.Map</span> k <span class="dt">Int</span>  <span class="co">-- ^ Current count</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> <span class="dt">M.Map</span> k <span class="dt">Int</span>  <span class="co">-- ^ New count</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>increaseCount <span class="ot">=</span> M.insertWith (<span class="op">+</span>)</span></code></pre></div>
<p>And then we can do things like <code>increaseCount "apples" 4 basket</code>. The extremely
succinct definition of <code>increaseCount</code> is only possible because functions in
Haskell are always considered <em>curried</em>: every function takes just one element.</p>
<h1 id="sockets-handles-and-more">Sockets, Handles and more</h1>
<p>However – there is a second idiomatic aspect of argument ordering. For
<em>imperative</em> code, it is common to put the “object” or “handle” first. <code>base</code>
itself is ripe with examples, and packages like <code>network</code> hold many more:</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="co">-- From System.IO</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>hSetBuffering</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="ot">  ::</span> <span class="dt">Handle</span> <span class="ot">-&gt;</span> <span class="dt">BufferMode</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>hGetBuf</span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="ot">  ::</span> <span class="dt">Handle</span> <span class="ot">-&gt;</span> <span class="dt">Ptr</span> a <span class="ot">-&gt;</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> <span class="dt">Int</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a><span class="co">-- From Control.Concurrent.Chan</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>writeChan</span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a><span class="ot">  ::</span> <span class="dt">Chan</span> a <span class="ot">-&gt;</span> a <span class="ot">-&gt;</span> <span class="dt">IO</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="co">-- From Control.Concurrent.MVar</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>modifyMVar</span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a><span class="ot">  ::</span> <span class="dt">MVar</span> a <span class="ot">-&gt;</span> (a <span class="ot">-&gt;</span> <span class="dt">IO</span> (a, b)) <span class="ot">-&gt;</span> <span class="dt">IO</span> b</span></code></pre></div>
<p>This allows us to easily partially apply functions to a specific “object”, which
comes in useful in <code>where</code> clauses:</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">writeSomeStuff ::</span> <span class="dt">Chan</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>writeSomeStuff c <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>  write <span class="st">&quot;Tuca&quot;</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>  write <span class="st">&quot;Bertie&quot;</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>  write <span class="st">&quot;Speckle&quot;</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>  write <span class="ot">=</span> writeChan c</span></code></pre></div>
<p>In addition to that, it allows us to replace the type by a record of functions
– as I went over in the <a href="/posts/2018-03-08-handle-pattern.html">handle pattern explanation</a>.</p>
<h1 id="specializing-top-level-handle-functions">Specializing top-level handle functions</h1>
<p>However, we end up in a bit of a bind when we want to write succinct top-level
definitions, like we did with <code>increaseCount</code>. Imagine we have a <code>Handle</code> to
our database:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode haskell literate"><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">Handle</span> <span class="ot">=</span> <span class="dt">Handle</span></span></code></pre></div>
<p>Some mock utility types:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode haskell literate"><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">Tier</span> <span class="ot">=</span> <span class="dt">Free</span> <span class="op">|</span> <span class="dt">Premium</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">MemberId</span> <span class="ot">=</span> <span class="dt">String</span></span></code></pre></div>
<p>And a top-level function to change a member’s plan:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>changePlan</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="ot">  ::</span> <span class="dt">Handle</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> <span class="dt">Tier</span>       <span class="co">-- ^ New plan</span></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="co">-- ^ Comment</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> <span class="dt">MemberId</span>   <span class="co">-- ^ Member to upgrade</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>changePlan <span class="ot">=</span> <span class="fu">undefined</span></span></code></pre></div>
<p>If we want a specialized version of this, we need to explicitly name and bind
<code>h</code>, which sometimes feels a bit awkward:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="ot">halloweenPromo1 ::</span> <span class="dt">Handle</span> <span class="ot">-&gt;</span> <span class="dt">MemberId</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>halloweenPromo1 h <span class="ot">=</span> changePlan h <span class="dt">Premium</span> <span class="st">&quot;Halloween 2018 promo&quot;</span></span></code></pre></div>
<p>We sometimes would like to be able to write succinct definitions, such as:</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="ot">halloweenPromo2 ::</span> <span class="dt">Handle</span> <span class="ot">-&gt;</span> <span class="dt">MemberId</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>halloweenPromo2 <span class="ot">=</span> specialize changePlan <span class="dt">Premium</span> <span class="st">&quot;Halloween 2018 promo&quot;</span></span></code></pre></div>
<p>But is this possible? And what would <code>specialize</code> look like?</p>
<p>Since this is a feature that relates to the type system, it is probably
unsurprising that, yes, this is possible in Haskell. The concept can be
represented as changing a function <code>f</code> to a function <code>g</code>:</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode haskell literate"><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">Specialize</span> f g <span class="kw">where</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="ot">  specialize ::</span> f <span class="ot">-&gt;</span> g</span></code></pre></div>
<p>Of course, a function can be converted to itself:</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode haskell literate"><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">Specialize</span> (a <span class="ot">-&gt;</span> b) (a <span class="ot">-&gt;</span> b) <span class="kw">where</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>  specialize <span class="ot">=</span> <span class="fu">id</span></span></code></pre></div>
<p>Furthermore, if a <code>Handle</code> (<code>a</code> below) is the first argument, we can skip that
it the converted version and first supply the second argument, namely <code>b</code>. This
leads us to the following definition:</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Specialize</span> (a <span class="ot">-&gt;</span> c) f <span class="ot">=&gt;</span> <span class="dt">Specialize</span> (a <span class="ot">-&gt;</span> b <span class="ot">-&gt;</span> c) (b <span class="ot">-&gt;</span> f) <span class="kw">where</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>  specialize f <span class="ot">=</span> \b <span class="ot">-&gt;</span> specialize (\a <span class="ot">-&gt;</span> f a b)</span></code></pre></div>
<p>This is a somewhat acceptable solution, but it’s not great:</p>
<ul>
<li>type errors from incorrect usage of <code>Specialize</code> will be hard to read</li>
<li><code>AllowAmbiguousInstances</code> may required to defer instance resolution to the
call site of <code>specialize</code></li>
</ul>
<p>Again, not show stoppers, but not pleasant either.</p>
<h1 id="flippin-partial-application">Flippin’ partial application</h1>
<p>The unpleasantness around <code>specialize</code> is mainly caused by the fact that we need
a typeclass to make this work for multiple arguments. Maybe using some sort of
combinator can give us a simpler solution?</p>
<p>Because we’re lazy, let’s see if GHC has any ideas – we’ll use
<a href="https://wiki.haskell.org/GHC/Typed_holes">Typed holes</a> to get a bit more info
rather than doing the work ourselves:</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">halloweenPromo3 ::</span> <span class="dt">Handle</span> <span class="ot">-&gt;</span> <span class="dt">MemberId</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>halloweenPromo3 <span class="ot">=</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>  changePlan <span class="ot">`_`</span> <span class="dt">Premium</span> <span class="ot">`_`</span> <span class="st">&quot;Halloween 2018 promo&quot;</span></span></code></pre></div>
<p>We get an error, and some suggestions:</p>
<pre><code>posts/2019-10-15-flip-specialize.lhs:152:18: error:
 • Found hole:
     _ :: (Handle -&gt; Tier -&gt; String -&gt; MemberId -&gt; IO ()) -&gt; Tier -&gt; t0
   Where: ‘t0’ is an ambiguous type variable
 • In the expression: _
   In the first argument of ‘_’, namely ‘changePlan `_` Premium’
   In the expression:
     changePlan `_` Premium `_` &quot;Halloween 2018 promo&quot;
 • Relevant bindings include
     halloweenPromo3 :: Handle -&gt; MemberId -&gt; IO ()
       (bound at posts/2019-10-15-flip-specialize.lhs:151:3)
   Valid hole fits include
     flip :: forall a b c. (a -&gt; b -&gt; c) -&gt; b -&gt; a -&gt; c
       with flip @Handle @Tier @(String -&gt; MemberId -&gt; IO ())
       (imported from ‘Prelude’ at posts/2019-10-15-flip-specialize.lhs:1:1
        (and originally defined in ‘GHC.Base’))
     seq :: forall a b. a -&gt; b -&gt; b
       with seq @(Handle -&gt; Tier -&gt; String -&gt; MemberId -&gt; IO ()) @Tier
       (imported from ‘Prelude’ at posts/2019-10-15-flip-specialize.lhs:1:1
        (and originally defined in ‘GHC.Prim’))
     const :: forall a b. a -&gt; b -&gt; a
       with const @(Handle -&gt; Tier -&gt; String -&gt; MemberId -&gt; IO ()) @Tier
       (imported from ‘Prelude’ at posts/2019-10-15-flip-specialize.lhs:1:1
        (and originally defined in ‘GHC.Base’))
 ...</code></pre>
<p>Wait a minute! <code>flip</code> looks kind of like what we want: it’s type really
converts a function to another function which “skips” the first argument. Is it
possible that what we were looking for was really just… the basic function
<code>flip</code>?</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a>halloweenPromo4</span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a><span class="ot">  ::</span> <span class="dt">Handle</span> <span class="ot">-&gt;</span> <span class="dt">MemberId</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>halloweenPromo4 <span class="ot">=</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>  changePlan <span class="ot">`flip`</span> <span class="dt">Premium</span> <span class="ot">`flip`</span> <span class="st">&quot;Halloween 2018 promo&quot;</span></span></code></pre></div>
<p>We can make the above pattern a bit cleaner by introducing a new operator:</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="ot">(/$) ::</span> (a <span class="ot">-&gt;</span> b <span class="ot">-&gt;</span> c) <span class="ot">-&gt;</span> (b <span class="ot">-&gt;</span> a <span class="ot">-&gt;</span> c)</span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>(<span class="op">/$</span>) <span class="ot">=</span> <span class="fu">flip</span></span></code></pre></div>
<div class="sourceCode" id="cb19"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="ot">halloweenPromo5 ::</span> <span class="dt">Handle</span> <span class="ot">-&gt;</span> <span class="dt">MemberId</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>halloweenPromo5 <span class="ot">=</span></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>  changePlan <span class="op">/$</span> <span class="dt">Premium</span> <span class="op">/$</span> <span class="st">&quot;Halloween 2018 promo&quot;</span></span></code></pre></div>
<p>Fascinating! I was aware of using <code>flip</code> in this way to skip a single argument
(e.g. <code>foldr (flip M.increaseCount 1)</code>), but, in all the time I’ve been
writing Haskell, I hadn’t realized this chained in a usable and nice way.</p>
<p>In a way, it comes down to reading the type signature of <code>flip</code> in two ways:</p>
<ol type="1">
<li><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="fu">flip</span><span class="ot"> ::</span> (a <span class="ot">-&gt;</span> b <span class="ot">-&gt;</span> c) <span class="ot">-&gt;</span> (b <span class="ot">-&gt;</span> a <span class="ot">-&gt;</span> c)</span></code></pre></div>
<p>Convert a function to another function that has the two first arguments
flipped. This is the way I am used to reading flip – and also what the
name refers to.</p></li>
<li><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="fu">flip</span><span class="ot"> ::</span> (a <span class="ot">-&gt;</span> b <span class="ot">-&gt;</span> c) <span class="ot">-&gt;</span> b <span class="ot">-&gt;</span> (a <span class="ot">-&gt;</span> c)</span></code></pre></div>
<p>Partially apply a function to the <em>second</em> argument. After supplying a
second argument, we can once again supply a second argument, and so on –
yielding an intuitive explanation of the chaining.</p></li>
</ol>
<p>It’s also possible to define sibling operators <code>//$</code>, <code>///$</code>, etc., to “skip”
the first N arguments rather than just the first one in a composable way.</p>
<p><strong>Update</strong>: <a href="https://github.com/danwdart">Dan Dart</a> pointed out to me that the
sibling operators actually exist under the names of <code>-$</code>, <code>--$</code>, etc. in the
<a href="https://hackage.haskell.org/package/composition-extra-2.0.0/docs/Data-Function-Apply.html">composition-extra package</a>.</p>
<h1 id="should-i-use-this-everywhere">Should I use this everywhere?</h1>
<p>… probably not? While it is a mildly interesting trick, unless it becomes a
real pain point for you, I see nothing wrong with just writing:</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="ot">halloweenPromo6 ::</span> <span class="dt">Handle</span> <span class="ot">-&gt;</span> <span class="dt">MemberId</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>halloweenPromo6 h <span class="ot">=</span> changePlan h <span class="dt">Premium</span> <span class="st">&quot;Halloween 2018 promo&quot;</span></span></code></pre></div>]]></description>
    <pubDate>Tue, 15 Oct 2019 00:00:00 UT</pubDate>
    <guid>http://jaspervdj.be/posts/2019-10-15-flip-partial-application.html</guid>
    <dc:creator>Jasper Van der Jeugt</dc:creator>
</item>
<item>
    <title>The ZuriHac registration system</title>
    <link>http://jaspervdj.be/posts/2019-09-03-zureg.html</link>
    <description><![CDATA[<h1 id="introduction">Introduction</h1>
<p>I am one of the organizers of <a href="https://zurihac.info/">ZuriHac</a>, and last year,
we hand-rolled our own registration system for the event in Haskell. This
blogpost explains why we decided to go this route, and we dip our toes into its
design and implementation just a little bit.</p>
<p>I hope that the second part is especially useful to less experienced Haskellers,
since it is a nice example of a small but useful standalone application. In
fact, this was more or less an explicit side-purpose of the project: I worked on
this together with Charles Till since he’s a nice human being and I like
mentoring people in day-to-day practical Haskell code.</p>
<p>In theory, it should also be possible to reuse this system for other events
– not too much of it is ZuriHac specific, and it’s all open source.</p>
<figure>
<img src="/images/2019-09-03-zurihac-lake.jpg" alt="Relaxing at Lake ZuriHac (formerly known as Lake Zurich) after a long day of hacking and talks" />
<figcaption aria-hidden="true">Relaxing at Lake ZuriHac (formerly known as Lake Zurich) after a long day of
hacking and talks</figcaption>
</figure>
<h1 id="why">Why?</h1>
<p>Before 2019, ZuriHac registration worked purely based on Google tools and manual
labor:</p>
<ul>
<li>Google Forms for the registration form</li>
<li>Google Groups to contact registrants</li>
<li>Google Sheets to manage the registrants, waitlist, T-Shirt numbers, …</li>
</ul>
<p>Apart from the fact that the manual labor wasn’t scaling above roughly 300
people, there were a number of practical issues with these tools. The biggest
issue was managing the waiting list and cancellations.</p>
<p>You see, ZuriHac is a free event, which means that the barrier to signing
up for it is (intentionally and with good reason!) extremely low.
Unfortunately, this will always result in a significant amount of people who
sign up for the event, but do not actually attend. We try compensating for that
by overbooking and offering cancellations; but sometimes it turns out to be hard
to get people to cancel as well – especially if it’s hard to reach them.</p>
<p>Google Groups is not great for the purpose we’re using it for: first of all,
attendees actually need to go and accept the invitation to join the group.
Secondly, do you need a Google Account to join? I still don’t know and have
seen conflicting information over the years. Anyway, it’s all a bit ad-hoc and
confusing.</p>
<p>So one of the goals for the new registration system (in addition to reducing
work on our side) was to be able to track participant numbers better and improve
communication. We wanted to work with an explicit confirmation that you’re
attending the event; or with a downloadable ticket so that we could track how
many people downloaded this <a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a>.</p>
<p>I looked into a few options (eventbrite, eventlama, and others…) but none of
these ticked all the boxes: aside from being free (since we have limited
budget). Some features that I wanted were:</p>
<ul>
<li>complete privacy for our attendees</li>
<li>a custom “confirmation” workflow, or just being able to customize the
registration flow in general</li>
<li>and some sort of JSON or CSV export option</li>
</ul>
<p>With these things in mind, I set out to solve this problem the same the way I
usually solve problems: write some Haskell code.</p>
<h1 id="how">How?</h1>
<p>The ZuriHac Registration system (<a href="https://github.com/zfoh/zureg">zureg</a>) is a “serverless” application that
runs on AWS. It was designed to fit almost entirely in the free tier of AWS;
which is why I, for example, picked DynamoDB over a database that’s actually
nice to use. We used Brendan Hay’s excellent and extensive <a href="http://brendanhay.nz/amazonka-comprehensive-haskell-aws-client">amazonka</a>
libraries to talk to AWS.</p>
<p>The total cost of having this running for a year, including during ZuriHac
itself, totaled up to 0.61 Swiss Francs so I would say that worked out
well price wise!</p>
<p>There are two big parts to the application: a fat lambda <a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> function
that provides a number of different endpoints, and a bunch of command line
utilities that talk to the different services directly.</p>
<p><img src="/images/2019-09-03-overview.png" /></p>
<p>All these parts, however, are part of one monolithic codebase which makes it
very easy to share code and ensure all behaviour is consistent – globally
coherent as some would call it. One big “library” that has well-defined
module boundaries and multiple lightweight “executables” is how I like to design
applications in Haskell (and other languages).</p>
<h2 id="building-and-deploying">Building and deploying</h2>
<p>First, I’d like to go into how the project is built and compiled. It’s not
something I’m proud of, but I do think it makes a good cookbook on how to do
things the hard way.</p>
<p>The main hurdle is that we wanted want to run our Haskell code on Lambda, since
this is much cheaper than using an EC2 instance: the server load is very bursty
with long periods (days up to weeks) of complete inactivity.</p>
<p>I wrote a bunch of the zureg code before some Haskell-on-Lambda solutions popped
up, so it is all done from scratch – and it’s surprisingly short. However, if
I were to start a new project, I would probably use one of these frameworks:</p>
<ul>
<li><a href="https://hackage.haskell.org/package/wai-lambda">wai-lambda</a></li>
<li><a href="http://hackage.haskell.org/package/serverless-haskell">serverless-haskell</a></li>
<li><a href="http://hackage.haskell.org/package/aws-lambda-haskell-runtime">aws-lambda-haskell-runtime</a></li>
</ul>
<p>Converting zureg to use of these frameworks is something I woulld like to look
into at some point, if I find the time. The advantage of doing things from
scratch, however, is that it serves the educational purposes of this blogpost
very well!</p>
<p>Our entire serverless framework is currently contained in
<a href="https://github.com/zfoh/zureg/blob/38d2374a/lib/Zureg/Serverless.hs">a single 138-line file</a>.</p>
<p>From a bird’s eye view:</p>
<ol type="1">
<li><p>We define a
<a href="https://github.com/zfoh/zureg/blob/38d2374a/Dockerfile">docker image</a>
that’s based on Amazon Linux – this ensures we’re using the same base
operating system and system libraries as Lambda, so our binary will work
there.</p></li>
<li><p>We compile our code inside a docker container and copy out the resulting
executable to the host.</p></li>
<li><p>We zip this up together with a
<a href="https://github.com/zfoh/zureg/blob/38d2374a/deploy/main.py">python script</a>
that just forwards requests to the Haskell process.</p></li>
<li><p>We upload this zip to S3 and our
<a href="https://github.com/zfoh/zureg/blob/38d2374a/lib/Zureg/Serverless.hs">cloudformation</a>
takes care of setting up the rest of the infrastructure.</p></li>
</ol>
<p>I think this current situation is still pretty manageable since the application
is so small; but porting it to something nicer like Nix is definitely on the
table.</p>
<h2 id="the-database">The database</h2>
<p>The data model is not too complex. We’re using an event sourcing approach: this
means that our source of truth is really an append-only series of events rather
than a traditional row in a database that we update. These events are stored as
plain JSON, and we can define them in pure Haskell:</p>
<p><a href="https://github.com/zfoh/zureg/blob/38d2374a/lib/Zureg/Model.hs">lib/Zureg/Model.hs</a></p>
<p>And then we just have a few handwritten functions in the database module:</p>
<p><a href="https://github.com/zfoh/zureg/blob/38d2374a/lib/Zureg/Database.hs">lib/Zureg/Database.hs</a></p>
<p>This gives us a few things for free; most importantly if something goes wrong we
can go in and check what events led the user to get into this invalid state.</p>
<p>This code is backed by the <a href="https://hackage.haskell.org/package/eventful-core">eventful</a> and <a href="https://hackage.haskell.org/package/eventful-dynamodb">eventful-dynamodb</a> libraries, in
addition to some custom queries.</p>
<h2 id="the-lambda">The lambda</h2>
<p>While our admins can interact with the system using the CLI tooling,
registrants interact with the system using the webapp. The web application is
powered by a fat
<a href="https://github.com/zfoh/zureg/blob/38d2374a/lib/Zureg/Main/Lambda.hs">lambda</a>.</p>
<p>Using this web app, registrants can do a few things:</p>
<ul>
<li>Register for the event (powered by a huge web 1.0 form using
<a href="https://hackage.haskell.org/package/digestive-functors">digestive-functors</a>);</li>
<li>View their ticket (including a QR code generated by
<a href="https://hackage.haskell.org/package/qrcode">qrcode</a>;</li>
<li>Confirm their registration;</li>
<li>Cancel their registration.</li>
</ul>
<p>In addition to these routes used by participants, there’s a route used for
ticket scans – which we’ll talk about next.</p>
<h2 id="the-scanning">The scanning</h2>
<p>Now that we have participant tickets, we need some way to process them at the
event itself.</p>
<p><a href="https://github.com/zfoh/zureg/blob/38d2374a/static/scanner.js">scanner.js</a> is a
small JavaScript tool that does this for us. It uses the device’s webcam to
scan QR codes – which is nice because this means we can use either phones,
tablets or a laptop to scan tickets at the event, the device just needs a modern
browser version. It’s built on top of <a href="https://github.com/cozmo/jsQR">jsQR</a>.</p>
<p>The scanner intentionally doesn’t do much processing – it just displays a
full-screen video of the webcam and searches for a QR code using an external
library. Once we get a hit for a QR code, we poll the lambda again to retrieve
some information (participant name, T-Shirt size) and overlay that on top of the
video.</p>
<figure>
<img src="/images/2019-09-03-scanner.png" alt="Testing the scanner" />
<figcaption aria-hidden="true">Testing the scanner</figcaption>
</figure>
<p>This is useful because now the people working at the registration desk can see,
as demonstrated in the image above, that I registered too late and therefore
should only pick up a T-Shirt on the second day.</p>
<h1 id="what-is-next">What is next?</h1>
<p>There is a lot of room for improvement, but the fact that it had zero technical
issues during registration or the event makes me very happy. Off the top of my
head, here are some TODOs for next years:</p>
<ul>
<li>We should have a CRON-style Lambda that handles the waiting list automation
even further.</li>
<li>It should be easier for attendees to update their information.</li>
</ul>
<p>Other than that, there are some non-functional TODOs:</p>
<ul>
<li>Can we make the build/deploy a bit easier?</li>
<li>Should we port zureg to use one of the existing Haskell-on-Lambda
frameworks?</li>
<li>I’m currently using
<a href="https://github.com/zfoh/zureg/blob/38d2374a/lib/Zureg/Views.hs#L125-L133">somewhat fancy</a>
image scaling to get a sharp scaled up QR image, but this does not work if
someone saves it on their phone – we should just do the scaling on the
backend.</li>
</ul>
<p>Any contributions in these areas are of course welcome!</p>
<p>Lastly, there’s the question of whether or not it makes sense for other
events to use this. I discussed this briefly with
<a href="https://github.com/fmthoma">Franz Thoma</a>, one of the organizers of
<a href="https://munihac.de/2019.html">Munihac</a>, who expressed similar gripes about
evenbrite.</p>
<p>As it currently stands, zureg is not an off-the-shelf solution and requires some
customization for your event – meaning it only really makes sense for Haskell
events. On the other hand, there are a few people who prefer doing this over
mucking around in settings dashboard that are hugely complicated but still do
not provide the necessary customization.</p>
<section id="footnotes" class="footnotes footnotes-end-of-document" role="doc-endnotes">
<hr />
<ol>
<li id="fn1"><p>I realize this is a bit creepy, and fortunately it turned out
not to be necessary since we could do the custom confirmation flow.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2"><p>In serverless terminology, it seems to common to refer to lambdas
that deal with more than one specific endpoint or purpose as “fat lambdas”.
I think this distracts from the issue a bit, since it’s more important to
focus on how the code works and whether or not you can re-use it rather than
how it is deployed – but coming from a functional programming perspective I
very much enjoy the sound of “fat lambda”.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>]]></description>
    <pubDate>Tue, 03 Sep 2019 00:00:00 UT</pubDate>
    <guid>http://jaspervdj.be/posts/2019-09-03-zureg.html</guid>
    <dc:creator>Jasper Van der Jeugt</dc:creator>
</item>

    </channel>
</rss>
